尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
sqli-labs Less 1 新手教程:SQL注入从判断注入点到联合查询脱库
sqli-labs 是我见过最适合新手入门 SQL 注入的靶场没有之一。Less 1 又是整个靶场的第一关难度最低但它把 SQL 注入最核心的“判断注入点、确认列数、找显示位、联合查询脱库”这条完整链路都串起来了。我第一次接触 SQL 注入就是从这一关开始的当时照着网上的教程一步步敲磕磕绊绊半天才搞明白每个参数为什么要这么改。这关如果吃透了后面几十关的核心思路都会顺畅很多。这篇文章我会把 Less 1 从环境准备到最终拿到数据的全过程完整走一遍每一步都会解释“为什么要这么做”而不是单纯丢给你几条 SQL 语句。适合完全零基础、刚搭好靶场但不知道从哪下手的初学者也适合对注入原理一知半解、想回头补基础的人。1. 环境搭建与靶场准备1.1 本地实验环境怎么配sqli-labs 是一个基于 PHP MySQL 的靶场所以本地环境需要能跑 PHP 和 MySQL。新手最省事的方案是装一个集成环境常见的几款各有优劣phpStudy国内用的人多启动快自带 PHP 和 MySQL非常适合新手。注意选一个稳定的版本别追最新版。XAMPP跨平台干净清爽适合喜欢自己动手折腾的。默认面板是英文对部分新手可能有点门槛。LAMP / LNMP 手动部署适合有一定 Linux 基础的人熟悉一下原生环境没有坏处但对纯新手不推荐容易在环境问题上卡住。我用的是 phpStudy版本是较稳定的 2018 版PHP 版本选的 5.6后面会说为什么不建议用 7.x。安装完成后把 Web 服务器的根目录设为sqli-labs所在的目录然后启动 Apache 和 MySQL。1.2 靶场源码部署与常见坑从官方仓库把靶场源码下载下来后解压到 Web 根目录比如C:\phpstudy_pro\WWW\sqli-labs。这时候访问http://localhost/sqli-labs/会看到靶场的首页。第一次进来要初始化数据库页面顶部会提示你创建一个数据库。正常流程是点击“Setup/reset Database”链接它会自动创建security库和对应表。这一关数据量不大整个过程几秒钟。我遇到过几个常见问题提前写在这里给你避坑页面能打开但点链接报数据库连接错误大概率是数据库账号密码不对。默认配置里连接信息写在sql-connections/sql-connect.php里确认用户名和密码跟你环境里 MySQL 的一致。创建数据库时报错先检查 MySQL 是不是真的启动了再确认当前用户有没有建库权限。phpStudy 默认 root 用户密码是空的如果改了密码记得同步改靶场配置文件。PHP 版本问题如果你用的是 PHP 7.x 或更高版本某些代码会报mysql_*函数未定义的错误因为老靶场用的是 PHP 5 时代的mysql_系列函数。最简单的办法是切换 PHP 版本到 5.6或者开启兼容扩展。环境一旦通了能正常打开 Less 1 的页面接下来的所有操作就都能在自己电脑上复现。这也是靶场最大的价值你可以随便折腾不用担心把别人的系统搞坏。2. SQL 注入原理与 Less 1 关卡分析2.1 为什么会存在 SQL 注入漏洞要理解 Less 1得先明白一句话SQL 注入的本质是用户输入被拼进了 SQL 语句并且被执行了。举个生活化的例子。你在一家餐厅点餐菜单上是固定的菜品。正常流程是你在菜单上勾选“红烧肉”后厨照着菜单做菜。但是如果服务员偷懒直接把你的原话当成菜名递给后厨你说“红烧肉再给我两瓶酒”后厨可能真会照做。SQL 注入就是这么回事——程序把用户输入的参数原封不动地塞进 SQL 查询里没有做任何过滤和校验。Less 1 的后台查询逻辑大致是这样$sql SELECT * FROM users WHERE id$id LIMIT 0,1;注意看这里的$id是从 URL 参数?id直接取出来的外面加了一对单引号。如果你正常请求?id1最终执行的 SQL 就长这样SELECT * FROM users WHERE id1 LIMIT 0,1看起来没什么问题。但如果我传的id不是数字而是一段精心构造的字符串呢比如id1那 SQL 就会变成SELECT * FROM users WHERE id1 LIMIT 0,1单引号数量不配对SQL 语法错误数据库就会抛异常。网页上通常会把错误信息直接显示出来——这就是我们用来判断注入点的突破口。2.2 请求特征与注入点判断打开 Less 1 的页面点一下“Lets inject”URL 会变成类似这样http://localhost/sqli-labs/Less-1/?id1页面上一大段文字最显眼的是“You are in...”以及一行看似莫名其妙的代码。这行代码其实就是后台查询语句的预览它非常诚实地告诉了你你的输入被直接拼接到 SQL 里了。接下来我们做第一步测试把id1改成id1数字后面加一个单引号回车。你会发现页面变了不再显示“You are in...”而是蹦出一段错误You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 1 LIMIT 0,1 at line 1不要急着跳过这段报错它透露了三个关键信息后台 SQL 的闭合方式是单引号。因为多加了一个单引号导致语法错误报错信息里出现了1这正好对应查询语句WHERE id$id中夹着输入的那两个单引号。SQL 语句末尾还有一段LIMIT 0,1。这是靶场自己加的限制只显示一条结果。我们后面联合查询时不用管它只需要在输入末尾加上注释符把 LIMIT“吃掉”就行。报错信息直接回显到页面上。这意味着后面的手工注入里我们能看到很多有用的数据库反馈信息。到这一步已经可以确认这个参数存在字符型注入并且是通过单引号闭合的。但还不够我们还需要确认查询结果是几列数据也就是字段数量。这一步是联合查询的前提也是 Less 1 的核心考点。3. Less 1 超详细实战过程3.1 第一步判断字段数量知道存在注入之后第一步就是确定当前的查询返回了几个字段。最经典的办法是用ORDER BY子句。ORDER BY在 SQL 里是用来排序的它后面可以跟列名也可以跟数字。数字表示“按第几列排序”。如果指定的列数超出了查询结果的总列数数据库就会报错。比如我们依次尝试?id1 ORDER BY 1 -- ?id1 ORDER BY 2 -- ?id1 ORDER BY 3 -- ?id1 ORDER BY 4 --前三次页面都正常显示到了ORDER BY 4时又报错了报错信息里会出现Unknown column 4 in order clause。这说明当前查询一共只有 3 列。为什么 1、2、3 都行4 就不行因为users表恰好有 3 个字段ORDER BY最多只能排到 3。这一步的结果决定了后面UNION SELECT里我们得填几个占位符。这里有个细节值得注意我用的注释符是--不是#也不是单纯的--。原因后面专门讲先记住这个写法。3.2 第二步构造 UNION SELECT知道了 3 列就可以上UNION SELECT了。UNION的作用是把两条查询语句的结果合并在一起但有个硬性条件前后两条查询返回的列数必须相等。所以我们这么写?id1 UNION SELECT 1,2,3 --页面还是正常显示但等一等细看页面中的内容会发现它多显示了两行原本一张表格的位置出现了2和3。这说明什么说明UNION SELECT 1,2,3里的第 2 个和第 3 个字段被直接展示在页面上。为什么要这么做因为我们要知道哪些列的数据会回显到前端。如果页面上显示 2 和 3就代表第 2 列和第 3 列的数据能让我们看到。后面我们把 2 和 3 替换成数据库的函数或字段名就能把信息读出来。但这里有个小坑现在的输出是 1、2、3因为第一条查询其实也返回了一行数据就是id1那条。为了让页面显示UNION SELECT的这部分通常把前面的id改成不存在的值比如-1?id-1 UNION SELECT 1,2,3 --改成-1后第一条查询结果为空页面上就只显示UNION SELECT产生的2和3了回显更干净。这一步也解释了为什么很多注入教程里喜欢用-1而不是1。3.3 第三步获取数据库名与版本信息拿到显示位之后就可以利用 MySQL 自带的信息函数了。先把第 2 列替换成database()第 3 列替换成version()看数据库名字和版本号?id-1 UNION SELECT 1,database(),version() --页面上第二块会显示当前数据库名第三块会显示 MySQL 版本号。我这边执行完得到的结果是security和5.5.53。这一步的意义比单纯拿个名字重要得多database()告诉我们当前所在的数据库是security后面查表时要在security库下找。version()告诉我们 MySQL 版本如果版本高于 5.0就可以用信息字典information_schema来查全库的表结构如果是 4.x 老版本那只能用暴力猜测表名的方式难度会大不少。在 MySQL 5.0 以上版本中information_schema是一个系统库里面藏着所有数据库的元数据信息。这是脱库的钥匙。3.4 第四步查询所有表名拿到数据库名之后就要看这个库里面有哪些表。我们用information_schema.tables来查?id-1 UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schemasecurity --这里的group_concat()函数可以把多行结果拼成一行字符串非常实用。不加它的话如果有多张表页面上只会显示第一张表的表名因为每行结果只有一列能回显。我在本地执行的结果是emails,referers,uagents,users一共四张表重点肯定是users。为什么直觉上它最容易存用户名和密码而且前面报错信息里看到的SELECT * FROM users恰恰印证了这一点。3.5 第五步查询列名知道表名之后下一步查列名。用information_schema.columns?id-1 UNION SELECT 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schemasecurity AND table_nameusers --执行后页面上显示id,username,password很标准的三个字段id是用户编号username是用户名password是密码。这也正好对应ORDER BY那一步判断出来的 3 列结构。3.6 第六步脱库拿数据列名都齐了剩下就是直接查数据。把username和password都拼在显示位上用group_concat确保所有行都能看到?id-1 UNION SELECT 1,group_concat(username),group_concat(password) FROM security.users --页面上哗啦啦列出来一堆用户名和密码第一关到此就算通关了。整个过程中其实我们完全可以在第三步之后直接用select * from users一把梭把整张表的内容拉出来。但从教学角度看一步一步拆解表名、列名、数据会让你对information_schema的使用有更扎实的理解。后面在更复杂的场景里比如需要绕过某些过滤时这种拆解能力会派上大用场。4. 实战中的报错与排查实录4.1 为什么我用 -- 而不是 -- 或这是新手最容易卡住的地方之一。SQL 标准里--是注释符但它后面必须跟一个空格才能生效。你直接写?id1 --在 MySQL 里是有效的因为--后面有一个空格。但如果你在浏览器地址栏里输入--加空格空格会被 URL 编码成%20或者被某些浏览器吞掉导致注释不生效。#号在 MySQL 里也是注释符而且不需要加空格。但麻烦的是URL 里的#会被浏览器当成“页面锚点”处理请求根本不会把#后面的内容发到服务器。所以直接用#也不行除非把它写成%23。--之所以能通杀大多数场景是因为在 URL 解码后会变成空格变相满足了--后必须跟空格的要求。所以在手工注入时我几乎都用--。但也别死记这一个有些 Web 层过滤会对--做拦截到时候还得灵活换%23或--%20。4.2 union select 出来还是原页面内容出现这个现象通常有两个原因一是前面提到的第一条查询有结果。如果?id1本身有数据页面优先渲染的是第一条查询的结果你用UNION追加的数据根本没有在显示位展示。解决方法是把id改成不存在的值比如-1或者999。二是列数对不上。UNION SELECT 1,2,3如果跟前面查询的列数不一致数据库直接报错。这时候回到ORDER BY那一步重新确认列数。4.3 回显内容被截断group_concat默认有长度限制默认group_concat_max_len是 1024如果数据量非常大结果会被截断。我们这关只有十几个用户完全不用担心。但如果后续在数据量大的场景下脱库可以顺便加上?id-1 UNION SELECT 1,group_concat(username SEPARATOR 0x3c62723e),group_concat(password SEPARATOR 0x3c62723e) FROM security.users --设置group_concat_max_len的方式是?id-1 UNION SELECT 1,group_concat_max_len,3 --或者启动 MySQL 时加上参数但手工注入场景下通常只需要对值大一点即可。4.4 页面不显示任何内容但不出错这种情况往往是因为闭合方式判断错了。Less 1 是单引号闭合如果你用的是数字型注入的思路不带引号?id1 and 11这种测试就会显得“没有反应”因为整个 SQL 变成了SELECT * FROM users WHERE id1 and 11 LIMIT 0,1这里1 and 11被当成了字符串查不到数据页面自然显示不出来。解决办法是回到最开始的引号测试先把闭合方式试出来。5. 从 Less 1 延伸出去的注入思路5.1 字符型与数字型的判断差异Less 1 是典型的字符型注入输入的参数被单引号包起来了。在真实环境中你还会碰到数字型注入参数没有引号包裹直接拼进 SQL。判断方法其实很简单在参数后面加and 11和and 12如果页面表现不一样基本就是数字型如果毫无变化大概率是字符型还得再补一个引号试试。这背后的逻辑是数字型注入的参数直接参与运算and 11为真、and 12为假结果自然不同。字符型注入的参数被当成了字符串的一部分加and 11只会让整个字符串查询不到结果。5.2 拿到数据之后能做什么很多人打完靶场就结束了但真实场景里拿到数据之后还有很长的路要走。密码字段在真实系统中通常不是明文而是哈希值比如 MD5、SHA1 等。你还要根据哈希特征判断算法然后用在线字典或彩虹表去解。Less 1 里的密码是明文纯粹是为了教学方便。另外数据之外的东西往往更有价值比如数据库版本、当前用户权限、是否支持文件读写、能不能拿到 UDF 或into outfile写入一句话木马。这些在后续的 Less 关卡里都会陆续出现Less 1 只是起点。5.3 怎么把这一关的能力用到后续关卡sqli-labs 的关卡难度是递进的。Less 2 是数字型注入Less 3 和 Less 4 分别是有单引号括号和双引号括号包裹的注入。你会发现核心手法完全一样变化的只是“怎么把输入从引号的包裹里逃出来”。Less 5 之后开始进入报错注入、布尔盲注、时间盲注和无回显注入这些对 SQL 基础的要求会明显提高。我的建议是Less 1 这关不要只满足于“跑通”最好能把手动拼 SQL 的过程重复三到五遍直到不看笔记也能从ORDER BY一路写到group_concat脱库。肌肉记忆在这种基础关卡里特别重要后面遇到复杂的 WAF 绕过时你才能把注意力放在绕过策略上而不是卡在基础语法上。6. 总结Less 1 带给我的实战启发我自己在带新人或者写教学材料的时候反复强调一个观点Less 1 看上去简单但它教会你的是一整套 SQL 注入的思维方法——每一步都去确认、把自己放在数据库执行的角度去思考“这条 SQL 会变成什么样”。当你习惯了这种思维再去看后面的 Less 2、Less 3其实就是在处理“如何把注入载荷构造得能让后台 SQL 按你的意愿执行”这件事。最后再分享一个小经验动手敲 SQL 的时候最好自己开一个 MySQL 命令行把后台拼接完成的语句手动复制进去执行一遍。比如查到某个 payload 之后先在命令行里跑一次SELECT * FROM users WHERE id-1 UNION SELECT 1,2,3 --看看真实的输出长什么样再对比网页上的回显。这样做几次你对 SQL 语句的敏感度提升得比你想象中快很多。靶场存在的意义不是让你复制几段 payload而是让你真正理解每个参数背后的数据库逻辑。
RELATED

