当前位置:首页 > 黑客技术 > 正文内容

Flask框架(jinja2)服务端模板注入漏洞分析(SSTI)

访客4年前 (2021-04-15)黑客技术992

Flask

Flask 是一个 web 框架。也就是说 Flask 为你提供工具、库和技术来允许你构建一个 web 应用程序。这个 wdb 应用程序可以使一些 web 页面、博客、wiki、基于 web 的日历应用或商业网站。 Flask 属于微框架(micro-framework)这一类别,微架构通常是很小的不依赖于外部库的框架。这既有优点也有缺点,优点是框架很轻量,更新时依赖少,并且专注安全方面的 bug;缺点是,你不得不自己做更多的工作,或通过添加插件增加自己的依赖列表。

Flask 的依赖如下:

  • Werkzeug 一个 WSGI 工具包
  • jinja2 模板引擎

Flask简单易学,下面是Flask版的hello world(hello.py):

安装Flask即可运行了:

Jinja 2

Jinja 2是一种面向Python的现代和设计友好的模板语言,它是以Django的模板为模型的。Jinja2 是 Flask 框架的一部分。

Jinja2 会把模板参数提供的相应的值替换了 {{…}} 块。Jinja2 模板同样支持控制语句,像在 {%…%} 块中:

Flask框架学习

最简单的Flask应用

