Nginx

Support HackTricks

Zafiyet değerlendirmesi ve penetrasyon testi için anında kullanılabilir kurulum. 20'den fazla araç ve özellik ile her yerden tam bir pentest gerçekleştirin; bu araçlar keşiften raporlamaya kadar uzanır. Biz pentester'ların yerini almıyoruz - onlara daha derinlemesine araştırma yapmaları, shell'leri patlatmaları ve eğlenmeleri için biraz zaman kazandırmak amacıyla özel araçlar, tespit ve istismar modülleri geliştiriyoruz.

Missing root location

Nginx sunucusunu yapılandırırken, root direktifi dosyaların sunulduğu temel dizini tanımlayarak kritik bir rol oynar. Aşağıdaki örneği dikkate alı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şim sağlar. Ancak, yalnızca belirli bir konum (/hello.txt) tanımlandığını not etmek önemlidir. Kök konumu için bir yapılandırma yoktur (location / {...}). Bu eksiklik, kök direktifinin küresel olarak uygulanması anlamına gelir ve kök yolu / için yapılan isteklerin /etc/nginx altındaki dosyalara erişmesine olanak tanır.

Bu yapılandırmadan kaynaklanan kritik bir güvenlik dikkati 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 açığa çıkarabilir. Kökü daha az hassas bir dizine, örneğin /etc olarak ayarlamak bu riski azaltabilir, ancak yine de diğer kritik dosyalara, diğer yapılandırma dosyalarına, erişim günlüklerine ve hatta HTTP temel kimlik doğrulaması için kullanılan şifrelenmiş kimlik bilgilerine istenmeyen erişime izin verebilir.

Alias LFI Yanlış Yapılandırması

Nginx yapılandırma dosyalarında, "location" direktifleri için dikkatli bir inceleme gereklidir. Aşağıdaki gibi bir yapılandırma aracılığıyla istemeden Yerel Dosya Dahil Etme (LFI) olarak bilinen bir zafiyet tanıtılabilir:

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

Bu yapılandırma, sunucunun /imgs../flag.txt gibi istekleri, hedef dizin dışındaki dosyalara erişim girişimi olarak yorumlaması nedeniyle LFI saldırılarına açıktır ve bu da /path/images/../flag.txt olarak çözülmektedir. Bu hata, saldırganların web üzerinden erişilememesi gereken dosyaları sunucunun dosya sisteminden almasına olanak tanır.

Bu güvenlik açığını azaltmak 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üvensiz yol kısıtlaması

Aşağıdaki sayfayı kontrol edin, şu gibi direktifleri nasıl atlayacağınızı öğrenin:

location = /admin {
deny all;
}

location = /admin/ {
deny all;
}
Proxy / WAF Protections Bypass

Güvensiz değişken kullanımı / HTTP İstek Bölme

Zayıf değişkenler $uri ve $document_uri ve bunlar $request_uri ile değiştirilerek düzeltilebilir.

Bir regex de zayıf olabilir:

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

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

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

Nginx yapılandırmasındaki bir zayıflık aşağıdaki örnekle gösterilmektedir:

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

