mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/network-services-pentesting/pentesting-web/nginx.md'] t
This commit is contained in:
parent
fa4296e7ce
commit
b499eb897f
BIN
src/images/nginx_try_files.png
Normal file
BIN
src/images/nginx_try_files.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 190 KiB |
@ -16,19 +16,19 @@ proxy_pass http://127.0.0.1:8080/;
|
||||
}
|
||||
}
|
||||
```
|
||||
Bu yapılandırmada, `/etc/nginx` kök dizin olarak belirlenmiştir. Bu ayar, belirtilen kök dizin içindeki dosyalara, örneğin `/hello.txt`, erişim sağlar. Ancak, yalnızca belirli bir konum (`/hello.txt`) tanımlandığını belirtmek önemlidir. Kök konumu için (`location / {...}`) herhangi bir yapılandırma yoktur. Bu eksiklik, kök direktifinin genel olarak geçerli olduğu 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ırmada, `/etc/nginx` kök dizin olarak belirlenmiştir. Bu ayar, belirtilen kök dizin içindeki dosyalara, örneğin `/hello.txt`, erişim sağlar. Ancak, yalnızca belirli bir konum (`/hello.txt`) tanımlandığını belirtmek önemlidir. Kök konumu için (`location / {...}`) bir yapılandırma yoktur. Bu eksiklik, kök direktifinin genel olarak geçerli olduğu anlamına gelir ve kök yolu `/` altındaki dosyalara erişim sağlar.
|
||||
|
||||
Bu yapılandırmadan kaynaklanan kritik bir güvenlik durumu 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`, 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.
|
||||
Bu yapılandırmadan kaynaklanan kritik bir güvenlik dikkate alınmalıdı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`, 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şim izni verebilir.
|
||||
|
||||
## Alias LFI Yanlış Yapılandırması <a href="#alias-lfi-misconfiguration" id="alias-lfi-misconfiguration"></a>
|
||||
|
||||
Nginx'in yapılandırma dosyalarında, "location" direktifleri için dikkatli bir inceleme gereklidir. Yerel Dosya Dahil Etme (LFI) olarak bilinen bir zafiyet, aşağıdaki gibi bir yapılandırma aracılığıyla istemeden tanıtılabilir:
|
||||
Nginx yapılandırma dosyalarında, "location" direktifleri için dikkatli bir inceleme gereklidir. Yerel Dosya Dahil Etme (LFI) olarak bilinen bir zafiyet, aşağıdaki gibi bir yapılandırma aracılığıyla istemeden 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 etkili bir şekilde `/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 yapılandırma, sunucunun `/imgs../flag.txt` gibi istekleri, hedef dizinin dışındaki dosyalara erişim girişimi olarak yorumlaması nedeniyle LFI saldırılarına açıktır ve bu da etkili bir şekilde `/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:
|
||||
```
|
||||
@ -65,23 +65,23 @@ deny all;
|
||||
## Güvensiz değişken kullanımı / HTTP İstek Bölme <a href="#unsafe-variable-use" id="unsafe-variable-use"></a>
|
||||
|
||||
> [!CAUTION]
|
||||
> Zayıf değişkenler `$uri` ve `$document_uri` ve bunlar `$request_uri` ile değiştirilerek düzeltilebilir.
|
||||
> Gü vulnerable değişkenler `$uri` ve `$document_uri` ve bunlar `$request_uri` ile değiştirilerek düzeltilebilir.
|
||||
>
|
||||
> Bir regex de zayıf olabilir:
|
||||
> Bir regex de şu şekilde savunmasız olabilir:
|
||||
>
|
||||
> `location ~ /docs/([^/])? { … $1 … }` - Zayıf
|
||||
> `location ~ /docs/([^/])? { … $1 … }` - Savunmasız
|
||||
>
|
||||
> `location ~ /docs/([^/\s])? { … $1 … }` - Zayıf değil (boşlukları kontrol ediyor)
|
||||
> `location ~ /docs/([^/\s])? { … $1 … }` - Savunmasız değil (boşlukları kontrol ediyor)
|
||||
>
|
||||
> `location ~ /docs/(.*)? { … $1 … }` - Zayıf değil
|
||||
> `location ~ /docs/(.*)? { … $1 … }` - Savunmasız değil
|
||||
|
||||
Nginx yapılandırmasındaki bir zayıflık aşağıdaki örnekle gösterilmektedir:
|
||||
Nginx yapılandırmasındaki bir zafiyet 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 beklenmeyen bir başlık oluşur:
|
||||
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
|
||||
@ -127,13 +127,63 @@ 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 kalmakla birlikte, nadir ya da doğrulaması basit değildir. Bu anomali, HackerOne'da bir güvenlik raporunda vurgulanmıştır, rapora [buradan](https://hackerone.com/reports/370094) ulaşabilirsiniz. Hata mesajı üzerindeki daha fazla araştırma, bunun [Nginx'in kod tabanındaki SSI filtre modülünde](https://github.com/nginx/nginx/blob/2187586207e1465d289ae64cedc829719a048a39/src/http/modules/ngx_http_ssi_filter_module.c#L365) meydana geldiğini belirlemiş ve Sunucu Tarafı Dahil Etmelerin (SSI) kök neden olduğunu ortaya çıkarmıştır.
|
||||
**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 kalmakla birlikte, nadir ya da doğrulaması kolay değildir. Bu anomali, HackerOne'da bir güvenlik raporunda vurgulanmıştır, [buradan](https://hackerone.com/reports/370094) görüntülenebilir. Hata mesajı üzerindeki daha fazla araştırma, bunun [Nginx'in kod tabanındaki SSI filtre modülünde](https://github.com/nginx/nginx/blob/2187586207e1465d289ae64cedc829719a048a39/src/http/modules/ngx_http_ssi_filter_module.c#L365) 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:
|
||||
Bu **yanlış yapılandırmayı tespit etmek** için, değişken yazdırmayı test etmek amacıyla bir referer başlığı ayarlamayı içeren aşağıdaki komut çalıştırılabilir:
|
||||
```bash
|
||||
$ curl -H ‘Referer: bar’ http://localhost/foo$http_referer | grep ‘foobar’
|
||||
```
|
||||
Bu yanlış yapılandırmanın sistemler arasında taranması, Nginx değişkenlerinin bir kullanıcı tarafından yazdırılabileceği birçok ö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.
|
||||
Bu yanlış yapılandırma için sistemler arasında yapılan taramalar, 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.
|
||||
|
||||
### $URI$ARGS değişkenleri ile try_files kullanımı
|
||||
|
||||
Aşağıdaki Nginx yanlış yapılandırması, bir LFI zafiyetine yol açabilir:
|
||||
```
|
||||
location / {
|
||||
try_files $uri$args $uri$args/ /index.html;
|
||||
}
|
||||
```
|
||||
Yapılandırmamızda, belirtilen sırada dosyaların varlığını kontrol etmek için kullanılan `try_files` direktifi bulunmaktadır. Nginx, bulduğu ilk dosyayı sunacaktır. `try_files` direktifinin temel sözdizimi aşağıdaki gibidir:
|
||||
```
|
||||
try_files file1 file2 ... fileN fallback;
|
||||
```
|
||||
Nginx, belirtilen sırada her dosyanın varlığını kontrol edecektir. Eğer bir dosya mevcutsa, hemen sunulacaktır. Eğer belirtilen dosyalardan hiçbiri mevcut değilse, istek yedek seçeneğe iletilecektir; bu başka bir URI veya belirli bir hata sayfası olabilir.
|
||||
|
||||
Ancak, bu yönerge içinde `$uri$args` değişkenlerini kullanırken, Nginx, istek URI'sı ile herhangi bir sorgu dizesi argümanını birleştirerek eşleşen bir dosya aramaya çalışacaktı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 yük ile:
|
||||
```
|
||||
GET /?../../../../../../../../etc/passwd HTTP/1.1
|
||||
Host: example.com
|
||||
```
|
||||
Kullanarak payload'ımız kök dizininden (Nginx yapılandırmasında tanımlanan) çıkacağız ve `/etc/passwd` dosyasını yükleyeceğiz. Hata ayıklama günlüklerinde 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
|
||||
|
||||
```
|
||||
Nginx'e karşı yukarıda belirtilen yapılandırmayı kullanarak PoC:
|
||||

|
||||
|
||||
## Ham arka uç yanıtı okuma
|
||||
|
||||
@ -145,7 +195,7 @@ 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:
|
||||
Bunu yönetmek için, Nginx yapılandırmasında belirli direktifler kullanılır:
|
||||
```
|
||||
http {
|
||||
error_page 500 /html/error.html;
|
||||
@ -160,15 +210,15 @@ Geçerli bir `GET` isteği yapıldığında, Nginx bunu normal şekilde işler v
|
||||
|
||||
## 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, özellikle yerel dosya dahil etme (LFI) saldırılarına yatkın olanların, zayıflıklarını 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.
|
||||
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](https://medium.com/appsflyer/nginx-may-be-protecting-your-applications-from-traversal-attacks-without-you-even-knowing-b08f882fd43d) bağlantısına bakabilirsiniz.
|
||||
Daha fazla bilgi için [Danny Robinson ve Rotem Bar](https://medium.com/appsflyer/nginx-may-be-protecting-your-applications-from-traversal-attacks-without-you-even-knowing-b08f882fd43d) bağlantısını kontrol edin.
|
||||
|
||||
### **Maclicious Yanıt Başlıkları**
|
||||
|
||||
[**bu yazıda**](https://mizu.re/post/cors-playground) gösterildiği gibi, web sunucusundan gelen yanıtta mevcut olan belirli başlıklar, Nginx proxy'sinin davranışını değiştirecektir. Bunları [**belgelere**](https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/) bakarak kontrol edebilirsiniz:
|
||||
[**bu yazıda**](https://mizu.re/post/cors-playground) 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**](https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/) 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.
|
||||
@ -199,26 +249,26 @@ return 200 "Hello. It is private area: $mappocallow";
|
||||
}
|
||||
}
|
||||
```
|
||||
Varsayılan bir `default` olmadan, **kötü niyetli bir kullanıcı** `/map-poc` içinde **tanımsız bir URI**'ye erişerek güvenliği aşabilir. [Nginx kılavuzu](https://nginx.org/en/docs/http/ngx_http_map_module.html), bu tür sorunları önlemek için bir **varsayılan değer** ayarlamayı önerir.
|
||||
Varsayılan bir `default` olmadan, **kötü niyetli bir kullanıcı** `/map-poc` içinde **tanımsız bir URI**'ye erişerek güvenliği atlayabilir. [Nginx kılavuzu](https://nginx.org/en/docs/http/ngx_http_map_module.html), 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. 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:
|
||||
Nginx'e karşı DNS spoofing, belirli koşullar altında mümkündür. 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)**'i DNS çözümü için kullanacak şekilde yapılandırılmışsa, bu yöntem etkisizdir. Nginx, bir DNS sunucusunu aşağıdaki gibi belirtmeye izin verir:
|
||||
```yaml
|
||||
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 kendiliğinden bir zafiyet oluşturmasa da, yapılandırmalarının dikkatlice incelenmesi gerekmektedir; aksi takdirde güvenlik açıkları oluşabilir.
|
||||
**`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ı dikkatli bir şekilde incelenmelidir, aksi takdirde güvenlik açıklarına yol açabilir.
|
||||
|
||||
## 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ç noktalara erişmek için bir [**h2c Smuggling saldırısı**](../../pentesting-web/h2c-smuggling.md) gerçekleştirilebilir.
|
||||
|
||||
> [!CAUTION]
|
||||
> Bu zafiyet, bir saldırganın **`proxy_pass` uç noktası ile doğrudan bir bağlantı kurmasına** (bu durumda `http://backend:9999`) izin verecektir; bu içeriğin nginx tarafından kontrol edilmeyeceği anlamına gelir.
|
||||
> 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 savunmasız yapılandırma örneği [buradan](https://bishopfox.com/blog/h2c-smuggling-request) alınmıştır:
|
||||
`/flag` çalmak için zayıf yapılandırma örneği [buradan](https://bishopfox.com/blog/h2c-smuggling-request):
|
||||
```
|
||||
server {
|
||||
listen 443 ssl;
|
||||
@ -239,7 +289,7 @@ deny all;
|
||||
}
|
||||
```
|
||||
> [!WARNING]
|
||||
> `proxy_pass` belirli bir **path**'e, örneğin `http://backend:9999/socket.io` gibi yönlendirilse bile, bağlantı `http://backend:9999` ile kurulacaktır, bu nedenle o iç uç noktasındaki **herhangi bir diğer path** ile iletişim kurabilirsiniz. Bu nedenle, proxy_pass URL'sinde bir path belirtilip belirtilmediği önemli değildir.
|
||||
> `proxy_pass` belirli bir **path**'e, örneğin `http://backend:9999/socket.io` yönlendirilse bile, bağlantı `http://backend:9999` ile kurulacaktır, bu nedenle o iç uç noktasındaki **herhangi bir diğer path** ile iletişim kurabilirsiniz. Bu nedenle, proxy_pass URL'sinde bir path belirtilip belirtilmediği önemli değildir.
|
||||
|
||||
## Kendin dene
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user