0x01 前言
笔者在最近的CTF比赛中遇到了几次关于python沙箱逃逸的web题目,故此做一些总结。在阅读这篇文章之前,我相信你已经了解关于python的一些基本语法以及沙箱逃逸的思路,所以这里就不再赘述了。
0x02 内置模块
在谈python沙箱逃逸之前,我们先来学习一下python常用的内置模块
1. os模块,可以通过os.system(cmd)调用系统命令,例如os.system(‘whoami’)
2. timeit模块,这个模块中的timeit函数本来返回的是命令执行时间的,但是我们也可以利用它来执行任意命令,例如:
3. subprocess模块,在python中,我们可以通过标准库中的subprocess包来fork一个字进程,并运行一个外部的程序。subprocess.call(),父进程等待子进程完成。例如:
4. commands模块,利用这个模块同样能执行任意命令,例如
5. platform模块,这个模块最常见是用来获取系统应用信息的,我们同样能使用它来进行任意命令执行。例如:
除了以上几个常用模块之外,exec和eval两个函数也是经常用来执行系统命令的,这里两个函数的区别是eval是要返回计算结果的,然而exec是不会返回的。
0x03 绕过
介绍了常用的执行系统命令的方法之后,下面我们来谈谈绕过
1.既然有那么多的用来执行系统命令的模块和函数存在,出题人可以直接使用del删除它们
应对:如果说没有过滤reload函数的话,我们可以使用它来重载我们需要的模块就行
2. 正则匹配并过滤掉一些危险函数或者危险模块
应对:这里我提供几个实例大家慢慢体会并且可以举一反三
其他的编码绕过方式或者字符串拼接执行读者可以自己去脑洞。
3. 使用内联函数,我们可以使用内联函数__import__和__builtins__调用一切函数。
在做python sand box题的时候我们可以自己去定义object类,原因是object类中基本涵盖了Python的所有基础函数。例如:
我们发现定义的object中存在hook函数,那么我们利用起来执行任意命令。
这也是常用的魔术方法。
0x4 再谈timeit模块
在前面我们提到了timeit模块可以用来执行任意系统命令,但是细心地同学会发现timeit只返回给我们执行命令所花的时间,如果不能通过cloudeye等外带通道获取命令执行的结果,那么这样用起来就非常的鸡肋了。幸运的是我们可以利用时间盲注(time based rce)去获取信息。
利用这个小trick我们就可以写个脚本愉快的python沙箱逃逸了。
0x05 总结
python沙箱逃逸需要我们熟练掌握python的一些基础知识,并且在平时我们要学会举一反三,尽量的脑洞一些新技巧。笔者之前看到有大牛通过pwn去做python沙箱逃逸题,如果说能控制PyCodeObject里边的字节码就变相决定了python去执行什么样的字节码,那也就等价于能执行任意命令了,所幸python作为动态语言是允许使用types操作字节码的。无奈笔者对二进制研究颇浅,师傅们可以自行去研究,Orz。