1、概念
SSTI是一种常见的Web安全漏洞,它允许攻击者通过注入恶意模板代码,使服务器在渲染模板时执行非预期的操作。
(1)渲染模版
至于什么是渲染模版:服务器端渲染模板是一种Web开发技术,它允许在服务器端动态生成HTML页面或其他格式的输出内容,而不是在客户端(浏览器)生成。这种技术的核心是模板引擎,它允许开发者将动态内容嵌入到静态模板中,从而生成最终的页面
<1>模版引擎的作用
模版引擎的主要作用是将模板(一种包含占位符的静态文件)与数据(动态内容)结合,生成最终的输出内容。
<2>模版引擎的功能:
变量替换:将模板中的占位符替换为实际的数据。
条件语句:根据条件动态生成内容。
循环语句:根据数据集合生成重复的内容。
模版继承:允许一个模板继承另一个模板的结构。
而常见的模版引擎有:Django、jinja2、Twig、EJS
<3>服务器端渲染模版的工作原理
假设有一个Web应用,用户访问某个页面时,服务器需要动态生成HTML内容。
服务器端渲染模板的基本工作流程为:
用户请求页面:用户通过浏览器发送HTTP请求,请求某个页面。
服务器接收请求:服务器接收到请求后,解析请求参数。
加载模版文件:服务器加载预定义的模板文件,模板文件中包含占位符。
数据绑定:服务器将动态数据绑定到模板中的占位符
生成最终内容:模板引擎将模板和数据结合,生成最终的HTML内容。
返回响应:服务器将生成的HTML内容返回给浏览器,浏览器渲染并显示页面。
<4>示例 (使用Python的Jinja2模板引擎)
假设此刻有一个简单的web应用,使用Flask框架和Jinja2模板引擎来动态生成HTML页面。
模版文件(template.html)
<!DOCTYPE html>
<html>
<head><title>{{ title }}</title>
</head>
<body><h1>{{ heading }}</h1><p>{{ content }}</p>
</body>
</html>
这个模板文件中包含了三个占位符:{{title}}、{{heading}} 和 {{content}}。
假如在Jinja2模版中,我们用Python代码这样来渲染文件(app.py):
from flask import Flask, render_templateapp = Flask(__name__)@app.route('/')
def index():# 动态数据data = {'title': 'My Page','heading': 'Welcome to My Page','content': 'This is a dynamic content.'}# 使用render_template渲染模板return render_template('template.html', **data)if __name__ == '__main__':app.run(debug=True)
在这个代码中:
1、render_template 函数 将模板文件 template.html 和动态数据 data 结合起来。
2、模板引擎会将 {{title} 替换为 "My Page", {{"heading"}} 替换为 'Welcome to My Page' , {{'content'}} 替换为 'This is a dynamic content'
3、最终生成的HTML内容会发送给浏览器。
然后当我们访问这个Web应用时,浏览器会收到以下HTML内容:
<!DOCTYPE html>
<html>
<head><title>My Page</title>
</head>
<body><h1>Welcome to My Page</h1><p>This is a dynamic content.</p>
</body>
</html>
这个过程就是服务器端渲染模板。
(2)非预期操作
而非预期操作又指的是什么呢:别看这些词这么高大尚,其实通俗的讲就是指在软件或系统中执行的、未被设计或预期的操作。(非预期操作)在Web安全领域,非预期操作通常是指攻击者通过漏洞或缺陷,使应用程序执行了开发者未预期的操作.
<1>非预期操作的类型
信息泄露:攻击者通过漏洞获取服务器上的敏感信息,如配置文件内容、环境变量等。
代码执行:攻击者通过漏洞执行任意代码,从而控制服务器。
权限提升:攻击者通过漏洞提升系统权限,进一步控制服务器。
拒绝服务攻击(Dos):攻击者通过漏洞使服务器无法正常提供服务。
输入验证不足、错误的逻辑实现、配置错误都是非预期操作的成因。
<2>示例(还是使用Python的Jinja2模板引擎)
同样假设我们有一个简单的Web应用,允许用户输入一些内容,然后将这些内容显示在页面上。但是,我们没有对用户输入进行过滤。
模版文件(template.html)
给一个html模版:
<!DOCTYPE html>
<html>
<head><title>User Input</title>
</head>
<body><p>You entered: {{ user_input }}</p>
</body>
</html>
Python代码(app.py):
from flask import Flask, request, render_templateapp = Flask(__name__)@app.route('/')
def index():# 获取用户输入user_input = request.args.get('input', '')# 渲染模板并显示用户输入return render_template('template.html', user_input=user_input)if __name__ == '__main__':app.run(debug=True)
两种情况:
1、正常情况
如果用户通过URL /?input=Hello 访问页面,页面会显示:
<!DOCTYPE html>
<html>
<head><title>User Input</title>
</head>
<body><p>You entered: Hello</p>
</body>
</html>
2、非预期操作
如果用户通过URL /?inpput={{5+3}} 访问页面,Jinja2模板引擎会执行 5+3 ,页面会显示:
<!DOCTYPE html>
<html>
<head><title>User Input</title>
</head>
<body><p>You entered: 8</p>
</body>
</html>
这是开发者未预期的操作,因为用户输入的模板代码被模板引擎执行了,所以叫非预期操作。
那么要是再严重一点:
如果用户通过URL /?input={{config.items}} 访问页面,Jinja2模板引擎会执行 config.items() ,可能会返回应用程序的配置信息,导致信息泄露。
2、SSTi的原理
之前说模板引擎允许开发者将动态内容嵌入到静态模板中,以便生成最终的HTML页面或其他格式的输出。but,如果没有对用户输入进行严格的验证和过滤,攻击者可以注入恶意的模板代码,从而在服务器端执行一系列操作(非预期,不可知)。
3、SSTI的危害
所以总的来说还是有三个危害:
信息泄露;
代码执行;
权限提升
4、分类
SSTI 漏洞主要分为两类:简单的模板注入和复杂的模板注入。
(1)简单模版注入
攻击者直接注入模板代码,使服务器在渲染模板时执行恶意操作
(2)复杂模版注入
攻击者通过构造复杂的模板代码,绕过应用程序的输入验证和过滤机制。
5、例题
NSSCTF
【HDCTF 2023】SearchMeaster
启动
你可以使用POST请求给我发送DATA
也不知道发送什么,注意到题目search,用dirsearch扫描一下目录
结果扫了一下又没扫出来
那就还是用nikto扫一下ip
可以看到Target IP 为1.14.71.254
结果还是没连上
后面在端口前面加冒号:就连上了(我也纳闷,在kali里有时候接端口是空格,冒号不行,有时候又得冒号,但物理机url包是冒号的)
可以看到有一个composer.json可用
访问一下
直接得到提示是smart模版
说明存在ssti模版注入
返回原页面传 data={ ,报错,证明存在RCE漏洞(报错表明模板引擎尝试解析和执行了我传递的模板代码。)因为之前说过RCE漏洞是应用调用代码执行函数或系统命令执行函数,导致远程代码执行或系统命令执行 ,这里典型的是尝试执行了命令然后无果
这样一来就可以利用SSTI模版注入结合RCE漏洞执行命令来达到目的了
想确认smart模版的话试试{4*4}是否能回显16
可以看到有16,无疑存在smart模版 (没被骗haha)
那直接构造payload就可以了
data={if system('ls /f*')}{/if}
smart模版引擎的条件语法
{if} {/if} 标签
{if}:开始条件判断;
{/if}:结束条件判断
在该模版引擎中执行 system函数 system()不用说了
'ls /f*':要执行的系统命令,用于列出 /f* (f字符开头,用于提高查找flag的效率)目录下的文件
执行后得到flag路径
继续替换system命令即可
data={if system('cat /flag_13_searchmaster')}{/if}
get flag