前言
这是一个 SQL 注入笔记,其中包含了很多常用的payload,涵盖了 5 种最流行的数据库及其衍生产品(MySQL、PostgreSQL、MSSQL/SQL Server、Oracle、SQLite)。
某些payload包含占位符,这些占位符在使用前需要被替换为具体的值。占位符以<>表示,并且使用大写字母,例如。替换时需替换整个占位符(包括<>)。
避免使用 OR(OR 1=1)
除了打 CTF之外,其他情况都要避免使用涉及 or 表达式的注入(例如 ' or 1=1 --),除非只能用or。
原因:
-
登录绕过不稳定
"OR 1=1" 在某些情况下可以绕过登录验证,但其效果并不稳定。通常是期望 SQL 查询返回一行匹配的数据(例如用户名和密码都正确)。如果使用 "OR 1=1",查询可能会返回多行数据(例如整个user表),这可能导致目标拒绝登录请求。例如,查询 SELECT * FROM users WHERE username = '' OR 1=1 AND password = '' 会返回所有用户,但如果目标只在查询返回单行时才允许登录,这种方法就会失效。相比之下,使用其他方法(如注释掉密码检查部分并配合有效用户名)可能更可靠,即 "OR 1=1" 的通用性不足。
-
可能导致数据库崩溃
在某些场景(如搜索功能)中注入 "OR 1=1" 会导致数据库返回表中的所有行。如果数据库表非常大,这种操作可能会引发性能问题,甚至导致数据库过载或系统崩溃。
-
数据操作风险高
当 "OR 1=1" 用于 UPDATE 或 DELETE 语句时,可能会意外修改或删除大量数据。例如,在重置密码的场景中,注入 "OR 1=1" 可能会导致所有用户的密码都被更改,而不仅仅是目标用户。这种操作可能引发数据丢失或损坏,风险极高。
安全的 or payload
但实际上也存在安全的 or 注入payload,这些 payload 可以在没有查询参数的情况下使用。
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
常用的测试方法
以下是一个简单通用的方法,用于发现基本的 SQL 注入漏洞,通过逐步操作来检测是否存在 SQL 注入。
第一步:尝试使用单引号让原有的 SQL 语句报错
首先,我们需要在某个有效的输入值中注入单引号(')或双引号("),以尝试让目标本身的sql语句报错。例如:
-
假设有一个搜索功能,搜索关键词 fuck 返回 23 个结果。 -
在搜索关键词后附加单引号,变为 fuck',然后提交。 -
如果结果变为 0 个(或者直接报错),说明 SQL 语句可能因为我们插入了单引号而发生改变。注意:这也可能是因为 fuck' 本身是一个无效的搜索词,但后续步骤可以帮助我们确认。
第二步:尝试修复目标的sql语句检查是否恢复原始响应
可以尝试用以下方法替换注入的单引号,看看是否能恢复到原始响应(即 23 个结果)。依次尝试以下替换:
-
将 fuck' 替换为 fuck' '(单引号后加空格和另一个单引号) -
将 fuck' 替换为 fuck'||' -
将 fuck' 替换为 fuck'+' -
将 fuck' 替换为 fuck' AND '1'='1 -
将 fuck' 替换为 fuck' -- -
如果某个替换后的搜索词(如 fuck' ')再次返回 23 个结果,说明原始响应被恢复了,就表示这个搜索功能很可能存在 SQL 注入。
第三步:处理整数值的情况
如果以上方法都无法恢复原始响应,可能是因为我们注入的字段是一个整数值(而不是字符串)。在这种情况下,尝试以下方法:
-
将 fuck' 替换为 fuck -- - -
将 fuck' 替换为 fuck AND 1=1 -
将 fuck' 替换为 fuck AND 1=1 -- -
同样,如果某个替换后的搜索词恢复了原始响应(23 个结果),则说明可能存在 SQL 注入。
第四步:确认 SQL 注入漏洞
为了进一步确认是否存在 SQL 注入,可以尝试以下方法:
方法 1:尝试 UNION 方法
-
构造一个 UNION 注入 payload,例如 fuck' UNION SELECT 1,2,3 -- -。 -
如果返回结果异常(例如有额外的数据或有明显的数据库报错),则可以确定存在sql注入。
方法 2:注入布尔值 payload
-
构造两个布尔值 payload: -
fuck' AND '1'='1(应该返回原始响应,即 23 个结果) -
fuck' AND '1'='0(应该返回 0 个结果)
-
-
如果结果符合预期(第一个 payload 返回 23 个结果,第二个返回 0 个结果),则基本上可以确认存在 SQL 注入漏洞。
识别数据库
一旦通过上面的方法发现了sql注入,可以通过下面这些payload来识别到底是什么数据库。
|
|
|
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
注释
注释语法可用于在 SQL 语句中添加注释,可以用于注释位于注入语句后的那些原本的内容,以及绕过某些过滤。需要注意"--"注释需要在"--"后加上空格才有效,而 /*comment*/
是行内注释。
|
/*comment*/ |
---|---|
|
/*comment*/ |
|
/*comment*/ |
|
/*comment*/ |
|
/*comment*/ |
字符串连接
这些函数/操作符可用于将两个或多个字符串连接在一起。
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
子字符串
这些函数可以用来选择一个字符串的子字符串。START 值应设置为 1(而不是 0),以便从第一个字符开始提取子字符串。还包括无逗号的版本,用于绕过某些 WAF(Web 应用防火墙)或过滤机制。
|
|
|
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
长度
这些函数以字节或字符为单位计算字符串的长度(由于 Unicode 的存在,某些字符可以有多个字节)。
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
分组连接
这些函数将多行结果中的值连接成一个单独的字符串。用你希望分隔每个值的字符串或字符(例如逗号)替换。
什么是 GROUP_CONCAT?
-
GROUP_CONCAT 是一个聚合函数,主要在 MySQL 和 MariaDB 中使用(其他数据库如 PostgreSQL 有类似功能,例如 STRING_AGG)。 -
它的作用是将一组行中的值(通常来自同一分组)连接成一个单一的字符串。 -
常用于 GROUP BY 查询中,将多行数据合并为一行。
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
将字符转换为整数用于进行比较
这对sql盲注很有用,可以确定字符所在的范围。注意,MySQL 和 Oracle 的函数输出的是十六进制数,而其他数据库输出的是十进制数。
|
|
|
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
限制与偏移查询
用于限制查询结果返回特定行数以及偏移起始行的语法,包括不使用逗号的语法,以便绕过某些 WAF(Web 应用防火墙)或过滤机制。
|
将查询结果限制为 1 行 | 限制为 1 行,从第 5 行开始 |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
数据库版本
提供数据库版本信息的函数和操作符。
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
数据库列表
查询数据库列表
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
数据库的表
查询指定数据库中的所有表
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
表中的列
查询指定数据库中的表的所有列
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
布尔判断检测
这些payload会在SQL查询的时候引发报错,前提是1=1的条件为真,将1=1替换为你想要测试的条件;如果错误反馈到响应中(例如500内部服务器错误),那么该条件就是成立的。
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
报错检测
这些payload会导致数据库错误,并在错误中返回数据库的版本信息。
MySQL
|
---|
|
|
|
|
|
|
PostgreSQL
|
---|
|
|
|
|
MSSQL
|
---|
|
|
|
Oracle
|
---|
AND 1337=(SELECT UPPER(XMLType(CHR(60)||CHR(58)||'~'||(REPLACE(REPLACE(REPLACE(REPLACE((SELECT banner FROM v$version),' ','_'),'$','(DOLLAR)'),'@','(AT)'),'#','(HASH)'))||'~'||CHR(62))) FROM DUAL) -- - |
|
|
|
延时注入
简单的延时注入
请注意,这些payload本质上是有危险的,因为sleep函数可能会执行多次,它们将导致数据库在查询的每一行中休眠 10 秒。
只有在确定注入的查询只影响一条记录时,才可使用。
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
复杂一些的延时注入
这些payload是相对安全的,只能休眠一次,将1=1替换为要测试的语句即可,如果延迟了十秒,则为真
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
堆叠注入
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
下列payload中,如果 1=1
成立,这些payload就会导致 10 秒的延迟。将 1=1
替换为你想要测试的条件;如果出现 10 秒的延迟,就说明该条件成立。
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
读取文件
这些函数可以读取本地文件的内容。另外,只有在可以进行堆叠注入的情况下,才能使用 Oracle 方法。SQLite 的 readfile 函数并非其核心函数。
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
写入文件
这些语句可以将内容写入本地文件。只有在可以进行堆叠注入的情况下,才能使用 PostgreSQL、MSSQL 和 Oracle 的方法。MSSQL 需要启用 “Ole Automation Procedures”。
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
执行命令
这些语句执行本地操作系统命令。只有在可以进行堆叠注入的情况下,才能使用 PostgreSQL、MSSQL 和第二种 Oracle 方法。第一种 Oracle 方法需要使用 OS_Command 包。
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
原文始发于微信公众号(棉花糖fans):建议收藏:SQL注入基础与各个数据库中的常用命令
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论