相关推荐

LNTON烟火识别本地部署全指南:CUDA/cuDNN/Python环境避坑实战

LNTON烟火识别本地部署全指南:CUDA/cuDNN/Python环境避坑实战

简介:本资源是面向安防监控、智能视觉开发及边缘AI部署工程师的烟火与烟雾识别实用工具包,基于LNTON羚通算法实现高精度实时检测,适用于森林防火、工厂安全巡检、仓储物流等高风险场景的早期预警需求。压缩包共874个文件,含843张标…

📅 2026/10/16 12:44:19
IO多路复用深度解析:select、poll与epoll的演进与实战

IO多路复用深度解析:select、poll与epoll的演进与实战

2. 为什么需要IO多路复用:一个线上事故引发的思考 先讲个真实的经历。有段时间我负责维护一个内部网关服务,高峰期维持着几千条TCP长连接。当时的代码是经典的“一线程一连接”模型,线程数越开越多,从最开始50个线程调到200个&…

📅 2026/10/16 12:39:18
降AI工具怎么用?一套流程把AI率压到15%以下

降AI工具怎么用?一套流程把AI率压到15%以下

我见过太多第一次碰降AI工具的人,拿着检测报告一脸懵:明明是自己逐字写的,为什么机器说有70%的AI生成痕迹?然后慌慌张张找了个工具,把整篇文章“洗”了一遍,结果AI率是降了,文字却变得像机翻&am…

