プログラミング学習サイト

プログラミング学習サイト

👦 対象者

  • プログラミング入門本を読み終わった学生
  • キャリアの方向性に迷いが出てしまったエンジニア

🏁 ゴール

このサイトの目標は、プログラミングに入門したての新米エンジニアに対して、プログラミング学習の「目的」と「手段」を見つけるヒントを示すことです。

📗 目次

🦫 筆者

みねぎしれい

和光市在住の26歳エンジニアです。 バックエンドもフロントエンドもちょこっとできますがインフラやセキュリティが好きです☺️

🏢 職歴

  • Cardio Flow Design(2年:アルバイト)
  • ニトリホールディングス(3年:情報システム改革室)
    • 家具製品開発システム : 商品企画プロセスを改善する社内のシステムを構築。フロントエンド~バックエンドまで担当
    • ODBC対応 : 保守切れとなる社内のデータベース接続方式を変更する対応。VBA,BV6で書かれた300以上のソースコードを改修する。
    • その他保守運用 : ニトリネットの保守運用作業
  • ITソリューション事業
    • 秘密❤️
  • 現職(人材業界)

page:https://minegishirei.hatenablog.com/entry/2023/01/27/193827

テンプレートインジェクション

テンプレートインジェクションとは

テンプレートエンジンはHTMLを描画する際に、その中のプレースホルダーを自動的に埋めることができる機能です。 これにより、サーバーサイドでレンダリングするタイプのWebサイトはPythonやNodeの値を直接HTMLに埋め込むことができます。

テンプレートインジェクションは、テンプレートエンジンがユーザーからの入力を適切にサニタイズせずに描画するときに発生するもので、 リモートコード実行につながる可能性があります。

リアルワールドバグハンティングによると、 テンプレートインジェクションはサーバーサイドとクライアントサイドの2種類が存在します。

テンプレートエンジンの具体例

テンプレートエンジンを使わずに FlaskのみでWebの描画を行おうとすると、以下のようなコードになります。

from flask import Flask
app = Flask(__name__)

@app.route("/")
def index():
  return "<h1>Hi, Flask!</h1>"

if __name__ == "__main__":
  app.run(host="0.0.0.0", port=80, debug=True)

シンプルなサイトであればこちらでも問題ないですが、規模が大きくなるとビジネスロジックと描画を分ける必要性が出てきますが、 Pythonではこのようなケースで、 Jinja2 というライブラリが活躍します。

import random
from flask import Flask, render_template
from flask import request
app = Flask(__name__)

@app.route("/",methods=['GET', 'POST'])
def index():
    query = 3
    if request.method == 'GET':
        query = request.args.get('query', '')
    return render_template("index.html", query = query)

if __name__ == "__main__":
  app.run(host="0.0.0.0", port=80, debug=True)

上記のソースコードで、 index.htmlのパスを指定し、ランダムな変数 rand_numをテンプレートに渡しています。

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>Flask</title>
        <style>body {padding: 10px;}</style>
    </head>
    <body>
        <h1>あなたがqueryパラメーターに入力したのは</h1>
        <p>文字列 : {{query}}</p>
    </body>
</html>

渡された変数 rand_num テンプレートの構文 {{}} によって描画することができます。 それだけでなく、 {% %} 構文によって比較を行うことも可能です。

このように、テンプレートエンジンによって描画部分とビジネスロジックを明確に分離することが可能です。

テンプレートエンジンを動かしてみる

上記のテンプレートエンジンのソースコードは次のリポジトリからお試しで実行できます。

git clone https://github.com/minegishirei/hacking_lab

テンプレートインジェクションの具体例

テンプレートエンジンでは、上記の通りデータを埋め込むために特定の構文を使って式を埋め込みますが、 外部からユーザーが入力した内容をそのままテンプレートに挿入すると、予期しないコードが実行されるリスクが生じます。

上記のテンプレートは正常な使い方なので問題ないですが、以下のように適切にサニタイズできないと危ないコードになります。

from flask import Flask, request
from jinja2 import Environment

app = Flask(__name__)
Jinja2 = Environment()

@app.route("/")
def page():

    name = request.values.get('name')
    
    # SSTI VULNERABILITY
    # The vulnerability is introduced concatenating the
    # user-provided `name` variable to the template string.
    output = Jinja2.from_string('Hello ' + name + '!').render()
    
    # Instead, the variable should be passed to the template context.
    # Jinja2.from_string('Hello {{name}}!').render(name = name)

    return output

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)
  • 通常の使い方

通常の使い方であれば、 GETのnameパラメーターに自分の名前を入れると思います。

http://localhost/?name=minegishi

と入力するとHello yamada!と出力されます。

  • テンプレートインジェクションの例

Jinjaをターゲットとしたテンプレートインジェクションでは、{{7*7}}を入力して、49が出るかどうかを確認するのがよさそうです。

http://localhost/?name={{7*7}}

tplmapのセットアップ

tplmapはgithubソースコードで、docker-compseを使用することで起動できます。

git clone https://github.com/epinna/tplmap.git
cd tplmap
cd docker-envs
docker-compose up

page:https://minegishirei.hatenablog.com/entry/2024/11/01/201520