HTTP isteklerinde \r (Carriage Return) ve \n (Line Feed) karakterleri yeni satır karakterlerini belirtir ve URL kodlu formları %0d%0a olarak temsil edilir. Bu karakterleri yanlış yapılandırılmış bir sunucuya yapılan bir isteğe (örneğin, http://localhost/%0d%0aDetectify:%20clrf) dahil etmek, sunucunun Detectify adında yeni bir başlık oluşturmasına neden olur. Bu, $uri değişkeninin URL kodlu yeni satır karakterlerini çözmesi nedeniyle gerçekleşir ve yanıt içinde beklenmedik bir başlık oluşur:

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 enjeksiyonu ve yanıt bölme 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çıklanmıştır bazı savunmasız örnekler ve tespit mekanizmaları ile. Örneğin, bu yanlış yapılandırmayı bir kara kutu perspektifinden tespit etmek için bu istekleri kullanabilirsiniz:

  • https://example.com/%20X - Herhangi bir HTTP kodu

  • https://example.com/%20H - 400 Bad Request

Eğer savunmasızsa, ilki "X" herhangi bir HTTP yöntemi olarak dönecek ve ikincisi H geçerli bir yöntem olmadığından bir hata dönecektir. Böylece sunucu şunları alacak: GET / H HTTP/1.1 ve bu hatayı tetikleyecektir.

Diğer tespit örnekleri şunlar olabilir:

  • http://company.tld/%20HTTP/1.1%0D%0AXXXX:%20x - Herhangi bir HTTP kodu

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

O konuşmada sunulan bazı savunmasız yapılandırmalar şunlardı:

  • $uri'nin son URL'de olduğu gibi ayarlandığına dikkat edin.

location ^~ /lite/api/ {
proxy_pass http://lite-backend$uri$is_args$args;
}
  • Dikkat edin ki yine $uri URL'de (bu sefer bir parametre içinde) bulunmaktadır.

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

Kullanıcı tarafından sağlanan verilerin, belirli koşullar altında Nginx değişkeni olarak ele alınabileceği keşfedilmiştir. Bu davranışın nedeni biraz belirsiz kalmakta, ancak nadir ya da doğrulaması basit değildir. Bu anomali, HackerOne'da yayınlanan bir güvenlik raporunda vurgulanmıştır, buradan görüntülenebilir. Hata mesajı üzerindeki daha fazla araştırma, bunun Nginx'in kod tabanındaki SSI filtre modülünde meydana geldiğini belirlemiş ve Sunucu Tarafı Dahil Etmelerin (SSI) kök neden olduğunu ortaya çıkarmıştır.

Bu yanlış yapılandırmayı tespit etmek için, değişken yazdırmasını test etmek amacıyla bir referer başlığı ayarlamayı içeren aşağıdaki komut çalıştırılabilir:

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

Bu yanlış yapılandırmanın sistemler arasında taranması, bir kullanıcının Nginx değişkenlerini yazdırabileceği birden fazla örneği ortaya çıkardı. Ancak, savunmasız örneklerin sayısındaki azalma, bu sorunu düzeltme çabalarının bir ölçüde başarılı olduğunu göstermektedir.

Ham arka uç yanıtı okuma

Nginx, arka uç tarafından üretilen hataları ve HTTP başlıklarını yakalamak için proxy_pass aracılığıyla bir özellik sunar; bu, dahili hata mesajlarını ve başlıkları gizlemeyi amaçlar. Bu, Nginx'in arka uç hatalarına yanıt olarak özel hata sayfaları sunmasıyla gerçekleştirilir. Ancak, Nginx geçersiz bir HTTP isteğiyle karşılaştığında zorluklar ortaya çıkar. Böyle bir istek, alındığı gibi arka uca iletilir ve arka ucun ham yanıtı, Nginx'in müdahalesi olmadan doğrudan istemciye gönderilir.

Bir uWSGI uygulamasını içeren örnek bir senaryoyu düşünün:

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, Nginx'in 300'den büyük durum kodlarına sahip arka uç yanıtları için özel bir yanıt sunmasını sağlar. Örneğimizdeki uWSGI uygulaması için, 500 Hatası yanıtının Nginx tarafından yakalanıp işlenmesini garanti eder.

  • proxy_hide_header: Adından da anlaşılacağı gibi, bu direktif belirtilen HTTP başlıklarını istemciden 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 herhangi bir gizli başlık ifşa etmeden standart bir hata yanıtı döner. Ancak, geçersiz bir HTTP isteği bu mekanizmayı atlayarak, gizli başlıklar ve hata mesajları da dahil olmak üzere ham arka uç yanıtlarının ifşasına neden olur.

merge_slashes kapalı

Varsayılan olarak, Nginx'in merge_slashes direktifi açık olarak ayarlanmıştır; bu, bir URL'deki birden fazla ileri eğik çizgiyi tek bir eğik çizgiye sıkıştırır. Bu özellik, URL işleme sürecini kolaylaştırırken, Nginx'in arkasındaki uygulamalardaki zayıflıkları, özellikle yerel dosya dahil etme (LFI) saldırılarına yatkın olanları, yanlışlıkla gizleyebilir. Güvenlik uzmanları Danny Robinson ve Rotem Bar, Nginx'in ters proxy olarak hareket ettiği durumlarda bu varsayılan davranışla ilişkili potansiyel riskleri vurgulamışlardır.

Bu tür riskleri azaltmak için, bu zayıflıklara duyarlı uygulamalar için merge_slashes direktifini kapatmak önerilir. Bu, Nginx'in URL yapısını değiştirmeden uygulamaya istekleri iletmesini sağlar ve böylece temel güvenlik sorunlarını gizlemez.

Daha fazla bilgi için Danny Robinson ve Rotem Bar bağlantısını kontrol edin.

Maclicious Yanıt Başlıkları

bu yazıda gösterildiği gibi, web sunucusundan gelen yanıtta mevcut olan belirli başlıklar, Nginx proxy'sinin davranışını değiştirecektir. Bunları belgelerde kontrol edebilirsiniz:

  • X-Accel-Redirect: Nginx'e bir isteği belirtilen bir konuma dahili olarak yönlendirmesini belirtir.

  • X-Accel-Buffering: Nginx'in yanıtı tamponlayıp tamponlamayacağını kontrol eder.

  • X-Accel-Charset: X-Accel-Redirect kullanıldığında yanıt için karakter setini ayarlar.

  • X-Accel-Expires: X-Accel-Redirect kullanıldığında yanıt için son kullanma süresini ayarlar.

  • X-Accel-Limit-Rate: X-Accel-Redirect kullanıldığında yanıtlar için transfer hızını sınırlar.

Örneğin, X-Accel-Redirect başlığı, nginx'de dahili bir yönlendirme oluşturur. Yani, root / gibi bir nginx yapılandırmasına sahip olmak ve web sunucusundan X-Accel-Redirect: .env ile bir yanıt almak, nginx'in /.env içeriğini göndermesine neden olacaktır (Path Traversal).

Map Direktifinde Varsayılan Değer

Nginx yapılandırmasında, map direktifi genellikle yetkilendirme kontrolü rolü oynar. Yaygın bir hata, varsayılan bir değer belirtmemektir; bu, yetkisiz erişime yol açabilir. Örneğin:

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 olmadan, kötü niyetli bir kullanıcı /map-poc içindeki tanımsız URI'ye erişerek güvenliği atlayabilir. Nginx kılavuzu bu tür sorunları önlemek için bir varsayılan değer ayarlamayı önerir.

DNS Spoofing Açığı

Nginx'e karşı DNS spoofing belirli koşullar altında mümkündür. Eğer bir saldırgan Nginx tarafından kullanılan DNS sunucusunu biliyorsa ve DNS sorgularını kesebiliyorsa, DNS kayıtlarını sahteleyebilir. Ancak, Nginx localhost (127.0.0.1) kullanacak şekilde yapılandırılmışsa, bu yöntem etkisizdir. Nginx, bir DNS sunucusunu aşağıdaki gibi belirtmeye izin verir:

resolver 8.8.8.8;

proxy_pass ve internal Direktifleri

proxy_pass direktifi, istekleri diğer sunuculara, ister dahili ister harici olarak yönlendirmek için kullanılır. internal direktifi, belirli konumların yalnızca Nginx içinde erişilebilir olmasını sağlar. Bu direktifler kendileri bir zafiyet olmasa da, yapılandırmaları güvenlik açıklarını önlemek için dikkatli bir şekilde incelenmelidir.

proxy_set_header Upgrade & Connection

Eğer nginx sunucusu Upgrade ve Connection başlıklarını geçirecek şekilde yapılandırılmışsa, korunan/dahili uç noktalarına erişmek için bir h2c Smuggling saldırısı gerçekleştirilebilir.

Bu zafiyet, bir saldırganın proxy_pass uç noktası ile doğrudan bir bağlantı kurmasına izin verecektir (http://backend:9999 bu durumda) ve içeriği nginx tarafından kontrol edilmeyecektir.

/flag çalmak için zayıf yapılandırma örneği buradan:

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

Not edin ki proxy_pass belirli bir yola işaret etse bile, bağlantı http://backend:9999 ile kurulacaktır, bu nedenle o iç uç noktası içinde herhangi bir başka yolla iletişim kurabilirsiniz. Bu nedenle, proxy_pass URL'sinde bir yol belirtilip belirtilmediği önemli değildir.

Kendin dene

Detectify, bu makalede tartışılan bazı yanlış yapılandırmalarla kendi savunmasız Nginx test sunucunuzu Docker kullanarak kurabileceğiniz bir GitHub deposu oluşturmuştur ve bunları kendiniz bulmayı deneyebilirsiniz!

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

Statik Analiz Araçları

Gixy, Nginx yapılandırmasını analiz etmek için bir araçtır. Gixy'nin ana hedefi, güvenlik yanlış yapılandırmalarını önlemek ve hata tespitini otomatikleştirmektir.

Nginxpwner, yaygın Nginx yanlış yapılandırmalarını ve güvenlik açıklarını aramak için basit bir araçtır.

Referanslar

Zafiyet değerlendirmesi ve penetrasyon testi için anında kullanılabilir kurulum. 20'den fazla araç ve özellik ile her yerden tam bir pentest gerçekleştirin; bu araçlar keşiften raporlamaya kadar uzanır. Biz pentester'ların yerini almıyoruz - onlara daha derinlemesine araştırma yapmaları, shell'leri patlatmaları ve eğlenmeleri için biraz zaman kazandırmak amacıyla özel araçlar, tespit ve istismar modülleri geliştiriyoruz.

HackTricks'i Destekleyin

Last updated