サーバーサイド・テンプレートインジェクション(Server-Side Template Injection、SSTI)とは、Webアプリケーションで使用されるテンプレートエンジンの脆弱性を悪用して、不正なコードをサーバー側で実行させる攻撃手法です。SSTIが発生すると、攻撃者はテンプレートエンジンを介してサーバーで任意のコードを実行できるため、機密情報の漏洩やサーバーの完全な制御権奪取など、深刻な被害が発生する可能性があります。
一般的にSSTIは、ユーザー入力をテンプレートエンジンに直接渡しているケースで発生しやすく、テンプレートエンジンがその入力を処理する際に、悪意あるコードを実行してしまいます。代表的なテンプレートエンジンには、Jinja2(Python)、Thymeleaf(Java)、Freemarker、Smarty(PHP)などが含まれ、これらのテンプレートエンジンでSSTIのリスクが問題視されています。
この記事の目次
サーバーサイド・テンプレートインジェクションの仕組み
SSTIは、以下のような手順で行われます:
- ユーザー入力をテンプレートに直接組み込む
Webアプリケーションで、ユーザーが入力したデータがそのままテンプレートエンジンに渡され、HTMLや他のコンテンツとしてレンダリングされるケースがあります。 - テンプレートエンジンによるコード実行
攻撃者がテンプレートエンジンに対して不正な構文やコードを入力すると、そのコードがテンプレートエンジンによって処理され、サーバー側で実行されてしまいます。 - 任意のコードの実行
攻撃者はこの仕組みを利用して、サーバー上でPythonやJavaScript、PHPなどのコードを実行し、システムの制御やデータの漏洩、ファイル操作などを行います。 - サーバーの制御権の奪取
任意コードが実行されると、攻撃者はサーバー内のファイルやデータベースにアクセスしたり、他のシステムを攻撃するための拠点として悪用したりします。
サーバーサイド・テンプレートインジェクションの例
SSTIの典型的な例として、Jinja2を使用するPythonのWebアプリケーションにおけるケースを見てみます:
1. Jinja2でのSSTI
Jinja2はPythonのテンプレートエンジンで、ユーザーが入力した内容を直接テンプレートに渡すと、SSTIが発生する可能性があります。例えば、以下のようにユーザー入力を直接テンプレートに組み込む場合を考えます:
from flask import Flask, render_template_string, request
app = Flask(__name__)
@app.route("/greet", methods=["POST"])
def greet():
name = request.form.get("name") # ユーザー入力を取得
template = f"Hello, {name}!" # 入力をテンプレートに組み込む
return render_template_string(template) # テンプレートをレンダリング
上記のコードは、ユーザーの名前を取得し、そのままテンプレートに渡しています。このとき、攻撃者が「{{7*7}}
」のような入力を渡すと、テンプレートエンジンはこれを計算し、「Hello, 49!
」と表示してしまいます。さらに、悪意あるコード(例:{{ config['SECRET_KEY'] }}
)を埋め込まれると、サーバーの環境情報や機密データが漏洩する可能性があります。
2. Smarty(PHP)でのSSTI
PHPのテンプレートエンジンSmartyにおいても同様の脆弱性が存在します。例えば、以下のようにユーザー入力を直接テンプレートに含めるケースです。
$smarty->assign('username', $_POST['username']);
$smarty->display('hello.tpl');
この場合、攻撃者が「{$smarty.server.SCRIPT_NAME}
」などのコードを入力すると、Smartyエンジンがそのまま処理し、PHPファイルの情報が漏洩する可能性があります。
サーバーサイド・テンプレートインジェクションのリスクと影響
SSTIが発生すると、以下のようなリスクや影響が考えられます:
- 機密情報の漏洩
攻撃者が任意のコードを実行できると、サーバー上にある環境変数や設定ファイルの機密情報(APIキー、データベース認証情報など)が漏洩する可能性があります。 - ファイル操作や不正アクセス
攻撃者は、ファイル操作コードを利用してサーバーのファイルを取得したり、データベースに不正アクセスを行ったりすることができます。 - ランサムウェアの実行やシステムの乗っ取り
SSTIを悪用してサーバー上でランサムウェアやマルウェアを実行することで、サーバーの完全な制御権を奪取し、さらに攻撃を拡大することが可能です。 - サービス妨害攻撃(DoS)
攻撃者が計算量の多い処理をサーバー側で実行すると、サーバーが過負荷状態に陥り、サービスの停止や遅延が発生することがあります。
サーバーサイド・テンプレートインジェクションに対する対策
SSTIを防ぐためには、以下のような対策が効果的です。
- ユーザー入力をテンプレートに直接渡さない
ユーザーからの入力をテンプレートに直接渡すのではなく、事前に無害化(エスケープ)処理を行います。例えば、HTMLエンコードを行うことで、不正なテンプレート構文がそのまま表示されるようにします。 - テンプレートエンジンを安全に設定する
使用するテンプレートエンジンの設定を見直し、不正な構文が実行されないように設定を強化します。Jinja2であれば、sandboxモードを有効にするなどの対策があります。 - ホワイトリストによるフィルタリング
テンプレートに含めるデータを事前にホワイトリストで制御し、許可された文字列やパターンのみをテンプレートに渡すようにします。 - 定期的なセキュリティ診断とテスト
アプリケーション開発の段階から、SSTIを含むセキュリティテストやペネトレーションテストを実施し、脆弱性の有無を確認します。OWASP ZAPやBurp Suiteといったツールでの自動診断も効果的です。 - 安全なテンプレートエンジンの選択
セキュリティ機能が充実したテンプレートエンジンを使用することで、脆弱性のリスクを低減できます。たとえば、テンプレートエンジンによっては、コード実行を無効化するオプションや、安全なデフォルト設定が提供されています。
まとめ
サーバーサイド・テンプレートインジェクション(SSTI)は、テンプレートエンジンの脆弱性を突くことで、サーバー側で任意のコードを実行できる非常に危険な攻撃手法です。ユーザー入力がテンプレートエンジンに直接渡されると、機密情報の漏洩やシステム乗っ取りなど、重大な被害が発生する可能性があります。SSTIへの対策としては、ユーザー入力の無害化、テンプレートエンジンの安全設定、セキュリティテストの実施などが効果的です。安全なテンプレート処理を徹底することで、SSTIのリスクを減らし、アプリケーションのセキュリティを高めることができます。