
# 常用注释
#: 注释#至行尾--: 注释--至行尾(2 个-跟上空格或一个其他字符)/**/: 注释/*至*/之间的字符
# 寻找及确认 SQL 注入
'和"![https://i.bakar.moe/assets/img/2023/7/d684c736f0cb1e8d173a373a68bb6bad.png]()
and和or![https://i.bakar.moe/assets/img/2023/7/929216f19b55db014a95069ef3da2a58.png]()
# MySQL 基本函数
@@version: 数据库版本@@basedir: 数据库路径mid(str, pos, len)和substring(str, pos, len): 对str从pos位置开始截取len个字符concat(str1, str2): 连接两个字符串database(): 当前数据库名length(str): 字符串长度user(): 当前用户名sleep(second): 睡眠second秒group_concat(): 将一列值连接成字符串limit offset, count: 显示从offset开始的count个结果
# 基于注入点值的属性
字符型需要闭合引号,数字型不需要
# 基于注入点的位置
注入点除了 GET 请求的参数及 POST 请求的 body 之外,也可能存在于 Cookie 或 Headers 中
# 基于注入的程度和顺序
- 一阶注入:注入语句直接对 Web 产生了影响
- 二阶注入:注入语句无法直接对 Web 产生影响,需要通过其他辅助间接产生危害
# 二阶注入示例
添加一个 admin'# 用户,登录该用户后修改密码,实际上能够修改 admin 的密码
修改该用户密码时的 SQL 语句如下
UPDATE users SET passwd="new_password" WHERE username='admin'#' AND password='old_password' |
实际上 # 后的字符都被注释了,相当于执行
UPDATE users SET passwd="new_password" WHERE username='admin' |
# 基于从服务器返回的响应
如果 Web 应用存在 SQL 注入,那么输入的 payload 总会导致响应上与正常的有所区别,可能体现在内容、长度、响应时间等方面
# 有回显
# 联合查询
UNION 关键字可以合并多条 SELECT 语句的查询结果,需要满足以下两个条件
- 查询语句的返回列数必须相同
- 查询语句返回的每列的数据类型必须相同

# 报错注入
页面会返回报错信息,可以将需要查询的结果放在报错信息里回显出来

# XPath 报错注入
涉及函数:
updatexml(XML_document, XPath_string, new_value): 更新 xmlextractvalue(XML_document, XPath_string): 查询 xml
XML_document 是 xml 文档对象名, XPath_string 是 XPath 路径, new_value 是需要替换的字符串
注入语句:
update(1, concat(0x7e, (select 查询语句), 0x7e), 1)extractvalue(1, concat(0x7e, (select 查询语句), 0x7e))
# floor + group by 报错注入
SELECT count(*), (concat(floor(rand(0)*2), '@', (SELECT version())))x FROM users GROUP BY x |
floor(x) 返回小于等于 x 的最大整数
group by 语句会遍历某一列的值( group by 的 group_key ),将结果保存在临时表中:
- 当读取到某行的值不在临时表中,会插入一条数据
- 当读取到某行的值在临时表中,会更新临时表中的对应数据
group by floor(rand(0)*2) 中,由于 group_key 是随机数, group by 在检测临时表是否存在某个值和将值插入临时表的时候会分别执行 group_key ,因此有可能临时表中存在 1 , group by 检测时计算为 0 ,而插入时计算为 1 的情况,最终导致插入主键重复的行而报错
# exp() 溢出报错注入
MySQL > 5.5.5 中,大于 709 的值传给 exp() 函数会引起溢出错误


# 堆叠注入
利用 ; 拼接多条 sql 语句

# 无回显
# 布尔盲注
页面的内容会改变,但不包含有用信息
涉及到的函数:
length(): 字符串长度mid(),substring(): 取子字符串left(),right(): 取字符串的左 / 右n个字符ord(),ascii(): 取字符 ASCII 值
# 延时盲注
不关注页面的返回内容,而关注页面的响应时间差
涉及到的函数:
sleep(): 睡眠指定秒数benchmark(count, expr): 执行exprcount次if(expr1, expr2, expr3): 相当于三元运算符,expr1为真返回expr2,为假返回expr3WHEN condition THEN result1 ELSE result2: 批量的三元运算符,如SELECT case WHEN age=19 THEN 'yes' ELSE 'no' FROM usersA regexp() B: 正则表达式B是否可以匹配A

# 特殊业务场景
# INSERT/UPDATE/DELETE 注入
注册、修改、删除信息时输入单引号返回异常信息,可能可以被利用




# LIKE 注入
% 闭合
# ORDER BY 注入
# 基于 IF 语句(数字型)
在知道列名 password 的情况下,使用 if(expr, id, password)

expr 为 True 按照 id 排序,为 False 按照 password 排序
不知道列名的情况下,使用类似 if(expr, 1, (SELECT id FROM information_schema.tables))
expr 为 True 时返回正常页面,为 False 时会报错
# 基于 rand() 盲注(数字型)
order by rand() ,排序结果可能不相同
# HTTP 参数污染
给同一个参数赋多个值,可能导致 Web 应用以意外的方式去解释这个参数
不同的程序组件对这类问题的处理方法也各不相同
# SQL 注入的读写
mysql.user 表中包含了数据库的用户信息,其中 file_priv 表示了用户是否可以读写外部文件
此外,全局变量 secure_file_priv 也对文件读写进行了限制:
- 值为
null表示不允许导入导出 - 值为
/tmp表示只能在/tmp下进行导入导出 - 没有具体值则表示导入导出不受限制
通过 load_file(path) 函数读取文件, path 是绝对路径


