【入門編】SSTIを防ぐための安全なテンプレート設計とコンテキスト分離 – アプリケーションセキュリティ & 安全な開発防御ガイド

テンプレートエンジンは「魔法の箱」じゃない!SSTIから身を守るための基礎知識

こんにちは!セキュリティの現場で日々、泥臭い攻防を繰り広げているエンジニアです。

今日は、Web開発で避けては通れない「テンプレートエンジン」と、そこに潜むちょっと怖い落とし穴「SSTI(Server-Side Template Injection)」についてお話しします。

「テンプレートエンジンなんて、ただの表示ツールでしょう?」と思っているなら要注意。実は、ここを適当に扱うと、あなたの家の玄関の鍵を、泥棒自身に開けさせるような事態を招いてしまうんです。

—

1. SSTIって何?身近な例で考えてみよう

まずは、SSTIを「手紙の代筆」に例えてみましょう。

あなたが「お客様への挨拶文」を自動生成するシステムを作ったとします。
テンプレートには「こんにちは、{{name}}さん!」と書いてあり、プログラム側でnameに「田中さん」を入れると、「こんにちは、田中さん!」と表示されますよね。

ここで悪意ある泥棒(攻撃者)がやってきて、nameの場所に、こんな細工を仕掛けたらどうなるでしょうか?

  • 「田中さん」ではなく、「{{system.delete_all_files()}}」という「呪文」を入力する。

もしテンプレートエンジンがこの呪文を「あ、これは命令だ!」と勘違いして実行してしまったら……はい、システムは大惨事です。これがSSTIの正体。ユーザーの入力が「データ」としてではなく「命令」として解釈されてしまう脆弱性なんです。

—

2. なぜ「サンドボックス」だけでは不十分なのか

多くのテンプレートエンジンには「サンドボックス(砂場)」という機能があります。「ここから外には出ちゃダメだよ」という遊び場です。

でも、考えてみてください。砂場の柵を乗り越える子供(攻撃者)がいたらどうしますか?
実は、テンプレートエンジンの多くは、PythonやJavaといった言語の内部構造にアクセスする「抜け道」を持っています。サンドボックスはあくまで「お行儀よく遊ぶためのルール」であって、「絶対的な檻」ではないことを理解しておく必要があります。

—

3. SSTIを防ぐ「鉄則」:ロジックとビューを切り離せ!

SSTIを防ぐための最大の秘訣は、「テンプレートの中に、計算や命令を書かせないこと」です。

悪い例:テンプレートの中でロジックを動かす


ようこそ、{{ user.name }}さん

良い例:データは「完成品」として渡す

テンプレートはあくまで「表示用」と割り切り、必要なデータはすべてプログラム側(コントローラー)で準備してから渡しましょう。

【Python (Flask/Jinja2) の例】

悪い例:テンプレートで何でもできちゃう状態
return render_template_string(f”Hello {user_input}”)

良い例:安全な実装
@app.route(“/greet”)
def greet():
# ユーザー入力をそのままテンプレートに埋め込まず、
# 処理済みの「ただの文字列」として渡すのが鉄則です!
user_name = get_sanitized_name(request.args.get(“name”))
return render_template(“greet.html”, name=user_name)

【greet.html (テンプレート側)】

ようこそ、{{ name }}さん

—

4. 開発現場で今すぐできる「防御の3ステップ」

明日からの開発で、ぜひ意識してほしいポイントをまとめました。

1. ユーザー入力を直接テンプレートの引数にしない

  • テンプレートエンジンの構築メソッド(render_template_stringなど)に、ユーザーからの入力をそのまま文字列連結で渡すのは「鍵をポストに放置する」のと同じくらい危険です。

2. テンプレート変数をエスケープする

  • ほとんどのモダンなエンジン(Jinja2など)は自動でエスケープしてくれますが、設定を無効化(|safeフィルターを多用するなど)していないか、一度見直してみましょう。

3. 「ロジックはバックエンドに隠す」

  • ビュー(HTML)は「見た目」だけを整える場所。データベースの参照やファイル操作などの「重い処理」は、すべてバックエンドの関数に隠して、テンプレートには「結果の文字列」だけを渡すように設計してください。

—

まとめ:セキュリティは「疑うこと」から始まる

セキュリティは難しいと思われがちですが、根本にあるのは「自分の庭(システム)には、招かれざる客が泥棒の格好をしてやってくるかもしれない」という想像力です。

テンプレートエンジンは非常に便利ですが、その便利さの裏には「命令を実行できる」というパワーが隠されています。そのパワーをユーザーに渡さないこと。これだけで、あなたのシステムは格段に堅牢になります。

一歩ずつ、安全なコードを書いていきましょう。応援しています!

コメント

タイトルとURLをコピーしました