📅 2026/10/16 12:39:18
MORE NEWS

更多资讯

📰

GIS坡度分析实战:从DEM到坡度分级的避坑指南

国产GIS工具里坡度分析这个功能,我前前后后用了差不多七八年。说实话,最早接触ArcGIS那会儿,我以为坡度分析就是把DEM丢进去点一下“Slope”完事,后来才发现,同样的DEM、同样的工具,不同人做出来的结果能差…

📰

IEC 62439-3标准解析:PRP与HSR实现零切换冗余的核心原理

简介:本资源为IEC 62439-3:2016第3版完整英文原版标准文档,面向工业自动化、电力系统通信、轨道交通信号等领域的系统架构师、网络工程师及高可靠性网络设计研发人员,解决工业场景下关键通信链路零中断冗余架构的设计与实现问题。文档共358页…

📰

大厂RAG为何弃用纯向量检索?混合检索才是召回率生命线

做了几年RAG落地,被问得最多的一个问题就是:为什么你们不用纯向量检索?在很多人的想象里,RAG就是“文档切成块 → embedding → 塞进向量库 → 查相似度”,感觉纯向量就该是标准答案。但真到了大规模生产环境&#xff…

📰

STM32 FFT频谱分析与波形识别:从ADC采样到谐波特征分类

简介:面向STM32开发者的FFT频谱分析与波形识别完整工程,基于正点原子精英版3.5寸TFTLCD实现,可对50Hz~200Hz信号提取基频、3/5/7次谐波峰值,并区分正弦、方波、锯齿波、三角波,适合嵌入式信号处理学习、课设与竞赛项目…

📰

职场人际模式的“老剧本”:强迫性重复与五步修复指南

如果你总觉得自己身边的职场奇葩一套接着一套,换家公司还是同款领导,换个部门还是同款甩锅侠,那可能真的不是运气差,而是你心里有个“老剧本”在卡Bug。你可能已经对自己的抱怨感到麻木了——“我怎么老遇到这种人”被你说过无数遍…

📰

高德地图场景化使用技巧:通勤、停车、充电、接人全攻略

我常年在外跑业务,手机里最离不开的工具就是高德地图。但说句实话,身边很多人用了它好几年,连三分之一的功能都没用满。导航、打车谁都会,可一旦进入“通勤、停车、充电、接人、家庭守护”这些具体生活场景,大多数人就…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