[PyJail] python沙箱逃逸探究·下(HNCTF题解 - WEEK3)

[PyJail] python沙箱逃逸探究·下(HNCTF题解 - WEEK3)
最新回答
遗留的忧伤

2022-07-06 20:18:39

首先感谢Crazyman精心设计的这些题目~

具体题目可以在X宝 @Xenny偷题平台上找到。

总览传送门:

zhuanlan.zhihu.com/p/57...
calc_jail_beginner_level6题目描述

题目未给出远程pyjail的代码。连上远程后,屏幕上出现如下提示:
我的解答

简而言之,这题几乎将所有的hook机制都限制了。因此,我们需另寻他法。

通过深入研究,我找到了这个分析报告:

报告指出,利用_posixsubprocess.fork_exec函数实现远程代码执行(RCE)。然而,需要注意不同python版本的该函数参数数量可能不同:我的本地WSL环境中的python版本为3.8.10,函数接受17个参数;而远程python版本为3.10.6,函数接受21个参数。

同时,直接import _posixsubprocess会触发审计hook。但我们可以通过以下方式绕过限制:

或者直接...

因为可以多次exec,我们可以通过输入多行代码来解决问题:

此时,我观察到,程序会交替进入python和shell状态。尽管如此,不用过于担心,因为我们多次执行代码,只需重复输入我们所需的shell指令,总能找到对应的回显。

获取shell后,我们尝试获取题目代码:
calc_jail_beginner_level6.1题目描述

与前一题不同,本题仅有一次代码执行机会。

不过,我们之前提到的python 3.8引入的海象运算符,通过这种方式可以构造出执行代码的payload:

然而,发送payload后,虽然能够进入shell状态,但shell瞬间关闭,任何命令输入均不显示回显。

起初,我感到绝望,但随后决定尝试暴力多次尝试起shell,看看结果如何:

程序确实多次尝试起shell。这时,我突发奇想:将要执行的shell命令复制到剪贴板,然后在程序疯狂回显时,快速粘贴回车键,试图执行命令。结果,您猜怎么着?居然有一定概率能显示出执行命令的结果!真是意外的发现!于是,在这种“破烂”shell状态下,我成功拿到flag……

还有一种相对优雅(?)的方法:利用itertools中的无限迭代器暴力起shell。不过实测发现,并未达到无限执行:猜测远程起进程的限制导致了这一现象。

获取shell后,我们尝试获取题目代码:
s@Fe safeeval题目描述

题目未给出远程pyjail的代码。连接远程后,看到如下提示:
我的解答

可以看到,这题的WAF采用了基于代码字节码操作码的拦截机制。

尝试莽试一句话RCE,结果出现错误提示,表明直接使用__import__或__builtins__无效。

这时,我想到了lambda表达式,于是尝试莽试用lambda表达式包裹一句RCE代码:

结果成功获取shell,随后可自由操作。

获取shell后,我们尝试获取题目代码:

查看代码中的github链接,我们找到了test_expr函数的定义:

可见,save_eval的第二个参数实则名为allowed_codes,这波操作与变量名的配合并不理想。

分析payload被解析出的操作码,发现它们都在题目给出的黑名单中。

通过类的定义巧妙绕过了拦截,Robin的强大令人赞叹,有种大道至简的感觉。

本文使用 Zhihu On VSCode 创作并发布