2016-SWPU-CTF 一道web题解
题目首页是这样
尝试admin admin登录
把cookie值进行base64解码,得到O:5:"login":3:{s:3:"uid";s:1:"2";s:4:"name";s:5:"admin";s:4:"pass";s:32:"21232f297a57a5a743894a0e4a801fc3";}
可以看到经过了序列化
这到下面是没法做了,我有源码可以直接审计。swpu设置了bak泄露,也就相当于审计了。
在index.php文件中
`if(isset($_COOKIE['user'])){
$login = @unserialize(base64_decode($_COOKIE['user']));
if(!empty($login->pass)){
$status = $login->check_login();
if($status == 1){
$_SESSION['login'] = 1;
var_dump("login by cookie!!!");
}
}
}`
通过获取user的cookie值,经过base64解密,再反序列化。在反序列化的时候正常情况下会先调用__wakeup()函数,wakeup函数在function.php中
//反序列化时检查数据
public function __wakeup(){
$this->name = help::addslashes_deep($this->name);
$this->pass = help::addslashes_deep($this->pass);
}
跟addslshes_deep函数,发现过滤的严格,无法注入。
再调用__destruct()函数,
//预防cookie某些破坏导致登陆失败
public function __destruct(){
$this->check_login();
}
发现会调用check_login函数,跟一下发现里面也存在过滤,
public function check_login(){
mysql_conn();
$sqls = "select * from phpinfoadmin where username='$this->name'";
$sqls = help::CheckSql($sqls);
$re = mysql_query($sqls);
$results = @mysql_fetch_array($re);
//echo $sqls . $results['passwd'];
mysql_close();
if (!empty($results))
{
if($results['passwd'] == $this->pass)
{
return 1;
}
else
{
return 0;
}
}
}
不过核心是80sec的过滤,是可以绕过的
$sqls = "select * from phpinfoadmin where username='$this->name'";
$this->name是反序列化后解出的数据,完全可控,可以注入
所以能想到的是绕过__wakeup()函数的执行,直接执行__destruct()函数。这就用到了前一段时间爆出的SugarCRM v6.5.23 PHP反序列化对象注入漏洞分析其中的核心点就是:当PHP当序列化字符串中表示对象属性数的值大于真实的属性个数时会跳过__wakeup()的执行
O:5:"login":3:{s:3:"uid";s:1:"2";s:4:"name";s:5:"admin";s:4:"pass";s:32:"21232f297a57a5a743894a0e4a801fc3";}
上面的数据是正常的,反序列化时经过wakeup函数和destruct函数处理
O:5:"login":4:{s:3:"uid";s:1:"2";s:4:"name";s:5:"admin";s:4:"pass";s:32:"21232f297a57a5a743894a0e4a801fc3";}
该数据的真实的属性个数是3个,uid,name,pass。表示对象属性数被我改成了四个,所以在反序列化的时候就不执行wakeup函数了,直接执行了destruct函数。把上面的数据进行base64加密,然后把cookie的user值改为加密后的数据
就触发了上面说过的 $sqls = "select * from phpinfoadmin where username='$this->name'";
剩下的就是绕过80sec进行注入了