FlawOpen

flawopen.com/SSTI/解説

サーバーサイドテンプレートインジェクションとは?

CWE-1336: Server-Side Template Injectionリファレンスページ
要点

サーバーサイドテンプレートインジェクションは、信頼できない入力をデータとして渡さず、テンプレートソースとして解析させることで発生します。影響はエンジン、設定、公開された機能に依存し、式の評価からサーバー側コード実行まで幅があります。すべての SSTI がコード実行につながるわけではありません。

脆弱 — 入力がテンプレートを構築
# Python / Jinja2
template = f"Hello {name}!"
return render_template_string(template)

# Input: {{ 7*7 }} renders as "49"
# This confirms expression evaluation;
# impact still depends on engine access.

// Java / Freemarker
String tpl = "Welcome " + userName;
new Template("t", tpl, cfg)
    .process(model, out);
修正済み — 入力はデータ
# The template is a fixed string the
# developer wrote. The user value is
# passed in as a variable.
return render_template(
    "greeting.html", name=name
)

# Or with a literal template string:
return render_template_string(
    "Hello {{ name }}!", name=name
)

// Java equivalent: template from file,
// user value in the model map.

重要な違い

テンプレートエンジンの入力はテンプレートとコンテキストデータの二種類です。テンプレートはプログラムであり、データはそのプログラムが読む値です。SSTI はユーザー入力をデータからテンプレートソースへ越境させることで起こります。

これはデータをクエリ文字列に連結する SQL インジェクションと同じ構造上の誤りです。また、ログを経由してデータが式評価器に届いた Log4Shell とも同様です。対策の原則は共通で、プログラムを固定し、信頼できない値をパラメーターとして渡します。

コード実行に至る可能性がある条件

テンプレートエンジンが強力なオブジェクトやメソッドを公開すると、攻撃者がアプリケーションの機密機能に到達する可能性があります。コード実行の可否はエンジン、バージョン、設定、サンドボックス、公開データに依存します。情報漏えいやリソース枯渇もあり得ます。ユーザー制御のテンプレートソースはアクティブなロジックとして扱い、アクセス可能なオブジェクトや描画リソースを制限せずにサンドボックスだけに依存しないでください。

検出方法

{{7*7}} ${7*7} <%= 7*7 %> #{7*7}

応答にリテラル文字列ではなく 49 が含まれる場合、入力がテンプレート構文として評価されています。短い算術式は許可されたテスト環境で評価の有無を調べるのに役立ちます。構文はエンジンごとに異なり、それだけで確実な特定はできません。

よくある質問

XSS と同じですか?

いいえ。クライアント側テンプレートインジェクションは被害者のブラウザーで実行され、XSS の一種となる場合があります。SSTI はサーバー上のアプリケーションプロセスで評価されます。影響はエンジンと公開機能によって異なり、一部の設定ではコード実行が可能ですが、すべての SSTI で自動的に起きるわけではありません。

自動エスケープで防げますか?

いいえ。自動エスケープは描画される値を処理しますが、値がテンプレート構文として解析されることは防ぎません。出力時の XSS 対策であり、テンプレートソースへの注入対策ではありません。

管理者だけがテンプレートを編集できるなら安全ですか?

ユーザー提供のテンプレートソースを実行ロジックとして扱い、既定ではアプリケーションの主要コンテキストで処理しないでください。必要な場合は制限されたテンプレート向けのエンジンを使い、最小限の不活性データだけを公開して、CPU、メモリー、出力サイズ、時間を制限します。サンドボックスだけでは完全なセキュリティ境界になりません。

参考資料

関連項目 SSTI:テンプレートインジェクションの原因と対策 FreeMarker/Velocity SSTI:テンプレートを安全に使う Jinja2 の render_template_string() は安全か