2024第七届巅峰极客部分wp
GoldenHornKing
源码给了是很明显的ssti,在/calc路由里传参calc_req,黑名单是不能有:数字、百分号、非ascii之外的字符。最烦的是这个access,原本是False,可以不用管,但是一旦成功执行一次代码,access就会变成True,这个环境就不能打了,所以我们最好还是在本地先去掉这个access,方便我们调试,先打通一遍,再打开环境尝试。
1 | |
这里calc_req参数外面给了四个大括号,这意味着我们传参不需要像ssti一样再传两对大括号进去了,直接可以打payload。
这里是没给回显的,除非你有read()所以我们只能通过服务器是否爆500来判断我们的payload是否有问题。
我们先拿eval:
1 | |
这里使用 .__subclasses__() 后面配合 [] 可能更多地是选择了系统中第一个有 __init__、__globals__ 的子类,因此不会导致错误。
这里还有一个拿eval的办法:
1 | |
因为代码前面app = FastAPI(),app是FastAPI的一个对象,我们就可以直接调用app也就是FastAPI类的方法了。
拿到eval后,我们到现在这道题有两个做法:
方法一:打内存马进行rce
打FastAPI内存马,在FastAPI类有一个add_api_route方法,我们可以通过这个方法来增加一个路由,进行rce
1 | |
我们需要再eval里重新获取一遍app也就是FastAPI的对象。
1 | |
sys.modules:sys模块中有一个名为modules的字典,它维护了所有已导入模块的当前状态。这个字典的键是模块的名称,而值是对应的模块对象。modules['__main__']:__main__是运行 Python 程序的主模块,无论是直接从命令行运行的脚本,还是通过某个执行环境运行的代码。通过sys.modules['__main__'],我们获取到了当前执行程序的主模块对象。__dict__:每个模块对象都有一个__dict__属性,它是一个字典,包含了模块内定义的所有全局变量和函数。['app']:最后,从模块的__dict__中获取名为app的对象。
然后整合以下payload:
1 | |
现在访问/shell就可以拿到flag了
方法二:修改__file__进行任意文件读取
1 | |
在跟路由读取了当前代码文件内容,并输出到网页上。那么如果我们能修改__file__为/flag那么访问根路由就能拿到flag了。
__file__在全局变量globals里有
1 | |
使用setattr(object, name, value)方法修改对象的属性值。
1 | |
Q:为什么不用
__import__('sys').modules['__main__'].__dict__,__file__明明在这里面啊?A:因为setattr函数的第一个值是一个对象,
__dict__是__main__的一个属性,并不是一个对象。
整合一下payload:
1 | |
php_online
admin_Test
扫后台发现/admin.html,这里可以文件上传,并执行命令。

但是命令执行过滤了基本所有字符,留下的只有:
命令部分fuzz出来的可用字符为t * . /
只能执行临时文件:
1 | |
通过.(点,也就是 source命令)去执行/tmp目录里的文件

flag没有权限读,尝试提权,发现find命令有suid权限:

直接find执行命令:
1 | |