sqli-labs Less-25通关指南:SQL注入中or与and过滤的双写绕过
sqli-labs 这套靶场很多人从 Less-1 一路点过来前面的关卡基本是“见招拆招”单引号闭合、联合查询、报错函数一套流程下来就觉得 SQL 注入不过如此。等刷到 Less-25你会发现页面又干干净净地返回了报错但直接用order by却怎么都不对——这就是靶场第一次正式把“过滤”和“绕过”摆到台面上。Less-25 的 SQLi 本身很常规真正拦人的是关键字or和and。这一关适合刚刷完前 24 关、想从“能出数据”进阶到“理解被过滤后为什么还能出数据”的人。它会逼着你把 SQL 语句拆开看弄清楚一件事服务端在我输入之后到底改了什么搞懂这一关后面遇到真实站点的简单关键字过滤你至少不会第一反应就去点自动化工具而是能用最小 payload 做判断。下面我从过滤逻辑说起把整个通关过程完整走一遍顺便记录一些容易踩的坑。1. Less-25 到底过滤了什么1.1 为什么order by突然不灵了我第一次刷 Less-25 的时候按前面的老套路直接提交?id1 order by 3 --结果页面报错而且报错内容跟我想的不一样。它并不是“列数不对”那种正常的 MySQL 错误而是最原始的语法错误像是 SQL 语句本身就被打散了一样。这里先别急着怀疑闭合方式问题就出在关键字order上。order这个单词里面有or两个连续字母。Less-25 的后端会把输入内容里的or替换成空字符串于是我的order就变成了der。最终数据库收到的 SQL 大概长这样SELECT * FROM users WHERE id1 der by 3 -- LIMIT 0,1一条 SQL 里出现der byMySQL 自然直接报错。这不是因为你闭合方式写错了也不是列数不对而是关键词在到达数据库之前就被“阉割”了一部分。如果你开着 MySQL 的 general log或者使用能够显示后端真实 SQL 的调试方式就能看到这个过程。没有调试条件的也可以根据报错页面的原文反推。Less 系列很多关卡都会在错误信息里带出部分真实 SQL这是个很值得利用的信号。1.2 从现象推测后端过滤代码Less-25 的过滤逻辑从行为上推测大概是这样一段 PHP 代码$id $_GET[id]; $id str_ireplace(or, , $id); $id str_ireplace(and, , $id); $sql SELECT * FROM users WHERE id$id LIMIT 0,1;有些版本可能写成preg_replace(/or/i, , $id)之类的正则形式但核心特征是一样的不区分大小写OR、Or、oR都会被删替换所有匹配到的位置不是只删第一个替换不是递归的不会删完再检查一遍。第三点就是整个关卡的钥匙。oorrder经过一次替换后中间那一组or被删掉剩下的字符正好拼回order。由于它不会对拼出来的结果再执行一次过滤order就安全地进入了 SQL 语句。为了把这种映射关系讲清楚我整理了一个对比表我输入的原始内容经过过滤后实际到达 SQL 的内容结果order byder byder by语法错误OR空字符串空语法错误或逻辑改变and空字符串空闭合引号被破坏oorrder byorder byorder by正常执行ananddandand正常执行后两行就是典型的双写绕过。理解这张表就相当于理解了 Less-25 的所有核心内容。后面那些复杂 payload无非是把order、and、or出现的地方用双写形式重新套进去。2. 绕过思路盘点为什么“双写”是首选2.1 双写绕过的原理与适用边界双写绕过的原理建立在上一节的非递归过滤之上。过滤器只会“删除一次”不会对删除后产生的新字符串继续做同样的检查。所以我们人为地把关键字的部分字母重复一遍让过滤器删掉一份之后剩下的那份刚好能拼出原来的关键字。在 Less-25 里最实用的转换关系有三个order by写成oorrder byand写成ananddinformation_schema写成infoorrmation_schema需要注意这里不要画蛇添足。比如select里面本来就不含or或and你完全没必要写成selselectect。很多人一看“原来要双写”就把所有 SQL 关键字都双写一遍结果反而让语句变得没法读还容易引入新的语法问题。Less-25 只过滤or和and你就只处理包含这两个字母串的关键字。另外双写也不是万能的它依赖“单次替换”这个前提。如果以后遇到一个递归过滤的 WAF也就是删完or之后会重新从结果里再找一次or那oorrder经过第一轮变成order经过第二轮又会被删成der双写就直接失效。所以每次遇到新的过滤场景先花几十秒做一个小实验判断过滤是不是递归的会比盲目堆积 payload 高效得多。2.2 大小写、注释、运算符替换为什么不优先用有人会想过滤了or那我用OR大小写绕过行不行在 Less-25 里面不行因为str_ireplace或者带i修饰的正则都是大小写不敏感的。OR、Or、oR全部照删不误。你试一个就知道报错内容跟全小写时没有区别。还有人会想用内联注释把它拆开比如o/**/r是不是能绕过这个思路本身没错有些正则写得不好的 WAF 确实会漏掉。但 Less-25 是在 SQL 执行前做纯字符串替换它不关心注释语法而且 MySQL 对关键字中间插注释也不是所有版本都能接受。这个方案在这个关卡里远不如双写稳定不建议作为首选。用运算符||代替OR、用代替AND理论上也是可行的。但 MySQL 对||的默认行为在不同版本里不完全一致有些老版本会把||当成字符串连接符。加上 URL 里面会被解析成参数分隔符如果你直接提交1 11后端收到的可能只是1和临时变量11而不是你期望的逻辑运算符。虽然可以通过%26%26编码绕过但实际调试起来比双写多一层麻烦。因此在这个关卡里我会老老实实选择双写。说到底绕过方案要选“简单的、可预期”的而不是“高级的、花里胡哨”的。能把 payload 稳定跑通比什么都重要。3. 完整通关实操从探测到拖库3.1 环境准备和第一次探测本地跑 sqli-labs 的方法很成熟无非是 PHP MySQL 环境然后把sql-connections/db-creds.inc里的数据库账号密码改成自己本机的账号密码。注意 Less-25 页面默认会回显 MySQL 错误这对我们观察过滤结果非常有利。如果你第一次访问能看到页面上方有账号信息下方是连接状态说明环境已经就绪。接下来的所有请求我建议至少把浏览器开发者工具或 Burp 的 Repeater 打开。直接用地址栏也能过关但遇到、、#这类特殊字符时地址栏容易帮你做了一些“隐式编码”导致你无法准确判断自己发出去的内容。用 Burp Repeater 至少能看到实际的请求头这对理解过滤逻辑很重要。第一步只发三个请求?id1 ?id1 ?id1 --第一个请求正常说明 id 参数会带入查询。第二个请求报错错误信息里面出现类似1 LIMIT 0,1的内容说明参数被一对单引号包裹而且 LIMIT 在最后。第三个请求恢复正常说明用--把闭合引号后面的内容注释掉是生效的。到这里注入点确认完毕单引号字符型注入查询语句是SELECT * FROM users WHERE id$id LIMIT 0,13.2 判断列数找到回显位确定了注入点之后先猜列数。Less-25 的order by必须双写所以提交?id1 oorrder by 3 --页面正常。继续试?id1 oorrder by 4 --页面报错说明这张表只有 3 列。这里值得停下来看一眼 SQL 的真实形态SELECT * FROM users WHERE id1 order by 3 -- LIMIT 0,1注意--里的在 URL 中代表空格。整个注释符到行尾把原本的闭合引号和LIMIT 0,1一起注释掉了。如果你在 Burp 里发现被当成普通字符而不是空格可以直接改用%20或者%23。列数确定后找回显位?id-1 union select 1,2,3 --这里把 id 改成 -1是因为前面没有任何 id 为 -1 的记录可以让联合查询前面的结果集为空从而让union select后面的内容显示在页面上。请求发出去后页面应该能看到数字 2 和 3 对应位置出现回显。3.3 爆库、爆表、爆列、拿数据拿到回显位之后常规联合查询就能一路拿数据。第一步看数据库名?id-1 union select 1,database(),3 --页面回显security这就是当前使用的数据库名字。接下来是重头戏爆表名。表名存放在information_schema.tables里但information_schema这个单词里面含有or所以必须写成?id-1 union select 1,group_concat(table_name),3 from infoorrmation_schema.tables where table_schemadatabase() --这个 payload 发出去页面会返回类似下面这样的结果emails,referers,uagents,users如果结果被截断只显示了一部分也不用慌后面讲排查的时候会说怎么处理。看到users表之后接下来看它的列名。列名信息在information_schema.columns里?id-1 union select 1,group_concat(column_name),3 from infoorrmation_schema.columns where table_nameusers --返回结果应该是id,username,password最后一步把账号密码直接拿出来?id-1 union select 1,group_concat(username,0x3a,password),3 from users --0x3a是冒号的十六进制写法作用是让返回结果变成类似admin:password的可读格式。到这里这一关的核心数据就算拿完了。如果你更习惯一行一行看数据也可以不加group_concat而是直接limit 0,1、limit 1,1这样逐条枚举。比如?id-1 union select 1,username,password from users limit 0,1 --这种方式在数据量大的时候更可靠不容易被输出长度限制截断。3.4 报错注入和时间盲注作为复习路线Less-25 虽然用联合查询就能过但既然这一关专门训练“过滤环境下怎么重构 SQL”我建议顺便练一下报错注入和时间盲注因为它们在真实环境下比联合查询更通用。报错注入的 payload 可以这样写?id1 anandd updatexml(1,concat(0x7e,database(),0x7e),1) --这里的anandd双写后变成andupdatexml本身不含or和and所以不用改。0x7e是波浪号~它的作用是让报错信息变成类似XPATH syntax error: ~security~如果你直接把database()丢进updatexml而不加concat有些版本下不会触发报错这就是我刚开始试的时候最郁闷的地方。加一个concat(0x7e,payload,0x7e)是最稳妥的触发姿势。时间盲注则非常直白?id1 anandd sleep(3) --如果页面等待了 3 秒才返回说明and sleep(3)被真正执行了。你可以把sleep(3)换成if(条件,sleep(3),0)来猜数据。注意这里的if函数没有or和and不需要双写但条件表达式里如果用到or或者and就得继续双写。比如?id1 anandd if(11,sleep(3),0) --这个 payload 双写的是andif(11,sleep(3),0)里面没有需要额外处理的字符串所以整体可以正常执行。4. 常见问题与踩坑实录4.1 问题速查表我在本地刷这一关的时候来回折腾了不少次也见过很多人在网上问相似的问题。这里整理一个速查表基本覆盖了最常见的翻车现场现象可能原因解法order by一直报语法错误or被过滤order变成了der使用oorrder by所有带and的条件全报错and被过滤条件表达式只剩一半使用ananddinformation_schema无法识别关键字里的or被删使用infoorrmation_schema看起来没生效被 URL 解析成参数分隔符改为%26%26或用双写updatexml不报错第一个参数或路径参数构造不触发错误使用concat(0x7e,payload,0x7e)group_concat结果看不全输出长度被页面截断用limit 0,1单行枚举--在某些工具里失效加号被当成普通字符或没转成空格改用--%20或%23这张表里的每一行都是我或者身边人实际踩过的坑。如果你刷的时候遇到报错先别急着换工具对照这个表定位一两次基本能判断出是过滤问题还是注释问题。4.2 利用报错原文反推真实 SQLLess 系列一个特别好的地方在于它会很慷慨地返回 MySQL 的语法错误原文。这本来是靶场设计但在实际测试中也很有用。举个例子。你提交?id1 anandd 11 --在 Less-25 里它会正常返回还是报错正确结果是正常返回因为anandd被过滤成and最终 SQL 是SELECT * FROM users WHERE id1 and 11 -- LIMIT 0,1如果你误写成?id1 and 11 --由于and被删掉请求发出去后很可能直接变成语法错误。你会在报错信息里看到类似1 11这种不伦不类的内容。看到这种内容第一反应应该是过滤删掉了and导致两个表达式之间缺少连接符。这个方法不仅能帮你定位过滤规则还能帮你判断自己写出来的 payload 是否真的被还原成了预期 SQL。在真实环境中不一定每次都有这么清晰的报错回显但只要允许你故意触发错误这个思路永远值得先试一次。4.3 几个容易忽略的小细节第一个细节是注释符的选择。--是 SQLi 里最常见的写法但它的原理容易被忽略在 URL 解码后是空格所以 MySQL 才能正确识别--注释。如果你用的是 Burp并且没有将加号编码某些版本会原样传递加号这时候注释就不会生效。更稳妥的替代方案是%23也就是#的 URL 编码。很多老手直接用%23就是因为这个坑。第二个细节是双写对象。不是说所有关键字都要双写只需要双写包含or或and的部分。比如table_schemadatabase()里就没有这两个字符串不用动。如果你把整条 SQL 所有单词都改一遍反而容易把本来正确的函数名改坏比如把concat改成cconconatcat那个就彻底跑不通了。第三个细节是group_concat的结果截断问题。在本地缺省配置下group_concat的长度限制通常在 1024 字节左右如果你的数据量比较大页面可能只会显示一部分。这时候不要慌换成limit 0,1一行行看或者先取一个最小表验证流程都比强行拼接更实际。第四个细节是环境里的 PHP 配置。现在的 PHP 版本早就没有magic_quotes_gpc这个老功能了所以单引号可以直接传入。如果你在一个很老的集成环境里刷遇到单引号被转义的情况记得先看一下 PHP 配置文件不要一上来就觉得是过滤规则的问题。最后说点体会Less-25 的过滤规则其实很粗糙放到真实环境里顶多算个入门级 WAF但它的教学价值并不在“绕过去”本身。它逼着你去关注一个问题我提交的 payload在到达数据库之前会被后端改写成什么样子我以前刷前 24 关的时候经常是 payload 能跑通就完事根本不管数据库收到了什么。到了这一关被order by连续报错打了几次脸之后我才真的开始打开调试工具一个个请求去看过滤后的 SQL。我后来处理各种过滤场景第一步永远是先故意触发一次报错从报错原文里读真实 SQL而不是靠猜。这个习惯就是在 Less-25 养成的。双写只是解决方案之一分析过滤模型才是真正通用的能力。手动把这关完整走一遍之后再回头看各种通关手册你会发现它们只给了 payload没给你为什么——而那才是这关真正值钱的地方。

