搭建 SqliLabs 这件事,看起来就是"下载—解压—丢进网站根目录—打开浏览器"这四步,但真正动过手的人都知道,能一次跑通的概率大概跟抛硬币差不多。我第一次搭的时候折腾了整整一个下午:安装页面要么白屏,要么卡在第一步不动,要么直接提示数据库连不上。后来带着别人一起搭,发现大家踩的坑高度重合,基本都集中在 PHP 版本、数据库配置、字符集和安装脚本这几个地方。SqliLabs 说白了就是一套用 PHP 写的、故意留了练习缺口的环境,专门给学 Web 安全的人用来在本地模拟各种注入场景,不联网、不影响别人、搞坏了删掉重来就行。它适合刚入门安全方向、想找个安全沙箱练手的人,也适合需要临时搭一套环境做验证的老手。下面我就把搭建过程中真正会卡住人的点,按出现频率从高到低捋一遍,尽量让你少走我当年走过的弯路。
1. 先把 SqliLabs 的出身弄明白,才知道它为什么这么挑环境
很多人搭不起来,根源其实在一开始就没搞清楚这东西是个什么年代的产物。你把它当成一个普通的现代 Web 应用去部署,那自然会处处碰壁。理解它的"出身",后面所有报错就都能串起来。
1.1 它本质上是一套写死在老版本 PHP 上的代码
SqliLabs 最早是十多年前的产物,那会儿国内用 PHP 5.2、5.3 的还一大堆,所以它的源码里大量使用了mysql_connect、mysql_query、mysql_fetch_array这一批函数。这批函数有个特点:它们在 PHP 5.x 时代是主力,但到了 PHP 7.0 被官方直接删掉了,不是"废弃"而是"移除"——也就是说只要你用 PHP 7 以上去跑老版本的 SqliLabs,连数据库那一步就会直接抛致命错误。
这就解释了一个非常典型的现象:同一份代码,放在同事的电脑上能跑,放在你的电脑上就白屏。不是代码有问题,也不是你装错了,纯粹是两边 PHP 版本不一样。我当年就是被这个坑到怀疑人生的——本地环境装的是最新版集成工具,默认 PHP 8 起步,结果mysql_*函数一律找不到。
1.2 新版环境"越先进越跑不动"的反直觉结论
安全圈里有个挺有意思的现象:越是刚装好的新环境,越跑不动这些经典靶场。因为 PHP 8 之后不仅移除了mysql_*,还收紧了一大堆语法规则,比如未定义变量会直接报 Warning、动态属性被弃用、字符串与数字比较规则也变了。SqliLabs 的代码里到处是"能跑就行"的写法,在严格模式下自然一路飘红。
所以正确的思路不是"想办法让新 PHP 兼容它",而是"给它配一个它出生的年代的环境"。这跟你在老电脑上跑 DOS 游戏是一个道理——你不太可能去改游戏,而是搞个模拟器。SqliLabs 的"模拟器"就是 PHP 5.4 到 5.6 这一段区间,绝大多数版本在 5.4/5.6 上都跑得非常稳。理解这一点,后面选环境、切版本就有了主心骨,不会被各种花里胡哨的报错牵着鼻子走。
2. PHP 版本是第一道硬门槛,绕不过去
如果说搭建 SqliLabs 只有一个必须解决的问题,那一定是 PHP 版本。这道坎你迈不过去,后面数据库、字符集、权限的事情根本轮不到你操心。下面把报错、原因和两种主流解法讲透。
2.1 典型报错长什么样,它的真实含义是什么
当你用 PHP 7/8 去跑老版 SqliLabs 时,浏览器里通常会看到类似这样的字:
Fatal error: Uncaught Error: Call to undefined function mysql_connect() in ...或者:
Deprecated: The each() function is deprecated ...再或者干脆一片空白,什么都不显示。前两条很直白——它在告诉你"我要调用的这个函数在这个 PHP 里不存在"。第三条白屏最坑,因为默认情况下 PHP 的错误是不显示的,你得先把php.ini里的display_errors打开,错误才会浮到页面上来。我的习惯是搭这类环境时第一件事就把报错打开:
display_errors = On error_reporting = E_ALL改完记得重启 Web 服务,不然php.ini不会重新加载。这一步看着简单,但能帮你省掉大量"盲猜"的时间——有报错和没报错,排查效率差十倍。
2.2 降级 PHP 还是换一套代码,我的选择逻辑
面对版本不兼容,你面前有两条路:
- 第一条是降级 PHP 环境,装一个 PHP 5.4/5.6 的运行时,让原始代码原封不动地跑起来。
- 第二条是换一套已经适配新版 PHP 的代码,社区里有不少人在原版基础上把
mysql_*改成了mysqli或 PDO 的版本。
我个人的选择是:优先降级环境,而不是换代码。理由很实在——你学这套靶场的目的是理解注入原理,而不是给自己新开一个"调代码"的坑。换来的适配版代码谁改的、改得全不全、有没有顺手把某些行为改掉,你都不清楚,练到某一关时行为跟教程对不上,你反而会怀疑自己学错了。而用 PHP 5.4/5.6 跑原版,行为跟绝大多数公开资料完全一致,出了问题也容易对上号。
当然,如果你手上环境受限、实在装不了老 PHP,那就退而求其次用适配版,但要有个心理准备:个别关卡的响应可能和网上描述略有出入,遇到时先别怀疑自己,先对比代码。
2.3 集成环境怎么配:几个真正管用的操作
大多数人是通过集成环境(就是把 Apache、PHP、MySQL 打包在一起的那种工具)来搭的,这确实是最省事的路子。关键在于选一个支持自由切换 PHP 版本的集成环境。切换的步骤通常是:关掉当前服务,在版本列表里选到 5.4 或 5.6,启动,然后把 SqliLabs 的整个文件夹放进网站根目录(一般是WWW或www目录)。
这里有几个我踩过的细节:
- 切换 PHP 后一定要重启服务,不然 Apache 加载的还是旧的 PHP 模块。
- 确认网站根目录到底是哪个,有些集成环境默认站点目录和软件安装目录不是同一个,放错地方就是 404。
- 访问地址别写错大小写,比如文件夹叫
sqli-labs,你在浏览器里就老老实实写sqli-labs,别写成SqliLabs。Windows 下可能不敏感,但一旦你迁到类 Unix 环境,大小写就是致命的。
把这一层搞定,你访问首页就能看到那个经典的欢迎界面和一行行的关卡链接了。看到界面,说明最硬的坎已经过了。
3. 数据库连接:账号、密码、端口三件套对不上就卡死
PHP 版本解决之后,下一个高频翻车点就是数据库连接。SqliLabs 的安装脚本需要连上 MySQL 去建库建表,只要这个连接对不上,安装就会卡在第一步反复报错。这块看着简单,但细节全在配置文件的默认值上。
3.1 默认凭据和你的实际环境对不上
SqliLabs 的数据库连接信息集中写在一个配置文件里(通常在sql-connections目录下,文件名带db-creds字样)。里面长这样:
$dbuser = 'root'; $dbpass = 'root'; $dbname = 'security';问题就出在这儿:它默认用户名和密码都是 root/root。而很多集成环境里,MySQL 的 root 密码是空的,或者被设成了别的字符串。你的环境是空密码,脚本却拿着root当密码去连,自然连不上。
解决方式很直接——把配置文件里的用户名密码改成你环境里真实的值。如果是空密码,就把$dbpass留空:
$dbuser = 'root'; $dbpass = '';这一步几乎是人人都要改一次的。我建议你搭之前先确认两件事:一是 MySQL 服务确实启动了(有些集成环境默认不开),二是你的 root 密码到底是什么。拿不准就用命令行工具连一下,能连上再回来改配置。
3.2 MySQL 端口和"连接方式"的隐藏坑
除了账号密码,还有两个不显眼但很要命的地方。第一是端口。默认 MySQL 用 3306,但如果你的机器上已经装过一个独立的 MySQL,或者之前装过别的数据库占用了 3306,集成环境里的 MySQL 可能被自动换到了 3307、3308 之类的端口。这种情况下,PHP 脚本仍然去连 3306,就连到了错误的实例上,要么连不上,要么连上了但库不存在。
第二是本地连接方式。有些环境下,连接本机数据库时用的不是 TCP 端口,而是本地套接字文件(socket)。如果配置里写的是localhost,走的可能就是 socket 路径;而 socket 文件的路径在不同集成环境里又不一样,偶尔会出现"明明服务在跑、端口也对,就是连不上"的情况。遇到这种玄学问题,可以试着把连接主机从localhost改成127.0.0.1,强制走 TCP,很多时候一下就通了。
提示:改完配置文件后不需要重启数据库,但 PHP 是每次请求重新读取脚本的,所以直接刷新页面即可生效。
4. 卡在安装页面:一条可以照着做的完整排查链路
前面两步都过了之后,你会来到那个安装 / 重置数据库的页面。这页面上通常有几个步骤按钮,比如"创建数据库""创建数据表""写入数据"。很多人在这里卡住——点一下转半天、点完没反应、或者报一堆红字。下面是我总结的一套排查顺序,照着走基本能定位到问题。
4.1 第一步永远是看报错,而不是反复点
新手最容易犯的错就是:点了一次没反应,再点,还不行,继续点,最后把库搞成了半残状态。正确做法是——先看报错信息。如果页面什么都不显示,回到第 2 节说的,把 PHP 报错打开。报错里通常已经写清楚了是"连接被拒绝""表已存在""权限不足"还是"语法错误"。
我遇到过最常见的三类提示:连接类(账号密码端口不对)、已存在类(上次安装残留了同名数据库)、权限类(当前数据库账号没有建库权限)。这三类的处理方式完全不同,不看报错根本没法对症下药。所以别急,先把报错读懂。
4.2 分步验证:连接、建库、建表、写数据逐个击破
安装脚本干的事其实就是四件:连上数据库、建库、建表、写初始数据。任何一步失败,整体就卡住。你可以按这个顺序用命令行手动验证,比在页面上盲点高效得多:
| 验证环节 | 怎么做 | 常见失败原因 |
|---|---|---|
| 连接数据库 | 命令行用配置里的账号密码登录 | 密码错、端口错、服务没开 |
| 建库 | 手动执行一句建库语句 | 账号无建库权限、同名库已存在 |
| 建表 | 在刚建的库里建一张测试表 | 字符集不支持、权限不足 |
| 写数据 | 往测试表插一行再查出来 | 权限不足、字符集不匹配 |
这套流程走一遍,问题出在哪一环一目了然。我习惯在安装前先手动确认连接能用,连接这一关过了,后面基本都是小问题。如果之前装失败过,建议先把残留的同名数据库删掉再重新跑安装,否则脚本很可能因为"库已存在"而在中途报错,留下一个半成品环境。
4.3 安装跑完了但页面还是报数据库错误
还有一种诡异情况:安装页面上所有步骤都显示成功了,可你回到关卡列表点进某一关,还是提示"无法连接数据库"或"未知数据库"。这通常有两个原因。一是你访问的关卡引用的库名和你实际创建的库名对不上——安装脚本会创建几个不同名字的库,如果某个库没建成功,用到它的关卡就会报错。二是浏览器缓存了旧的页面,你看到的是上一轮的残留状态。
遇到这种情况,先清缓存、换无痕窗口刷新;还不行就进数据库命令行,show databases;看一眼到底建出来哪几个库,跟关卡实际引用的名字对一遍。这个对比动作能立刻帮你判断是"库没建全"还是"页面没刷新",比反复重启服务省事多了。
5. 字符集、权限和那些容易忽略的小细节
主体流程跑通之后,还有一类问题不会让你彻底打不开,但会在你用的时候冷不丁冒出来,比如中文乱码、某些关卡行为异常、文件读写失败等。这些细节不影响"能打开",但影响"好用"。
5.1 字符集不止影响显示,还可能影响行为
数据库和表的字符集设置会直接影响数据的存储和取出方式。如果你建库时没指定字符集,落到了默认值上,而脚本又按另一种字符集去读写,就可能出现中文乱码,甚至某些关卡的数据对不上号。稳妥的做法是建库时明确指定一个通用的字符集,比如:
CREATE DATABASE security CHARACTER SET utf8 COLLATE utf8_general_ci;这里要强调一点:字符集的选择不光关乎"显示得好不好看",它在你后续研究不同编码相关的注入场景时,本身就是关键变量之一。所以别图省事全用默认,明确建一个你知道的字符集,后面做实验时心里才有底。这一点我在实际操作中体会很深——同一个关卡,换个字符集表现可能就不一样,提前把环境变量固定下来,才谈得上"可复现"。
5.2 目录权限和文件路径:类 Unix 环境下的高发区
如果你不是用集成环境,而是自己在服务器上手动搭,那目录权限就是绕不开的坎。Web 服务进程(比如 Apache 或 Nginx 的运行用户)需要对 SqliLabs 的目录有读取权限,对某些需要写文件的子目录还得有写权限。权限没配好,表现可能是页面能开但图片、样式加载不出来,或者安装脚本无法写入临时文件。
另外就是路径问题。SqliLabs 里有不少地方用了相对路径来引用配置文件。如果你把它塞进了一个多层嵌套的子目录,或者改了目录名,相对路径就可能断掉,导致"某些页面单独报错、其他页面正常"这种迷惑现象。我的建议是:把整个文件夹原样丢进网站根目录,不改目录名、不加嵌套层级,先把最干净的路径跑通,再考虑改名的事。
5.3 浏览器缓存和"假成功"的迷惑
最后说一个特别容易被忽略的点:浏览器缓存。搭建过程中你会反复刷新安装页面和关卡页面,浏览器很可能把某一次的"报错页"缓存下来,导致你明明已经改好了配置,刷新看到的还是旧报错。这时候你会以为自己没改对,来回折腾配置。解决办法很简单——用无痕窗口,或者强制刷新(Ctrl+F5)。我搭环境的习惯是全程开着无痕窗口,省得被缓存牵着走。
还有一种"假成功":配置改完,页面看起来正常了,但其实是浏览器显示了缓存的正确页,实际请求还是失败的。判断方法也简单,打开开发者工具看一眼网络请求的状态码,200 还是 500 一目了然,别只信眼睛看到的页面。
6. 反复踩坑之后,我攒下的几条省事经验
搭了这么多次,我现在的流程已经固定下来了,基本能一次跑通。这里把经验摊开说,你照着做大概率能少折腾。
第一,动手前先确认三件事:PHP 版本是不是 5.4/5.6、MySQL 服务是不是在跑、root 密码到底是什么。这三件事确认完,80% 的坑就已经提前避开了。很多人是装到一半才发现版本不对,前面做的全白费。
第二,报错一定要开。display_errors和error_reporting这两项,是我搭任何 PHP 环境的第一步。没有报错信息的环境,就是在摸黑走路。
第三,配置文件的账号密码先改再装。别指望默认的 root/root 能对上你的环境,先去看一眼自己环境的真实凭据,改完再点安装,能省下一轮排查。
第四,失败过的安装一定要清干净再重来。残留的同名库是新安装失败的最常见原因之一,删库重来比修修补补快得多。
第五,环境要固定、要记录。我每次搭完都会在纸上或文档里记一笔:PHP 版本、MySQL 端口、库名字符集、配置文件改了哪几处。下次迁移或者帮别人搭,直接照抄。别小看这个习惯——靶场这类东西,环境和行为是强绑定的,你今天调好的一个参数,可能就是你明天复现某个现象的关键。
还有一个我自己踩过的教训:别一边搭环境一边急着做练习。环境没彻底稳定之前就冲进去,稍微有点异常你分不清是"环境问题"还是"自己操作问题",越练越乱。老老实实把环境跑到首页、点到任意一关都能正常响应,确认稳定了,再开始用它。这个先后顺序,是我花了两个下午才想明白的。
如果你搭到一半又遇到没见过的报错,先别慌,回到"连接—建库—建表—写数据"这条链路上一段一段验。绝大多数问题,都能在这条链路上找到那个断掉的小环节。