【php反序列化字符串逃逸】
反序列化字符串逃逸原理
原理
就会报错
可以反序列化类中不存在的元素
<?php
class user{public $name;public $age;
}
$b='O:4:"user":3:{s:4:"name";s:3:"bob";s:3:"age";s:2:"10";s:6:"gender";s:3:"boy";}';
print_r(unserialize($b));
得到的结果,多了一个boy
user Object
([name] => bob[age] => 10[gender] => boy
)
PHP 在反序列化时,底层代码是以 ;
作为字段的分隔,以 }
作为结尾(字符串除外),并且是根据长度判断内容的
O:4:"user":3:{s:4:"name";s:3:"bob";s:3:"age";s:2:"10";s:6:"gender";s:3:"boy";}s:6:"gender";s:4:"boy";
这是不会报错的,但是也不会进行反序列化。结果依然不变。
}
后面的序列化内容不影响
我们在结尾加任何字符都是不会报错的,通过这两个原理看到下面的demo:
filter就是把序列化后的一个b替换成两个a ,这里会输出原始序列化和替换后的序列化,最后是反序列化,输出如下:
经过了filter的处理 因为ydsaa长度为5不为4,所以反序列化的时候报错了,之前我们知道php是通过;
和}
来识别序列化长度的,只需要把username后面添加;} 让它提前闭合
再把变量名的数量更改了,因为我们上图的变量名长度只有3,但实际传入了18,得补足变量名长度就能成功把后面的age变量给修改了
练习一
发现了www.zip源码,主要的问题出在login.php
login.php
<?phpinclude 'function.php';
$config = include_once 'config.php';$username = $_POST['username'];
$password = $_POST['password'];
$sql = $_POST['sql'];$login = new