相关新闻

hs_dma_framework:打通FPGA到ARM64 Linux的高速数据采集框架

hs_dma_framework:打通FPGA到ARM64 Linux的高速数据采集框架

1. 从一块板子到一套平台:hs_dma_framework 到底在解决什么问题做高速数据采集的人大概都有过这种体验:FPGA 端逻辑跑得飞起,ADC 采样率拉到几百兆甚至上 G,数据在片内 FIFO 里堆得满满当当,结果一到"把数据搬到 …

2026/9/26 8:27:21 阅读更多 →
银河麒麟系统修复助手LiveCD实战:登录闪退与引导修复全指南

银河麒麟系统修复助手LiveCD实战:登录闪退与引导修复全指南

前阵子一台银河麒麟操作系统服务器重启后,界面一直停在登录页,鼠标点账号、输入密码回车,画面刷一下又弹回登录框,键盘还有效,就是进不去桌面。折腾了半小时没头绪,我直接掏出U盘,把系统修复助手…

2026/9/26 8:27:21 阅读更多 →
pipeline 项目中的高性能 JSON 编解码:json-iterator(jsoniter)完全指南

pipeline 项目中的高性能 JSON 编解码:json-iterator(jsoniter)完全指南

云原生CI/CDDevOps后端 【免费下载链接】pipeline A cloud-native Pipeline resource. 项目地址: https://gitcode.com/gh_mirrors/pipelin/pipeline 点击查看 免费下载 json-iterator(简称 jsoniter)是一款 100% 兼容 Go 标准库 encoding/j…

