Nginx
Reading time: 13 minutes
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Missing root location
Όταν ρυθμίζετε τον διακομιστή Nginx, η κατεύθυνση root παίζει κρίσιμο ρόλο καθορίζοντας τον βασικό κατάλογο από τον οποίο εξυπηρετούνται τα αρχεία. Σκεφτείτε το παρακάτω παράδειγμα:
server {
root /etc/nginx;
location /hello.txt {
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:8080/;
}
}
Σε αυτή τη διαμόρφωση, το /etc/nginx
έχει οριστεί ως ο ριζικός κατάλογος. Αυτή η ρύθμιση επιτρέπει την πρόσβαση σε αρχεία εντός του καθορισμένου ριζικού καταλόγου, όπως το /hello.txt
. Ωστόσο, είναι κρίσιμο να σημειωθεί ότι έχει οριστεί μόνο μια συγκεκριμένη τοποθεσία (/hello.txt
). Δεν υπάρχει διαμόρφωση για την ριζική τοποθεσία (location / {...}
). Αυτή η παράλειψη σημαίνει ότι η ριζική οδηγία ισχύει παγκοσμίως, επιτρέποντας τα αιτήματα για τη ριζική διαδρομή /
να έχουν πρόσβαση σε αρχεία κάτω από το /etc/nginx
.
Μια κρίσιμη ανησυχία ασφαλείας προκύπτει από αυτή τη διαμόρφωση. Ένα απλό αίτημα GET
, όπως το GET /nginx.conf
, θα μπορούσε να εκθέσει ευαίσθητες πληροφορίες εξυπηρετώντας το αρχείο διαμόρφωσης Nginx που βρίσκεται στο /etc/nginx/nginx.conf
. Η ρύθμιση της ρίζας σε έναν λιγότερο ευαίσθητο κατάλογο, όπως το /etc
, θα μπορούσε να μετριάσει αυτόν τον κίνδυνο, ωστόσο μπορεί να επιτρέπει ακόμα μη προγραμματισμένη πρόσβαση σε άλλα κρίσιμα αρχεία, συμπεριλαμβανομένων άλλων αρχείων διαμόρφωσης, αρχείων καταγραφής πρόσβασης και ακόμη και κωδικών πρόσβασης που χρησιμοποιούνται για την HTTP βασική αυθεντικοποίηση.
Alias LFI Misconfiguration
Στα αρχεία διαμόρφωσης του Nginx, απαιτείται προσεκτική επιθεώρηση για τις οδηγίες "location". Μια ευπάθεια γνωστή ως Local File Inclusion (LFI) μπορεί να εισαχθεί ακούσια μέσω μιας διαμόρφωσης που μοιάζει με την εξής:
location /imgs {
alias /path/images/;
}
Αυτή η ρύθμιση είναι επιρρεπής σε επιθέσεις LFI λόγω της ερμηνείας των αιτημάτων από τον διακομιστή όπως το /imgs../flag.txt
ως μια προσπάθεια πρόσβασης σε αρχεία εκτός του προοριζόμενου καταλόγου, επιλύοντας αποτελεσματικά σε /path/images/../flag.txt
. Αυτή η αδυναμία επιτρέπει στους επιτιθέμενους να ανακτούν αρχεία από το σύστημα αρχείων του διακομιστή που δεν θα έπρεπε να είναι προσβάσιμα μέσω του διαδικτύου.
Για να μετριαστεί αυτή η ευπάθεια, η ρύθμιση θα πρέπει να προσαρμοστεί σε:
location /imgs/ {
alias /path/images/;
}
Περισσότερες πληροφορίες: https://www.acunetix.com/vulnerabilities/web/path-traversal-via-misconfigured-nginx-alias/
Δοκιμές Accunetix:
alias../ => HTTP status code 403
alias.../ => HTTP status code 404
alias../../ => HTTP status code 403
alias../../../../../../../../../../../ => HTTP status code 400
alias../ => HTTP status code 403
Unsafe path restriction
Δείτε την παρακάτω σελίδα για να μάθετε πώς να παρακάμψετε οδηγίες όπως:
location = /admin {
deny all;
}
location = /admin/ {
deny all;
}
Proxy / WAF Protections Bypass
Unsafe variable use / HTTP Request Splitting
caution
Ευάλωτες μεταβλητές $uri
και $document_uri
και αυτό μπορεί να διορθωθεί αντικαθιστώντας τις με $request_uri
.
Ένα regex μπορεί επίσης να είναι ευάλωτο όπως:
location ~ /docs/([^/])? { … $1 … }
- Ευάλωτο
location ~ /docs/([^/\s])? { … $1 … }
- Όχι ευάλωτο (έλεγχος κενών)
location ~ /docs/(.*)? { … $1 … }
- Όχι ευάλωτο
Μια ευπάθεια στη διαμόρφωση του Nginx αποδεικνύεται από το παρακάτω παράδειγμα:
location / {
return 302 https://example.com$uri;
}
Οι χαρακτήρες \r (Carriage Return) και \n (Line Feed) σηματοδοτούν χαρακτήρες νέας γραμμής σε αιτήματα HTTP, και οι URL-encoded μορφές τους αναπαρίστανται ως %0d%0a
. Η συμπερίληψη αυτών των χαρακτήρων σε ένα αίτημα (π.χ., http://localhost/%0d%0aDetectify:%20clrf
) σε έναν κακώς ρυθμισμένο διακομιστή έχει ως αποτέλεσμα τον διακομιστή να εκδίδει μια νέα κεφαλίδα με το όνομα Detectify
. Αυτό συμβαίνει επειδή η μεταβλητή $uri αποκωδικοποιεί τους URL-encoded χαρακτήρες νέας γραμμής, οδηγώντας σε μια απροσδόκητη κεφαλίδα στην απόκριση:
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.19.3
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: https://example.com/
Detectify: clrf
Μάθετε περισσότερα για τους κινδύνους της έγχυσης CRLF και του διαχωρισμού απάντησης στο https://blog.detectify.com/2019/06/14/http-response-splitting-exploitations-and-mitigations/.
Επίσης, αυτή η τεχνική εξηγείται σε αυτή την ομιλία με μερικά ευάλωτα παραδείγματα και μηχανισμούς ανίχνευσης. Για παράδειγμα, προκειμένου να ανιχνεύσετε αυτή τη λανθασμένη ρύθμιση από μια προοπτική blackbox, μπορείτε να χρησιμοποιήσετε αυτές τις αιτήσεις:
https://example.com/%20X
- Οποιοσδήποτε κωδικός HTTPhttps://example.com/%20H
- 400 Bad Request
Αν είναι ευάλωτο, το πρώτο θα επιστρέψει καθώς το "X" είναι οποιαδήποτε μέθοδος HTTP και το δεύτερο θα επιστρέψει ένα σφάλμα καθώς το H δεν είναι έγκυρη μέθοδος. Έτσι, ο διακομιστής θα λάβει κάτι σαν: GET / H HTTP/1.1
και αυτό θα προκαλέσει το σφάλμα.
Άλλα παραδείγματα ανίχνευσης θα ήταν:
http://company.tld/%20HTTP/1.1%0D%0AXXXX:%20x
- Οποιοσδήποτε κωδικός HTTPhttp://company.tld/%20HTTP/1.1%0D%0AHost:%20x
- 400 Bad Request
Ορισμένες ευάλωτες ρυθμίσεις που βρέθηκαν σε αυτή την ομιλία ήταν:
- Σημειώστε πώς
$uri
έχει οριστεί όπως είναι στην τελική διεύθυνση URL.
location ^~ /lite/api/ {
proxy_pass http://lite-backend$uri$is_args$args;
}
- Σημειώστε πώς ξανά
$uri
είναι στο URL (αυτή τη φορά μέσα σε μια παράμετρο)
location ~ ^/dna/payment {
rewrite ^/dna/([^/]+) /registered/main.pl?cmd=unifiedPayment&context=$1&native_uri=$uri break;
proxy_pass http://$back;
- Τώρα στο AWS S3
location /s3/ {
proxy_pass https://company-bucket.s3.amazonaws.com$uri;
}
Οποιαδήποτε μεταβλητή
Ανακαλύφθηκε ότι τα δεδομένα που παρέχονται από τον χρήστη μπορεί να αντιμετωπίζονται ως μεταβλητή Nginx υπό ορισμένες συνθήκες. Η αιτία αυτής της συμπεριφοράς παραμένει κάπως ασαφής, ωστόσο δεν είναι σπάνια ούτε απλή η επαλήθευσή της. Αυτή η ανωμαλία επισημάνθηκε σε μια αναφορά ασφαλείας στο HackerOne, η οποία μπορεί να προβληθεί εδώ. Περαιτέρω έρευνα στο μήνυμα σφάλματος οδήγησε στην αναγνώριση της εμφάνισής του μέσα στον μηχανισμό φίλτρου SSI του κώδικα Nginx, προσδιορίζοντας τις Server Side Includes (SSI) ως την κύρια αιτία.
Για να ανιχνευθεί αυτή η κακή διαμόρφωση, μπορεί να εκτελεστεί η ακόλουθη εντολή, η οποία περιλαμβάνει την ρύθμιση ενός referer header για τη δοκιμή εκτύπωσης μεταβλητών:
$ curl -H ‘Referer: bar’ http://localhost/foo$http_referer | grep ‘foobar’
Σαρώσεις για αυτή τη λανθασμένη ρύθμιση σε συστήματα αποκάλυψαν πολλές περιπτώσεις όπου οι μεταβλητές Nginx μπορούσαν να εκτυπωθούν από έναν χρήστη. Ωστόσο, η μείωση του αριθμού των ευάλωτων περιπτώσεων υποδηλώνει ότι οι προσπάθειες για την επιδιόρθωση αυτού του ζητήματος έχουν υπάρξει κάπως επιτυχείς.
Ανάγνωση ωμής απάντησης backend
Το Nginx προσφέρει μια δυνατότητα μέσω του proxy_pass
που επιτρέπει την παρεμβολή σφαλμάτων και HTTP headers που παράγονται από το backend, με στόχο την απόκρυψη εσωτερικών μηνυμάτων σφάλματος και headers. Αυτό επιτυγχάνεται με το να σερβίρει το Nginx προσαρμοσμένες σελίδες σφάλματος ως απάντηση σε σφάλματα του backend. Ωστόσο, προκύπτουν προκλήσεις όταν το Nginx συναντά μια μη έγκυρη HTTP αίτηση. Μια τέτοια αίτηση προωθείται στο backend όπως έχει ληφθεί, και η ωμή απάντηση του backend αποστέλλεται απευθείας στον πελάτη χωρίς την παρέμβαση του Nginx.
Σκεφτείτε ένα παράδειγμα σεναρίου που περιλαμβάνει μια εφαρμογή uWSGI:
def application(environ, start_response):
start_response('500 Error', [('Content-Type', 'text/html'), ('Secret-Header', 'secret-info')])
return [b"Secret info, should not be visible!"]
Για να διαχειριστείτε αυτό, χρησιμοποιούνται συγκεκριμένες οδηγίες στη διαμόρφωση του Nginx:
http {
error_page 500 /html/error.html;
proxy_intercept_errors on;
proxy_hide_header Secret-Header;
}
- proxy_intercept_errors: Αυτή η οδηγία επιτρέπει στο Nginx να εξυπηρετεί μια προσαρμοσμένη απάντηση για τις απαντήσεις του backend με κωδικό κατάστασης μεγαλύτερο από 300. Διασφαλίζει ότι, για την εφαρμογή uWSGI που χρησιμοποιούμε ως παράδειγμα, μια απάντηση
500 Error
παγιδεύεται και διαχειρίζεται από το Nginx. - proxy_hide_header: Όπως υποδηλώνει το όνομα, αυτή η οδηγία κρύβει καθορισμένα HTTP headers από τον πελάτη, ενισχύοντας την ιδιωτικότητα και την ασφάλεια.
Όταν γίνεται μια έγκυρη αίτηση GET
, το Nginx την επεξεργάζεται κανονικά, επιστρέφοντας μια τυπική απάντηση σφάλματος χωρίς να αποκαλύπτει κανένα μυστικό header. Ωστόσο, μια μη έγκυρη HTTP αίτηση παρακάμπτει αυτόν τον μηχανισμό, με αποτέλεσμα την έκθεση των ακατέργαστων απαντήσεων του backend, συμπεριλαμβανομένων των μυστικών headers και των μηνυμάτων σφάλματος.
merge_slashes set to off
Από προεπιλογή, η merge_slashes
οδηγία του Nginx είναι ρυθμισμένη σε on
, η οποία συμπιέζει πολλαπλούς προοδευτικούς χαρακτήρες σε μια URL σε έναν μόνο χαρακτήρα. Αυτή η δυνατότητα, ενώ απλοποιεί την επεξεργασία URL, μπορεί ακούσια να αποκρύψει ευπάθειες σε εφαρμογές πίσω από το Nginx, ιδιαίτερα αυτές που είναι επιρρεπείς σε επιθέσεις τοπικής συμπερίληψης αρχείων (LFI). Οι ειδικοί ασφαλείας Danny Robinson και Rotem Bar έχουν επισημάνει τους πιθανούς κινδύνους που σχετίζονται με αυτή τη συμπεριφορά προεπιλογής, ειδικά όταν το Nginx λειτουργεί ως αντίστροφος διακομιστής.
Για να μετριαστούν αυτοί οι κίνδυνοι, συνιστάται να απενεργοποιήσετε την οδηγία merge_slashes
για εφαρμογές που είναι ευάλωτες σε αυτές τις ευπάθειες. Αυτό διασφαλίζει ότι το Nginx προωθεί τις αιτήσεις στην εφαρμογή χωρίς να αλλάζει τη δομή της URL, αποφεύγοντας έτσι την απόκρυψη οποιωνδήποτε υποκείμενων ζητημάτων ασφαλείας.
Για περισσότερες πληροφορίες, ελέγξτε Danny Robinson και Rotem Bar.
Maclicious Response Headers
Όπως φαίνεται σε αυτή την αναφορά, υπάρχουν ορισμένα headers που αν είναι παρόντα στην απάντηση από τον διακομιστή ιστού θα αλλάξουν τη συμπεριφορά του Nginx proxy. Μπορείτε να τα ελέγξετε στα docs:
X-Accel-Redirect
: Υποδεικνύει στο Nginx να ανακατευθύνει εσωτερικά μια αίτηση σε μια καθορισμένη τοποθεσία.X-Accel-Buffering
: Ελέγχει αν το Nginx θα πρέπει να αποθηκεύει την απάντηση ή όχι.X-Accel-Charset
: Ορίζει το σύνολο χαρακτήρων για την απάντηση όταν χρησιμοποιείται το X-Accel-Redirect.X-Accel-Expires
: Ορίζει τον χρόνο λήξης για την απάντηση όταν χρησιμοποιείται το X-Accel-Redirect.X-Accel-Limit-Rate
: Περιορίζει το ρυθμό μεταφοράς για τις απαντήσεις όταν χρησιμοποιείται το X-Accel-Redirect.
Για παράδειγμα, το header X-Accel-Redirect
θα προκαλέσει μια εσωτερική ανακατεύθυνση στο nginx. Έτσι, έχοντας μια ρύθμιση nginx με κάτι όπως root /
και μια απάντηση από τον διακομιστή ιστού με X-Accel-Redirect: .env
θα κάνει το nginx να στείλει το περιεχόμενο του /.env
(Path Traversal).
Default Value in Map Directive
Στην ρύθμιση Nginx, η οδηγία map
συχνά παίζει ρόλο στον έλεγχο εξουσιοδότησης. Ένα κοινό λάθος είναι να μην καθορίζεται μια προεπιλεγμένη τιμή, κάτι που θα μπορούσε να οδηγήσει σε μη εξουσιοδοτημένη πρόσβαση. Για παράδειγμα:
http {
map $uri $mappocallow {
/map-poc/private 0;
/map-poc/secret 0;
/map-poc/public 1;
}
}
server {
location /map-poc {
if ($mappocallow = 0) {return 403;}
return 200 "Hello. It is private area: $mappocallow";
}
}
Χωρίς ένα default
, ένας κακόβουλος χρήστης μπορεί να παρακάμψει την ασφάλεια αποκτώντας πρόσβαση σε μια μη καθορισμένη URI εντός του /map-poc
. Ο οδηγός του Nginx προτείνει την ρύθμιση μιας προκαθορισμένης τιμής για να αποφευχθούν τέτοια προβλήματα.
Ευπάθεια DNS Spoofing
Η DNS spoofing κατά του Nginx είναι εφικτή υπό ορισμένες συνθήκες. Εάν ένας επιτιθέμενος γνωρίζει τον DNS server που χρησιμοποιεί ο Nginx και μπορεί να παρεμποδίσει τα DNS queries του, μπορεί να παραποιήσει τα DNS records. Αυτή η μέθοδος, ωστόσο, είναι αναποτελεσματική εάν ο Nginx είναι ρυθμισμένος να χρησιμοποιεί localhost (127.0.0.1) για την επίλυση DNS. Ο Nginx επιτρέπει την καθορισμένη ρύθμιση ενός DNS server ως εξής:
resolver 8.8.8.8;
proxy_pass
και internal
Δηλώσεις
Η δήλωση proxy_pass
χρησιμοποιείται για την ανακατεύθυνση αιτημάτων σε άλλους διακομιστές, είτε εσωτερικά είτε εξωτερικά. Η δήλωση internal
διασφαλίζει ότι ορισμένες τοποθεσίες είναι προσβάσιμες μόνο εντός του Nginx. Αν και αυτές οι δηλώσεις δεν είναι ευπάθειες από μόνες τους, η διαμόρφωσή τους απαιτεί προσεκτική εξέταση για την αποφυγή κενών ασφαλείας.
proxy_set_header Upgrade & Connection
Εάν ο διακομιστής nginx είναι διαμορφωμένος να περνά τις κεφαλίδες Upgrade και Connection, μπορεί να εκτελεστεί μια επίθεση h2c Smuggling για την πρόσβαση σε προστατευμένα/εσωτερικά endpoints.
caution
Αυτή η ευπάθεια θα επέτρεπε σε έναν επιτιθέμενο να δημιουργήσει άμεση σύνδεση με το endpoint proxy_pass
(http://backend:9999
σε αυτή την περίπτωση) του οποίου το περιεχόμενο δεν θα ελέγχεται από το nginx.
Παράδειγμα ευάλωτης διαμόρφωσης για την κλοπή του /flag
από εδώ:
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /usr/local/nginx/conf/cert.pem;
ssl_certificate_key /usr/local/nginx/conf/privkey.pem;
location / {
proxy_pass http://backend:9999;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
}
location /flag {
deny all;
}
warning
Σημειώστε ότι ακόμη και αν το proxy_pass
δείχνει σε μια συγκεκριμένη διαδρομή όπως http://backend:9999/socket.io
, η σύνδεση θα γίνει με το http://backend:9999
, οπότε μπορείτε να επικοινωνήσετε με οποιαδήποτε άλλη διαδρομή μέσα σε αυτό το εσωτερικό σημείο. Έτσι, δεν έχει σημασία αν μια διαδρομή έχει καθοριστεί στη διεύθυνση URL του proxy_pass.
Δοκιμάστε το μόνοι σας
Η Detectify έχει δημιουργήσει ένα αποθετήριο GitHub όπου μπορείτε να χρησιμοποιήσετε το Docker για να ρυθμίσετε τον δικό σας ευάλωτο διακομιστή δοκιμών Nginx με μερικές από τις κακές ρυθμίσεις που συζητούνται σε αυτό το άρθρο και να προσπαθήσετε να τις βρείτε μόνοι σας!
https://github.com/detectify/vulnerable-nginx
Εργαλεία Στατικής Ανάλυσης
GIXY
Το Gixy είναι ένα εργαλείο για την ανάλυση της ρύθμισης Nginx. Ο κύριος στόχος του Gixy είναι να αποτρέψει τις κακές ρυθμίσεις ασφαλείας και να αυτοματοποιήσει την ανίχνευση σφαλμάτων.
Nginxpwner
Το Nginxpwner είναι ένα απλό εργαλείο για την αναζήτηση κοινών κακών ρυθμίσεων και ευπαθειών του Nginx.
Αναφορές
- https://blog.detectify.com/2020/11/10/common-nginx-misconfigurations/
- http://blog.zorinaq.com/nginx-resolver-vulns/
- https://github.com/yandex/gixy/issues/115
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.