代码作用:

  • 首先,导入Flask类。这个类的实例将会是我们的WSGI应用程序。
  • 接下来,创建一个该类的实例,第一个参数为应用模块或者包的名称。如果使用单一的模块,就需要使用__name__,因为模块的名称将会因其作为单独应用启动还是作为模块导入而有不同(即'__main__'或实际的导入名)。只有这样,Flask才能知道去哪找模版、静态文件等。
  • 然后使用route()装饰器告诉Flask什么样的URL才能触发函数。
  • 这个函数的名称也在生成URL的时候被特殊的函数采用,这个函数返回的就是我们想要显示在用户浏览器中的信息。
  • 最后使用run()函数来让应用运行在本地服务器上。其中if name=='__main__':确保服务器只会在该脚本被Python解释器直接执行的时候才会运行,而不是作为模块导入的时候。
  • 路由(装饰器)

  • 路由:@app.route()[app是Flask的实例化对象,可以改变]
  • 作用:Flask通过装饰器来识别用户需要访问的网址路径,并在对应的路径做出对应的操作。例如上述代码,当访问到"xxxxxx/"时,装饰器会触发[hello_world()]函数,从而在访问该URL时得到"Hello World!"
  • 例如:
  • 总结:route()装饰器就是把一个函数绑定在一个URL上,不仅如此,还可以构造含有动态部分的URL,也可以在一个函数上附着多个规则。

    变量规则

  • <>定义路由的变量参数,<>需要起个名字。
  • 注意:参数类型默认是字符串,使用unicode编码。
  • 给URL添加变量部分,可以把这些特殊字段标记为<var_name(自定义)>,这个部分将会作为参数传入到下面的函数中,并支持使用来进行转换。</var_name(自定义)>
  • 例如,需要注意的是,需要在函数的括号内输入变量名,后面的代码才可以正常运行:
  • 路由请求方式限定

  • 通过修改route()装饰器的methods参数可以改变路由对于服务器的请求方式(默认为GET)
  • 例如
  • 通过修改methods参数,通过'GET'和'POST'方法都可以对指定URL进行访问。

    关于Jinja2模版引擎

  • 模板:模板就是一个包含响应文本的文件,其中用占位符(变量)表示动态部分,告诉模板引擎其具体的值是需要从使用的数据中获取的。
  • 渲染:使用真实值来替换变量,在返回最终得到的字符串。
    Flask的渲染方法有render_template和render_template_string两种。
    render_template()是用来渲染一个指定的文件的。使用如下render_template_string则是用来渲染一个字符串的。SSTI与这个方法密不可分。
    使用方法如下
  • 返回一个模板文件。
    Flask是使用Jinja2来作为渲染引擎的。
    在网站的根目录下新建templates文件夹,这里是用来存放html文件。也就是模板文件。
  • 访问127.0.0.1:5000/index/的时候,flask就会渲染出index.html的页面。
    模板文件并不是单纯的html代码,而是夹杂着模板的语法,因为页面不可能都是一个样子的,有一些地方是会变化的。比如说显示用户名的地方,这个时候就需要使用模板支持的语法,来传参。
    例如:

    /templates/index.html

  • 例如:
  • 这个时候页面仍然输出This is index page。

    render_template()函数对模板进行渲染,第一个参数一定是模板的名称,之后的参数可以为模板中的变量代码块传递值,这个参数可以是整数、字符串、浮点数、字段、列表、函数等等。值得注意的是,后面的参数都使用键值对的形式,表示模板中对应变量的真实性。
    "index.html"是模板文件的名称,它是templates文件夹下的一个文件。

    模板中的代码块

  • 变量代码块
  • 变量使用双层大括号({{var_name}}),这就是变量代码块。
  • 注释:使用{# #}进行注释,如{#{{var_name}}#}
  • 控制代码块
    使用{% %}来定义控制代码块,可以实现一些逻辑功能,比如循环或者条件。
  • 比如:

    服务器端模板注入SSTI

    什么是服务器端模板注入?

    服务器端模板注入是指攻击者能够使用本机模板语法将恶意有效负载注入模板中,然后在服务器端执行该模板。

    模板引擎旨在通过将固定模板与易失性数据结合来生成网页。当用户输入直接连接到模板中而不是作为数据传递时,可能会发生服务器端模板注入攻击。这使攻击者可以注入任意模板指令以操纵模板引擎,从而经常使攻击者能够完全控制服务器。顾名思义,服务器端模板注入有效载荷是在服务器端交付和评估的,这可能使它们比典型的客户端模板注入更加危险。

    服务器端模板注入有什么影响?

    服务器端模板注入漏洞可能使网站受到各种攻击,具体取决于所讨论的模板引擎以及应用程序使用它的方式。在某些罕见情况下,这些漏洞不会带来真正的安全风险。但是,在大多数情况下,服务器端模板注入的影响可能是灾难性的。

    在规模最大的时候,攻击者可以潜在地实现远程代码执行,从而完全控制后端服务器,并使用它对内部基础结构进行其他攻击。

    即使在无法完全执行远程代码的情况下,攻击者通常仍可以使用服务器端模板注入作为其他众多攻击的基础,从而有可能获得对服务器上敏感数据和任意文件的读取权限。

    服务器端模板注入漏洞如何产生?

    当用户输入被串联到模板中而不是作为数据传递时,服务器端模板注入漏洞就会出现。
    简单来说也就是不正确的使用flask中的render_template_string方法会引发SSTI。
    仅提供占位符并在其中呈现动态内容的静态模板通常不容易受到服务器端模板注入的攻击。经典示例是一封电子邮件,其中用每个用户的名字打招呼,例如Twig模板中的以下摘录:

    这不易受到服务器端模板注入的影响,因为用户的名字仅作为数据传递到模板中。

    但是,由于模板只是字符串,因此Web开发人员有时会在呈现之前将用户输入直接连接到模板中。让我们以与上述示例类似的示例为例,但是这次,用户可以在发送电子邮件之前自定义部分电子邮件。例如,他们也许可以选择使用的名称:

    在此示例中,不是将静态值传递到模板中,而是使用GET参数动态生成模板本身的一部分name。在服务器端评估模板语法时,这可能使攻击者可以按以下方式将服务器端模板注入有效负载放置在name参数中:

    这类漏洞有时是由于不熟悉安全隐患的人对模板的不良设计导致的,也有的是有意实施的。例如,某些网站故意允许某些特权用户(例如内容编辑器)通过设计来编辑或提交自定义模板。如果攻击者能够利用这种特权来破坏帐户,则显然会带来巨大的安全风险。

    构建服务器端模板注入攻击

    确定服务器端模板注入漏洞并成功进行攻击通常涉及以下过程。

    检测

    最简单的初始方法是通过注入模板表达式中常用的特殊字符序列来使模板模糊,例如。如果引发异常,则表明服务器可能以某种方式解释了注入的模板语法。这表明服务器端模板注入可能存在漏洞。

    通过将数学运算设置为参数的值,我们可以测试这是否也是服务器端模板注入攻击的潜在入口点。
    例如,考虑一个包含以下易受攻击的代码的模板:

    我们还可能会通过请求URL来测试服务器端模板的注入,例如:

    如果结果输出包含Hello 49,则表明正在服务器端评估数学运算。这是服务器端模板注入漏洞的良好概念证明。
    请注意,成功评估数学运算所需的特定语法将根据所使用的模板引擎而有所不同。

    在其他情况下,该漏洞是通过将用户输入放置在模板表达式中来暴露的,就像我们之前在电子邮件示例中看到的那样。这可以采用将用户可控制的变量名放置在参数中的形式,例如:

    在网站上,生成的URL类似于:

    例如,这将在输出到中呈现Hello Carlos。

    实际在测试过程中,很容易就会忽略这个问题。因为它不会导致明显的XSS,并且与简单的哈希映射查找几乎没有区别。在这种情况下,测试服务器端模板注入的一种方法是,通过将任意HTML注入到值中,首先确定该参数不包含直接XSS漏洞:

    在没有XSS的情况下,这通常会导致输出中出现空白条目(只是Hello没有用户名),编码的标签或错误消息。下一步就是尝试使用通用模板语法突破该语句,并尝试在其后注入任意HTML:

    如果这又导致错误或输出空白,则说明使用了错误的模板语言提供的语法;如果没有模板样式的语法,则无法进行服务器端模板注入;如果输出和任意HTML一起正确呈现,则这表明存在服务器端模板注入漏洞:

    确定模版引擎

    一旦发现存在模板注入,下一步就是确定模版引擎。
    尽管存在大量的模板语言,但其中许多模板使用非常相似的语法,这些语法是专门为不与HTML字符冲突而选择的。结果,创建探测有效载荷以测试正在使用哪个模板引擎可能相对简单。
    通常只需提交无效的语法就足够了,因为产生的错误消息将准确告诉您模板引擎是什么,有时甚至是哪个版本。例如,无效表达式<%=foobar%>会触发基于Ruby的ERB引擎的以下响应:

    常用的方法是使用来自不同模板引擎的语法注入任意数学运算。

    SSTI漏洞

    首先来看一个简单的例子:

    访问页面后,输入id=1

    然后输入简单的XSS查看效果

    造成了XSS攻击。

    现在将代码进行修改

    再次输入XSS脚本查看效果

    发现被直接输出了。这是因为模板引擎一般都默认对渲染的变量值进行编码转义,这样就不会存在xss了。在这段代码中用户所控的是code变量,而不是模板内容。存在漏洞的代码中,模板内容直接受用户控制的。

    再来看一个例子:

    看到Template("Hello "+name),因为是Jinja2,所以参数方式为{{}},并且Template()完全可控。

    不过这个问题也并非是Jinja2的问题,而且在编写的过程中出现的。
    如果修改为下面这种,就不存在模板注入了。

    在Jinja2中是可以直接访问python的一些对象及其方法的,如字符串对象及其upper函数,列表对象及其count函数,字典对象及其has_key函数,那么怎么能够在Jinja2模板中访问到Python中的内置变量并且可以调用对应变量类型的方法,这就使用到了Python沙盒逃逸。

    其中Python的特性有:

    如果使用file对象读取文件,不能像字符串、列表一样直接进行引用,就需要使用Python的属性和方法。
    比如:

    这段代码,就是从列表获取到类,再取基类(object),再取object中的所有子类,再从子类中寻找file类,找到使用其构造方法创建对象后再用readlines读取文件内容。

    用Jinja2的语法:

    使用简单的代码进行测试

    构造参数{{22*33}}

    可以看到表达式被执行了。

    另外在Flask中也有全局变量。

    接下来看一下是如何获取到的,是一个怎么样的过程。
    1、获取字符串的类对象

    2、寻找基类

    3、寻找可用饮用

    4、加以利用

    这里使用vulhub进行测试。

    查看一下app.py的源码

    获取eval函数执行任意代码
    vulhub上的ssti文档直接给出了获取eval函数并执行任意python代码的poc

    简单的看一下代码,其实如果单写if&for语句,就好理解了。

    寻找方法:
    寻找__builtins__得到eval

    脚本不知道什么原因运行后也没有回显,如果各位大佬知道的话请教教小弟qwq。
    找到了一个python2/3都有__builtins__的类 _IterationGuard。

    找到python2/3通用的执行任意代码

    运行后:

    用jinja的语法即为(执行命令使用os.popen('whoami').read()才有执行结果的回显)

    不过需要注意的时,最好将POC转化为URL。

    不过关于SSTI最多的还是与Python沙盒逃逸相关,尤其是在相关比赛中。
    关于沙盒逃逸和CTF中常见的问题,将在下一篇文章中总结。

    参考(感谢大佬们的精彩文章):

    扫描二维码推送至手机访问。

    版权声明:本文由黑客接单发布,如需转载请注明出处。

    本文链接:https://therlest.com/106710.html

    分享给朋友:

    “Flask框架(jinja2)服务端模板注入漏洞分析(SSTI)” 的相关文章

    华流年京东618怎么买便宜

    京东618活动已经在火热进行中的哦,各位有买什么东西了吗?很多小伙伴在活动一开始的时候就迫不及待的买了很多东西了,还有些小伙伴还很犹豫不知道买啥,接下来百思特小编就来教教大家2020年京东618怎么便宜吧~ 京东618怎么买便宜 活动时...

    黑客了解,中国黑客越南网络apt,黑客网站密码破解工具

    6.42 · hxxp[://]offlineearthquake[.]com/file//?id=&n=000 进程三:使命履行及实时数据剖析10.61 2019年6月19日,FireEye Endpoint Security设备上收到了缝隙检测警报。 违规应用程序被辨认为Microso...

    安宫牛黄丸现在价格 - 天地和堂安宫牛黄丸多少钱

    一丸280元左右.装同仁堂安宫牛黄丸,那个年代的这个玩意,中医说法多少,体外培育牛黄。 两丸,字[2000]201号\制定安宫牛黄丸等药品价格的批复,到正规的同仁堂自己品牌的药店购买,价格不一样,希望懂得.天然牛黄天然麝香。北京同仁堂牛黄解毒丸的市场价格在2005年。 绿色木盒这三种包装的价格一样,...

    威海海景房房价走势 - 山东威海海景房骗局

    我是在乳山银滩买房的,多谢啦!可能是真实情况。 晚上夕阳衬着大海格外美丽,石岛房子要比银滩强的多。骗局倒是谈不上,是一个新兴的旅游区的新城,一般购房者以外地居民多,估计也是房子价格的一部分吧,那收入会更高,我家刚在D区买了房子,环境以及二十多公里的原生态沙滩形成。 但都在下面县级市的镇的郊区.听老妈...

    实用的刷卡门禁一体机 - 门禁设置说明书

    2011-04-0511:45:53卡号:方向:未知,具体操作说明:门禁控制器,还要看你们所用的门禁是ID的还是IC的。具体的可以根据说明书操作。 手动开门[1 的大门2011-04-0511:45:43[1 大门无效用户刷卡时间,你这个说的真不知道怎么回答你。蜂鸣器连续断续鸣响报警,具体到可以统计...

    如何寻找黑客微信号(只有一个微信号,黑客可以查到对方吗)

    一、如何寻找黑客微信号(只有一个微信号,黑客可以查到对方吗) 1、有黑客能查到微信聊天记录是骗人的吗绝对是骗子,请勿相信! 微信聊天信息保存在本地 一般聊天信息都是保存在本地的,除非开通会员可以将聊天信息存储。 黑客查找出来的微信聊天截图是真的吗在手机端启动微信,在微信主界面底部导航中点击“微信”...

    评论列表

    离鸢吝吻
    2年前 (2022-07-03)

    机模板语法将恶意有效负载注入模板中,然后在服务器端执行该模板。模板引擎旨在通过将固定模板与易失性数据结合来生成网页。当用户输入直接连接到模板中而不是作为数据传递时,可能会发生服务器端模板注入攻击。这使攻击者可以注入任意模板指令以操纵模

    只酷初霁
    2年前 (2022-07-04)

    ds参数可以改变路由对于服务器的请求方式(默认为GET)例如通过修改methods参数,通过'GET'和'POST'方法都可以对指定URL进行访问。关于Jinja2模版引擎模板:模板就是一个包含响应文本的文件,其中用占位符(变量)表示动态部分,告诉模板引擎其具体的值是需要从使用的数据中获取

    发表评论

    访客

    ◎欢迎参与讨论,请在这里发表您的看法和观点。