2026/9/26 8:27:21 阅读更多 →

最新新闻

AI前沿 | 2026年9月11日:OpenAI Agents API 公测 + Codex 架构开放 + MCP Agent 基建

AI前沿 | 2026年9月11日:OpenAI Agents API 公测 + Codex 架构开放 + MCP Agent 基建

AI前沿 | 2026年9月11日:OpenAI Agents API 公测 Codex 架构开放 MCP Agent 基建 📖 首屏导读 本教程配套付费专栏:《大模型工程师修炼手记》 19.9 元(AI 编程 Agent 实战 本文同主题系统课程) 《AI时代程序员的自…

2026/9/26 9:08:51 阅读更多 →
二手车价格预测实战解析 从 Kaggle 回归赛题到可落地估价方案

二手车价格预测实战解析 从 Kaggle 回归赛题到可落地估价方案

二手车价格预测是结构化数据建模里非常典型的一类业务问题,表面上是回归竞赛,实质上对应交易平台、车商系统和资产评估场景中的定价能力建设。这类任务的难点不在模型名字,而在于是否真正理解车辆属性、价格分布、异常样本和类别特征对结果的影响。 这场 Kaggle 赛题很适合…

2026/9/26 9:08:51 阅读更多 →
随访机制设计:为什么病人不回来第二次

