はじめに
ソフトウェア開発や関連する多くの分野は、例外なくサイバー脆弱性の影響を受けています。サーバサイドでHTMLコードを管理するためのテンプレートもその一つです。サーバサイドテンプレートを狙った攻撃はSSTI(略称)と呼ばれています。その詳細な仕組みについて、ここで詳しく探っていきます。
多くのウェブアプリ運営者は、Twig、Mustache、FreeMarker などのテンプレートエンジンを利用し、メールやウェブページ内のHTMLに動的かつ豊富なデータを手軽に埋め込むことを好みます。ユーザー入力が安全でない形や悪意ある要素とともにテンプレートに渡されると、SSTI攻撃が発生します。
SSTIとは、サーバサイドで使用される既存のテンプレートを介して、悪意ある要素を著名なテンプレートエンジンに挿入する行為です。ここで攻撃者の主な目的は、サーバ側の処理を掌握することにあります。
SSTIの仕組みは実例を用いると理解しやすいです。例えば、マーケティングアプリを使って顧客にメールを送信し、Twigテンプレートシステムで受信者の名前を表示している場合を考えてみてください。
受信者に変更権限が与えられていなければ、名前を単にテンプレートに追加するだけで問題はありません。しかし、受信者側でメールのカスタマイズが可能になると、送信側はテンプレート内容の制御を失い始めます。
攻撃者は、受信者側のカスタマイズ機能を利用して、使用されているテンプレート生成エンジンを突き止め、ペイロードを自由に改変することでSSTI攻撃を実行する可能性があります。
また、SSTI攻撃は必ずしも意図的に行われるわけではなく、ユーザー入力が直接テンプレートと結合されることで知らずに発生する場合もあります。このような状況は、攻撃者がテンプレートエンジンを変形させるコマンドを注入し、サーバを自在に操作する隙を与えてしまいます。いずれの場合も、SSTI攻撃の結果は大きな被害をもたらすことが多いです。
開発者は、サーバに送られるユーザー固有のデータを組み込んだ事前作成済みのウェブページを生成するため、これらのテンプレートを利用することが多いです。これにより、サーバ側でのリクエスト処理時にブラウザとサーバ間の通信が軽減されます。
サーバサイドテンプレートは、ユーザー入力をあらかじめ埋め込む柔軟性と省力性を提供するため、しばしばXXSやクロスサイトスクリプティングと混同されることがあります。
ウェブフレームワークで動的なHTMLを生成する際、テンプレート生成エンジンは最も好まれる手段です。構造的には、テンプレートは出力されるHTMLの固定部分と動的コンテンツ挿入のための特定のルールを含んでいます。
いくらベストプラクティスを採用していても、テンプレートシステムは十分に守られておらず、攻撃者や悪意あるテンプレート作成者の手に渡る恐れがあります。
ユーザーが作成したテンプレートを提供または導入できるウェブアプリは、SSTI攻撃の対象になりやすいです。例えば、ある変数のデータが編集されると、テンプレートエンジンが動的コンポーネントを加えるためにテンプレートファイルを利用するようになります。
さらに、HTTPリクエストが発生すると、エンジンは自動的にHTML出力レスポンスの生成を開始します。
確認のため、HTTP POSTリクエストを利用できます。
例:
POST /endpoint-detail HTTP/1.1
Host: example.com
parameter=test_data
この脆弱性を確認する方法はいくつかあり、ここでは異なるパラメーター値を使った手法を紹介します。
=${7*3}
=<%= 7*3 %>
={{7*3}}
次に、デバッグ出力(例えばDjangoの場合)を確認します。各テンプレートエンジンで出力形式は若干異なります。
POST /endpoint-detail HTTP/1.1
Host: example.com
parameter={% debug %}
このリクエストにより、デバッグ用の読み取り可能なオブジェクト一覧が取得されます。ここからは、たとえば「settings」といったオブジェクトにもアクセスできる可能性があります。シークレットキーの内容を確認してみてください。
POST /endpoint-detail HTTP/1.1
Host: example.com
parameter={{settings.SECRET_KEY}}
他のサイバー脆弱性と同様に、SSTIは対象に深刻な影響を及ぼします。たとえば、SSTIの存在はウェブサイトが多くの攻撃に晒されやすくなる原因となります。
SSTI攻撃の結果は、影響を受けたテンプレートエンジンの種類や、アプリがどのように利用されているかによって異なります。
主に、以下のような大きな被害が発生することが多いです:
これらすべての行為により、想像を超える混乱が生じる可能性があります。ごく稀に、SSTIの被害が軽微な場合もあります。
上記のSSTIの影響は、開発者やセキュリティ担当者が早期に注入を発見するためのサインとなります。しかし、SSTIは理解が難しく、XSS攻撃と似通っているため、見過ごされやすい側面があります。そのため、早期かつ正確な検出のためには、通常以上の対策が必要となります。
他の攻撃と同様、最初の検出ステップは脆弱性の存在を確認することです。有効な方法として、特殊文字列を含む一般的な表現でテンプレートをファズテストする手法が挙げられます。
もしテスターがその文字列を実行できなかった場合、SSTIの存在を示唆しています。
また、.stm、.shtml、.shtm などの拡張子を持つウェブページの存在を調べる方法もあります。これらの拡張子のページがあるサイトは、SSTI攻撃の影響を受ける可能性が高いです。
ただし、これらの手法だけでは100%の精度でSSTIを検出できるとは限りません。なぜなら、SSTIにはプレーンテキストとコードテキストの2種類の文脈が存在するためです。
以下に、各文脈ごとにSSTIを検出するための一般的な手法を詳しく説明します。
この手法では、XSS入力と似たプレーンなテキストを用いて脆弱性の有無を確認します。SSTIに適した状況かどうかを調べるため、パラメーター内に数学表現を用いることも可能です。
サイトの確認には、http://example.com/?username=${7*7} のようなURLが役立ちます。ここでは「example.com」を対象サイトのドメインに置き換えてください。URLの結果に数学的な値が表示されれば、SSTI脆弱性の存在を示します。
これは、サーバ側でエラーや空のレスポンスを引き起こすペイロードを構築する方法です。また、XSS脆弱性が全く発生しないようにする方法として、値に任意のHTMLを注入して試すことができます。
XSSが存在しない場合は、このペイロード構築の手法を用いてSSTIを検出してください。
SSTIの注入が確認された際には、影響を受けたテンプレートエンジンの特定に注力する必要があります。
テンプレート言語は多種多様ですが、多くは類似の構文を使用しており、HTML要素と矛盾しないよう設計されています。これにより、攻撃対象のテンプレートエンジンを特定するためのペイロード作成が容易になります。
無効な構文を送信する方法も、SSTIの存在を確認する有効な手段です。送信により、サーバ側からのエラーメッセージで重要な情報が引き出される場合があります。
多くの場合、この方法で十分な確認が可能です。他の手法を検討する際は、複数のペイロードを手動でテストし、テンプレートエンジンでの動作過程を解析してください。試行の結果に基づいて、構文パターンを絞り込むとよいでしょう。
また、各テンプレートエンジンの構文に則った任意の算術演算を注入する方法も一般的です。
上記の論理ツリーに従えば、正確なSSTIの特定が可能です。なお、TwigやJinja2など複数の言語で同様のペイロードが効果を示すこともあるため、複数の成功例を収集して判断することが望ましいです。
SSTI攻撃の影響を理解した上で、その予防策を学ばないのは賢明ではありません。テンプレートエンジンの使用を中止することは、コードの流れを損なわず複数の修正が可能であるという利点を失うため、適切な代替案とは言えません。
そのため、開発者やセキュリティ専門家は、SSTIの影響を受けないようにするための他の方法を模索する必要があります。以下に、専門家が推奨するSSTI予防策を示します。
いかなる場合でも、テンプレートは開発者や管理者以外に変更を許可するべきではありません。誰でも変更可能なテンプレートはハッカーにとって狙いやすいため、アクセス制限を厳格に実施することが望ましいです。ただし、常に実現できるとは限りません。
サニタイゼーションは、SSTI攻撃の可能性を低減する有力な手法です。これは、悪意のある要素が存在しないかをあらかじめ確認する作業を指します。特に、ユーザーから送信されたデータに対して実施する必要があります。正規表現を用い、検証済みのパターンリストを作成することで対応できますが、100%の保護を保証するものではありません。
SSTIからのより確実な保護には、サニタイゼーションよりもサンドボックス化が適しています。これはユーザー用に安全で制限された環境を構築する予防策であり、危険な機能やモジュールを排除し、脆弱性発見時には他のデータへのアクセスを制限します。その効果は高いものの、実装は困難であり、設定ミスなどにより容易に回避されることもあります。
SSTI攻撃を防ぐため、ロジック無しテンプレートの利用が可能です。ロジック無しテンプレートは、コードの解釈と表示を分離する設計となっており、Mustacheがその代表例です。これにより、リモートコード実行の可能性が低減されます。
上記の対策で十分な防御が得られない場合、リモートコード実行のリスクは避けがたいと考え、完全に隔離されたDockerコンテナ内でテンプレートエンジンを実行する独自のサンドボックス化を導入し、被害を最小限に抑える手法が必要です。
システム全体の安全を守るためには、さまざまな脆弱性を詳しく理解する必要があります。SSTI(サーバサイド・テンプレート注入)もその一例です。本記事を通じ、SSTIの深刻さと組織のデジタル資産を守るためのサイバーセキュリティの重要性について理解が深まれば幸いです。
Testing for Server Side Template Injection - OWASP
Server Side Template Injection Payloads - Github repository
最新情報を購読