Server-Side Template Injection (SSTI): 攻撃者コード実行の危険性 🎨

現代Webアプリケーションに潜む隠れた危険性の理解
Webアプリケーションのセキュリティにおいて、Server-Side Template Injection (SSTI) は最も重要かつ見落とされがちな脆弱性の一つです。攻撃者がテンプレートのネイティブ構文を悪用し、悪意のあるペイロードを注入すると、そのテンプレートはサーバー側で実行され、攻撃者にサーバーの完全制御を許す可能性があります。この脆弱性は近年増加傾向にあり、過去3ヶ月で毎週16組織のうち1組織がSSTI攻撃の影響を受けています。
Server-Side Template Injectionとは何か?
テンプレートエンジンは動的Webコンテンツ生成の基盤です。固定されたテンプレートと変動データを組み合わせてWebページを作成します。代表的なテンプレートエンジンにはJinja2 (Python)、Handlebars (JavaScript)、Thymeleaf (Java)、Twig (PHP)などがあります。これらのツールはプレゼンテーションロジックとビジネスロジックを分離し、開発を高速化し、コードの保守性を向上させます。
しかし、この力には代償も伴います。SSTIの脆弱性は、未サニタイズのユーザー入力をテンプレートエンジンに直接連結した場合に発生し、攻撃者が悪意のあるテンプレート構文を注入してサーバー側で評価させることが可能となります。これは、ユーザー入力を単なるデータとして扱わず、実行可能なテンプレートコードとして処理してしまう危険な誤用です。
テンプレートエンジンの仕組み
テンプレートエンジンは静的なテンプレートと動的データを統合してWebページを生成します。例:
<h1>ようこそ、{{ username }}!</h1>
安全な実装では、username 変数はデータとして渡され、適切にエスケープされます。しかし、開発者がユーザー入力をテンプレート文字列に直接連結すると、災いが起きる可能性があります:
# 脆弱なコード
template = "ようこそ、" + user_input + "!"
render_template_string(template)
このコードは、攻撃者にテンプレート式を注入させる扉を開きます。
脅威の現状:2024-2025年のSSTI
Atlassian Confluence、CrushFTP、Rejetto HTTP File Serverなどの有名プラットフォームが標的となり、SSTI脆弱性を突かれて成功裏に攻撃された事例もあります。CISAはこれらの事例を強調し、その重要性を示しています。最近の脆弱性には、Logpointのバージョン7.5.0未満でCVE-2024-56085として報告されたものもあり、認証済みユーザーがSearch Template Dashboards作成時にペイロードを注入できるケースもあります。
統計データは深刻な状況を示しています。直近3ヶ月で、リテール・卸売業界は最も影響を受けており、毎週11組織中1組織がSSTI攻撃の被害に遭っています。この業界の脆弱性は、多数の取引、顧客の重要情報、複雑なサードパーティ連携に起因し、攻撃の表面積を拡大しています。
さらに、クラウドベースの組織はオンプレミスの組織よりも約30%多くSSTI攻撃を受けており、設定ミスやサードパーティ連携、セキュリティ対策のギャップが原因と考えられます。
人気のテンプレートエンジンとその脆弱性
Jinja2 (Python/Flask)
Jinja2はPythonのWebフレームワーク、特にFlaskで広く使われています。脆弱なFlaskアプリ例:
@app.route("/page")
def page():
name = request.values.get('name')
output = Jinja2.from_string('こんにちは ' + name + '!').render()
return output
攻撃者は{{7*7}}をnameパラメータに送信し、49と評価させることが可能です。これはXSSとSSTIの両脆弱性を示し、ユーザー入力を適切にサニタイズしない点に問題があります。
リモートコード実行のために、攻撃者はPythonのオブジェクト内省機能を利用して危険なモジュールにアクセスできます:
{{ self._TemplateReference__context.cycler.__init__.__globals__.os }}
このペイロードはPythonのオブジェクト階層を辿り、osモジュールにアクセスし、コマンド実行を可能にします。
Handlebars (JavaScript/Node.js)
HandlebarsはJavaScriptのロジックレステンプレートエンジンです。設計上安全性を高めるためにロジック制限がありますが、設定ミスにより脆弱性が生じることもあります。ヘルパー関数やプロトタイプ汚染を悪用してコード実行に至るケースもあります。
Thymeleaf (Java/Spring)
Thymeleafは特定の属性内に式を配置しますが、[[...]]や[(...)]の構文を使った式インライン化もサポートし、[[${7*7}]]は簡単なSSTIテストペイロードとなります。ただし、Thymeleafのデフォルト設定では動的テンプレート生成はサポートされておらず、開発者はTemplateResolverを自作して文字列からテンプレートを動的に作成する必要があります。
脆弱な場合、ThymeleafのSSTIは壊滅的な結果をもたらす:
${T(java.lang.Runtime).getRuntime().exec('悪意のあるコマンド')}
Twig (PHP)
TwigはJinja2に似た構文を持ち、PHPアプリケーションでよく使われます。脆弱な実装では攻撃者が任意のPHPコードを実行可能:
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
なぜSSTIはSQLインジェクションより危険なのか
SQLインジェクションは依然として重要な脆弱性ですが、SSTIはより大きなリスクをもたらすことがあります。理由は以下の通り:
1. 直接サーバーアクセス
SQLインジェクションはデータベース操作に限定されますが、SSTIではリモートコード実行やサーバーの完全乗っ取りが可能です。その後、内部インフラへの攻撃や横展開も行えます。これはデータベースアクセスよりもはるかに強力です。
2. セキュリティコントロールの回避
SQLインジェクションはデータベースの権限やストアドプロシージャに制約されますが、SSTIはWebアプリケーションのコンテキスト内で実行され、しばしばアプリケーションの全権限を持ちます。攻撃者はアプリケーションサーバーの権限を継承します。
3. マルチステージ攻撃プラットフォーム
遠隔コード実行ができなくても、SSTIを利用して機密情報やファイルの読み取り、資格情報の窃取、内部ネットワークへのピボットなど多様な攻撃が可能です。SQLインジェクションは基本的にデータ抽出に限定されますが、SSTIはファイルシステムアクセスや設定ファイルからの情報窃取も可能です。
4. 検出の難しさ
従来のセキュリティツールはSQLインジェクションのパターンを検知しやすいですが、SSTIはそうではありません。OSのイベントを監視するEDRやCWPPは、SSTIの発生箇所を捉えにくく、シグネチャベースのWAFもパターンの変化に対応しづらいです。
5. 複雑なエクスプロイト経路
サンドボックスは突破しにくいですが、リフレクションAPIやシリアライズの脆弱性を突くエスケープ手法も存在します。最新のエクスプロイトツールは何百ものペイロードを自動生成し、防御を突破しようとします。
実世界の攻撃シナリオ
シナリオ1:E-グリーティングカードアプリ
ユーザーがメッセージを入力し、それをHTMLテンプレートに埋め込むWebアプリを考えます。もし直接テンプレート文字列にユーザー入力を連結していると、攻撃者は以下を注入可能:
{{config.items()}}
これにより、アプリの設定変数が露出し、データベースの資格情報やAPIキーなどの機密情報が漏洩する恐れがあります。
シナリオ2:PDF請求書生成
請求書やメールのテンプレートに悪意のあるコードを埋め込み、サーバー側で生成時に実行させると、リモートコード実行につながります。これにより、攻撃者はサーバー上で任意のコマンドを実行可能です。
シナリオ3:マーケティングメールキャンペーン
テンプレートエンジンはトランザクションメールの生成に使われるため、SMTPリレーの設定ミスやMXレコードの誤設定と相まってリスクが増大します。攻撃者はSSTIを利用して内部メッセージを読み出したり、顧客情報を窃取したり、正規インフラからフィッシングメールを送信したりできます。
SSTIの検出方法
初期検出
静的アプリケーションセキュリティテスト、動的テスト、ランタイム監視を開発パイプラインに組み込み、脆弱性を事前に検知します。
最も一般的な検出方法はポリグロットペイロードを用いたファジングです:
# SSTImapを使った例
python3 sstimap.py -u 'https://example.com/page?name=test' --level 5
このペイロードは、SSTIの脆弱性があればエラーを引き起こします。Hackmanitのテンプレートインジェクション表は、44の主要テンプレートエンジン向けの効率的なポリグロットを提供しています。
数式式のテスト
簡単な初期テストは、数学式を注入することです:
{{7*7}}
${7*7}
<%= 7*7 %>
${{7*7}}
#{7*7}
サーバーが49を返せば、テンプレートインジェクションが確認されます。
テンプレートエンジンの特定
インジェクションが確認されたら、さまざまな構文パターンを試して特定します:
- Jinja2/Twig:
{{7*7}}が49を返す - Smarty:
{7*7}が49を返す - Thymeleaf:
[[${7*7}]]が49を返す - FreeMarker:
${7*7}が49を返す - Velocity:
#set($x=7*7)$xが49を返す
エンジンごとに構文や機能が異なるため、この識別は重要です。
高度なエクスプロイト技術
サンドボックスの突破
多くのテンプレートエンジンは危険な操作を制限するサンドボックスを実装していますが、攻撃者は巧妙な手法でこれを回避します。
例:Jinja2では、Pythonのオブジェクト階層を辿って制限されたモジュールにアクセス:
{{''.__class__.__mro__[1].__subclasses__()}}
このペイロードはPythonの全クラスを列挙し、os.system()やsubprocess.Popen()といった危険なメソッドを見つけ出します。
機密ファイルの読み取り
任意のファイルを読み取る例:
{{''.__class__.__mro__[1].__subclasses__()[40]('/etc/passwd').read()}}
リモートコード実行の実現
コマンド実行は持続性や横展開に利用され、攻撃者はSSHキーを書き込み、cronジョブを設定し、Webシェルを設置します。
例:
Jinja2:
{{config.__class__.__init__.__globals__['os'].popen('whoami').read()}}
Thymeleaf:
__${T(java.lang.Runtime).getRuntime().exec("touch /tmp/pwned")}__::.x
Ruby ERB:
<%= system('whoami') %>
自動エクスプロイトツール
Tplmapなどのツールは適切なペイロードを自動選択し、エンコードも処理してシェルを瞬時に展開します。AI駆動のフレームワークは何百ものユニークなSSTIペイロードを生成し、防御を突破しようとします。
代表的なツール: - Tplmap: SSTIの自動検出とエクスプロイト - SSTImap: マルチエンジン対応のインタラクティブスキャナー - Tinja: 新規ポリグロットを用いた効率的検出
防止と対策
1. ユーザー入力を連結しない
最重要ルール:ユーザー入力をテンプレート文字列に直接連結しない。常にパラメータとして渡す:
脆弱な例:
template = "こんにちは " + user_input + "!"
render_template_string(template)
安全な例:
render_template('hello.html', username=user_input)
render_templateを使い、事前定義されたテンプレートに変数を渡すことで、Jinja2は自動的にエスケープし、安全にします。
2. ロジックレステンプレートエンジンの使用
攻撃リスクを低減するには、入力の検証、ロジックレスまたはサンドボックス化されたテンプレートへの切り替え、テンプレートエンジンの最新パッチ適用が必要です。MustacheやHandlebars(適切に設定された場合)は、実行可能なロジックを制限し、攻撃面を最小化します。
3. 入力検証の実施
静的アプリケーションセキュリティテストは、最初の防御線です。テンプレート作成時に信頼できない入力や危険なレンダリングヘルパーを呼び出す関数を検出するルールを設定します。例:
- Flaskの
render_template_string(request.*)や文字列連結を検出
4. コンテンツセキュリティポリシー
厳格なCSPを設定し、悪意のあるスクリプトの実行を防ぎます。これにより、SSTI脆弱性があっても二重の防御層となります。
5. Webアプリケーションファイアウォール
{{...}}や${...}、<%...%>などのテンプレート構文パターンを検知するルールを持つWAFを導入します。ただし、変数名や空白、エンコーディングの微妙な変更で回避される可能性もあります。
6. ランタイムアプリケーション自己防護
最新のセキュリティソリューションは、テンプレートがレンダリングされる際の挙動を監視し、悪意のある動作を検知・阻止します。これにより、未知の攻撃も防御可能です。
7. 最小権限の原則
テンプレートレンダリングを最小限の権限で実行し、脆弱性が悪用された場合の被害を抑えます。
8. 定期的なセキュリティ監査
開発者はテンプレートエンジンのドキュメントの”セキュリティに関する考慮”を見落としがちです。定期的なコードレビューとテンプレート使用パターンの監査が脆弱性の早期発見に役立ちます。
避けるべき脆弱パターン
パターン1:ユーザー制御のテンプレート選択
# 危険
template_name = request.args.get('template')
return render_template(template_name)
パターン2:動的テンプレート生成
// 危険
String template = "こんにちは " + userInput;
templateEngine.process(template, context);
パターン3:本番環境でのデバッグエンドポイント
デバッグやプレビュー用エンドポイントは、任意のテンプレートをオンデマンドでコンパイルできるため、攻撃者にとって攻撃の入り口となります。
パターン4:ビジネスロジックの埋め込み
テンプレートにビジネスロジックを直接埋め込むと、開発は楽になりますが、リスクも増大します。ループや計算、API呼び出しなどの機能を追加するたびに、攻撃者はテンプレートの操作やシステムリソースへのアクセス手段を増やします。
ビジネスへの影響とリスク評価
即時の影響は深刻です。資格情報の窃取、データ漏洩、収益に関わるサービスの停止などが起こり得ます。組織は:
- 金銭的損失(データ漏洩やダウンタイム)
- 規制罰則(GDPR、CCPAなど)
- 評判の毀損
- 法的責任(顧客データの漏洩)
- 運用の混乱(インシデント対応・復旧)に直面します。
特にリテール・卸売業界は、多数の取引と顧客の個人情報や決済情報を扱うため、攻撃対象となりやすいです。
開発段階でのSSTIテスト
コードレビューのチェックリスト
- ✅ すべてのテンプレートレンダリング関数がパラメータ化された入力を使用しているか
- ✅ ユーザー入力をテンプレート文字列に連結していないか
- ✅ 本番環境でデバッグ用テンプレートエンドポイントが無効化されているか
- ✅ テンプレートが敏感な関数やモジュールにアクセスできないか
- ✅ 入力検証がレンダリング前に適用されているか
自動テスト
CI/CDパイプラインにSSTI検出を組み込み:
# SSTImapを使った例
python3 sstimap.py -u 'https://example.com/page?name=test' --level 5
手動テスト手法
他のインジェクション攻撃と同様に、入力ポイントを特定し、ファジングと結果のレビューを行います:
- サーバーレスポンスに反映される入力フィールドを特定
- ポリグロットペイロードや数学式を注入
- サーバーの挙動(エラー、評価、遅延)を観察
- テンプレートエンジンを特定
- 攻撃用ペイロードを作成
- 結果を記録・報告
業界標準とコンプライアンス
SSTIは以下の規格に該当します:
- OWASP Top 10 2021: カテゴリA03 (Injection)
- CWE-1336: テンプレートエンジンでの特殊要素の不適切中和
- NIST: セキュアコーディングと入力検証の要件
- PCI DSS: 6.5.1 (Injection脆弱性)
結論:SSTIの脅威は高まる一方
Server-Side Template Injectionは、コード実行の力と正規のテンプレート処理のステルス性を併せ持つ重大な脆弱性です。2025年も引き続きサーバーサイドテンプレートインジェクションの検査は重要です。特に、開発者がユーザー入力の適切な検証に苦労している現状があります。
ポイントは、テンプレートエンジンは非常に強力なツールであり、慎重に扱う必要があるということです。ユーザー入力をテンプレートコードとして扱わないことが最重要です。安全なコーディング実践と多層防御策を講じ、定期的なセキュリティテストを行うことで、この攻撃ベクトルから自組織を守ることができます。
Webアプリケーションの開発・運用に関わる組織にとって、SSTIの脆弱性対策は最優先事項です。テンプレートエンジンの広範な利用と動的コンテンツ生成の必要性を考えると、リスクは高いですが、適切な認識とセキュリティ対策の実施により、効果的に防止・軽減可能です。
追加リソース
- OWASP Web Security Testing Guide: Server-Side Template Injection
- PortSwigger Web Security Academy: SSTI Tutorials
- PayloadsAllTheThings: SSTIペイロードリポジトリ
- Hackmanit Template Injection Table: 44テンプレートエンジンのインタラクティブリファレンス
- James Kettleのホワイトペーパー: “Server-Side Template Injection: RCE for the Modern Web App”
安全を確保し、入力を検証し続けてください。あなたのテンプレートエンジンは強力なツールです—未検証のユーザー入力を通じて攻撃者に鍵を渡さないようにしましょう。
Related InstaTunnel pages
Continue from this article into the most relevant product guides and workflows.
Related Topics
Keep building with InstaTunnel
Read the docs for implementation details or compare plans before you ship.