随访机制设计:为什么病人不回来第二次

写在前面 我是郭凤英。早年在三甲,一个上午几十个号,病人来不来第二次,我基本顾不上问。现在号少了,我才有工夫回头看这件事。 看下来发现:复诊率低,很少是因为"病人不重视",更多是我…

2026/9/26 9:08:51 阅读更多 →
本地智能体驱动的办公文档自动化实战

本地智能体驱动的办公文档自动化实战

1. 为什么“本地智能体”不是概念炒作,而是办公自动化的真实拐点 最近帮一家做合同审核的律所客户重构文档处理流程,他们每天要人工拆解300份PDF合同,提取关键条款、比对违约责任、生成风险摘要——平均每人每天花4.2小时在复制粘贴和格式校对…

2026/9/26 9:08:51 阅读更多 →
vibe-coding 工具生态与模型选择:用 TaoToken 统一 Key 打通 Cline 与 CC Switch 配置

vibe-coding 工具生态与模型选择:用 TaoToken 统一 Key 打通 Cline 与 CC Switch 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/26 9:08:50 阅读更多 →
Agent 响应延迟优化:一套分层工程实践框架

Agent 响应延迟优化:一套分层工程实践框架

Agent 响应延迟优化:一套分层工程实践框架本文基于一个常见的工程问题展开:如果要降低 Agent 的端到端响应延迟,可以从哪些环节入手? 原文内容偏向面试问答,本文在其"四层模型"框架基础上做工程化扩展&#…

2026/9/26 9:07:50 阅读更多 →

日新闻

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、…

2026/9/26 0:00:25 阅读更多 →
学校官网模拟全流程实践:从页面布局到后端接口与部署

学校官网模拟全流程实践:从页面布局到后端接口与部署

如果你正在找一门 Web 大作业的题目,或者刚开始接触 Web 前端开发想做点能拿来展示的东西,“学校官网模拟”几乎是最稳的选择。题目看着简单,但要把导航、新闻列表、轮播 Banner、二级页面、后台数据都串起来,其实已经把前端布局、…

2026/9/26 0:00:25 阅读更多 →
超级玛丽游戏源码C++:从零搭建横版跳跃游戏工程

超级玛丽游戏源码C++:从零搭建横版跳跃游戏工程

简介:这是一份面向游戏开发初学者与C进阶学习者的超级玛丽(超级马里奥)游戏源码,基于C面向对象编程实现,适合想通过经典项目理解游戏主循环、角色类设计、地图关卡加载与物理碰撞检测的读者参考。压缩包共49个文件&…

2026/9/26 0:00:25 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/25 19:27:14 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/25 11:15:26 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/25 20:29:09 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/25 20:29:43 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/25 20:29:31 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/25 19:27:26 阅读更多 →