前几天在逛github时发现有个开源cms出了个sql注入的漏洞,虽然时几个月前被提出来的,最新版也已经被修复,但是网上没有详细的分析过程,所以这里对这个漏洞进行分析并给出其他几种payload
前几天在逛github时发现有个开源cms出了个sql注入的漏洞,虽然时几个月前被提出来的,最新版也已经被修复,但是网上没有详细的分析过程,所以这里对这个漏洞进行分析并给出其他几种payload
0x00 漏洞复现
POST /api.php?c=call&f=index HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1/
Sec-Fetch-Dest: script
Sec-Fetch-Mode: no-cors
Sec-Fetch-Site: same-origin
Connection: close
Cookie: PHPSESSION=bd34va2vksdhvqr8t1sll4lva7; XDEBUG_SESSION=PHPSTORM
Content-Type: application/x-www-form-urlencoded
Content-Length: 67
data={"m_picplayer":{"_alias":"abc","fields_need":"CASE 1 WHEN (substr((select database()) from 1 for 1)=0x70) THEN sleep(5) ELSE 1 END"}}
0x01路由分析
网站有三个入口(前端,接口,后台)都是从framework/_init_phpok.php
这里执行,进行初始化处理
我们以action_api
为例,$ctrl
和$func
分别通过get请求中的c
和f
获取,默认值为index
然后在_action_phpok4
中调用相关的控制器和方法,例如访问http://127.0.0.1/api.php?c=call&f=index
就会调用frameworkapicall_control.php
中的index_f
方法
0x02 漏洞分析
我们首先来先看framework/api/call_control.php
中的index_f
方法,
对应的url请求路径为/api.php?c=call&f=index
这里首先判断传入的值是否以{
为首,如果是就将其转换为json格式
$call_all
然后通过$this->model('call')->all($this->site['id'],'identifier')
然后通过取得站点下的全部数据,并对数据进行格式化
在all()
方法中会获取数据库中的内容,并将ext
中的数据反序列化
下图时数据库存放数据的格式
所以最终$call_all
获取到的值如下图,其键为数据库中identifier
列中的数据,值为ext
反序列化后的数据
接着会遍历data中的数据
然后再下面的if($call_all && $call_all[$key] && $call_all[$key]['is_api'])
判断$call_all[$key]['is_api']
为真,那么就只有下面几个符合条件
并将data中的键和值传递给framework/phpok_tpl_helper.php
中的phpok
方法,
然后继续跟踪,这里又继续调用了framework/phpok_call.php
中的phpok
方法,下图是phpok
方法代码片段
在第一个红框中获取到的func
就是获取到内容的type_id
,即到时候调用的函数名为_arclist
在第二个红框里注意默认开启了缓存,如果两次请求的数据一样则会直接返回缓存的数据,所以每次构建payload的时候需要改变数据
最后调用_arclist
方法,并传递参数
其中在_arclist
方法中调用_arc_condition
方法,我们直接来看这个函数
这里判断是否存在fields_need
。若存在,通过,
进行分割,由于payload中没有逗号,所以直接拼接到sql语句中。
然后会将$condition
参数传入到arc_count
中方法,从截图中可以看出已经将payload带入。
在arc_count
方法中拼接sql语句进行执行
0x03 梅开二度
理解了漏洞的利用方式,我可以寻找是否还有别的地方也存在漏洞,
从调用函数执行的地方可以看到程序是从数据库中获取方法名然后动态调用的,所以我们的思路就是寻找可以动态调用的方法,在数据库中寻找is_api
为1的数据,然后去通过type_id
来查看这些方法中是否存在对其他参数过滤不严的地方。
例如我们可以寻找_catelist
方法中
在这里发现并没有对$rs['cateid']
进行任何过滤,如果存在该变量就直接将其放入模型中,这里再来看看cate_all
是如何执行的:
直接将拼接到sql语句中的orderby后然后执行
既然调用的是_catelist
方法,对应的data的键就是catelist
用以下payload可以证明我们的猜想:
data={"catelist":{"_alias":"abc","orderby":"if(2=1,1,sleep(0.5))"}}
测试的时候发现延迟的时间并不是sleep(0.5)中的0.5秒,而是大于0.5秒,因为这里的延迟的时间和所查询的数据的条数是成倍数关系的
0x04 修复方式
来看一下官方的修复方式
这里对data传过来的值首先将他转化为json格式后使用safe_text
方式进行过滤,同时在safe_text
中新增了对(
,)
,0x
进行过滤。
本公众号云息信安所提供的信息以及工具仅供安全测试人员用于授权测试,禁止用于未授权测试,请勿非法使用!!!造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号云息信安及作者不为此承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢!
原文始发于微信公众号(云息信安):某CMS sql注入梅开二度
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论