Training lab Web Security: mensimulasikan Clickjacking (UI Redressing) seperti yang bisa ditemukan dalam Bug Bounty Program (BBP). Berjalan 100% lokal.
Account Portal adalah aplikasi portal akun perusahaan (dummy) yang sengaja dibuat
rentan terhadap clickjacking. Halaman /account/settings.php dapat dimuat di dalam
<iframe> origin lain karena tidak mengirim header anti-framing:
X-Frame-Options❌ missingContent-Security-Policy: frame-ancestors ...❌ missing
Lab dilengkapi PoC lokal, endpoint secure pembanding, security headers inspector, template laporan BBP, remediasi, dan challenge mode (Guided / Research).
Vulnerability : Clickjacking (CWE-1021 Improper Restriction of Rendered UI Layers)
Target : Account Portal / 127.0.0.1
Difficulty : Easy
Cakupan Web : Client-Side / UI Redressing
lab-clickjacking/
├── index.php # landing (public)
├── login.php / logout.php
├── dashboard.php # beranda user + tugas riset
├── security-lab.php # hub lab (guided/research, hints, checklist, before/after)
├── security-headers.php # inspektor header anti-framing (live config)
├── remediation.php # X-Frame-Options vs CSP frame-ancestors
├── report.php # template laporan bug bounty
├── account/
│ ├── settings.php # VULNERABLE (tanpa header anti-framing)
│ └── settings-secure.php # SECURE (CSP frame-ancestors 'none' + XFO DENY)
├── attacker/
│ ├── clickjacking-poc.php # PoC: target dimuat di <iframe>
│ └── overlay-poc.php # PoC UI redressing (overlay attacker di atas target)
├── includes/
│ ├── db.php # SQLite + seed (users)
│ ├── auth.php # session, login/logout
│ └── security.php # helper & single source of truth anti-framing policy
├── assets/style.css
├── database/lab.sqlite # dibuat otomatis saat seed
└── tools/ujilab.sh # QA otomatis
Aliran data utama:
Attacker Page (attacker/clickjacking-poc.php)
│ <iframe src="http://127.0.0.1:8000/account/settings.php">
▼
/account/settings.php → tanpa X-Frame-Options / CSP frame-ancestors
▼
Browser menampilkan halaman target di dalam iframe → framing berhasil
Prasyarat: PHP 8+ dengan pdo_sqlite, dan curl.
bash jalankan.sh # seeded + jalan di http://127.0.0.1:8000
bash jalankan.sh 8080 # port kustom
bash jalankan.sh stop # matikan serverMenjalankan manual (ekuivalen):
php -S 127.0.0.1:8000Reset ke kondisi awal:
bash jalankan.sh stop
rm -f database/lab.sqlite
bash jalankan.shDi Termux
chmod +xtidak berlaku — selalu gunakanbash jalankan.sh.
Kredensial demo hanya dicantumkan di dokumentasi ini:
| Role | Username | Password |
|---|---|---|
| user | alice |
Password123 |
| admin | admin |
Admin123! |
/account/settings.php
Halaman memuat Account Settings: Display Name, Email, tombol Save Changes dan Delete Demo Account. Semua tombol hanya menampilkan "Demo action executed successfully." — tidak ada tindakan berbahaya.
VULNERABLE: halaman ini tidak mengirim X-Frame-Options maupun
Content-Security-Policy: frame-ancestors ....
- Korban sudah login ke portal (session aktif di browser).
- Attacker membuat halaman yang memuat halaman target di dalam
<iframe>. - Browser tidak dilarang memuatnya (tidak ada header anti-framing).
- Attacker menyusun UI pengecoh (overlay) dan CLI-nya; klik korban mendarat pada elemen target di dalam iframe (UI redressing).
- Dampak nyata bergantung aksi yang terpapar pada halaman yang di-frame.
Buka /attacker/clickjacking-poc.php (login dulu ke portal di tab utama):
Target : http://127.0.0.1:8000/account/settings.php
Status : Target can be framed
Halaman menampilkan:
<iframe src="http://127.0.0.1:8000/account/settings.php" width="700" height="500"></iframe>Jika session login aktif, halaman Account Settings tampil utuh di dalam iframe.
PoC kedua /attacker/overlay-poc.php mendemonstrasikan konsep overlay UI redressing.
PoC lokal saja — tidak ada request keluar dari aplikasi.
Payload PoC dasar (disalin dari halaman Security Lab / /security-lab.php):
<iframe src="http://127.0.0.1:8000/account/settings.php" width="800" height="600"></iframe>Payload overlay (UI redressing):
<div class="overlay">
Click here to continue
</div>
<iframe src="http://127.0.0.1:8000/account/settings.php"></iframe>Panjang-URL target menyesuaikan port yang dipakai (lihat app_base() di
includes/security.php).
VULNERABLE — halaman target dimuat sukses di dalam iframe. Ini menandakan aplikasi saat ini tidak mencegah dirinya di-frame.
PROTECTED — bila header proteksi ditambahkan, browser menolak memuat halaman di
dalam iframe. Bandingkan dengan /account/settings-secure.php yang sudah dilindungi.
Dampak clickjacking tidak otomatis High/Critical. Severity bergantung: apakah target dapat di-frame, korban harus login, ada sensitive action, aksi bisa dilakukan lewat satu click, ada/tidaknya CSRF protections, kemampuan menipu UI, dan dampak aksi tersebut.
Template siap salin di /report.php. Ringkasannya:
Title : Clickjacking on /account/settings.php Due to Missing Anti-Framing Headers
Severity : Low
Steps : login → buka /account/settings.php → buka /attacker/clickjacking-poc.php
→ amati iframe memuat halaman → berinteraksi dengan framed page
Impact : attacker dapat men-embed UI sensitif; dampak bergantung aksi yang terpapar
Remediation : X-Frame-Options dan/atau CSP frame-ancestors
Option 1 — X-Frame-Options
X-Frame-Options: DENY
# atau
X-Frame-Options: SAMEORIGINDENY = tidak boleh di-frame dari origin mana pun. SAMEORIGIN = hanya boleh oleh
origin yang sama.
Option 2 — Content-Security-Policy
Content-Security-Policy: frame-ancestors 'none';
# atau bila framing dari origin tertentu memang diperlukan:
Content-Security-Policy: frame-ancestors 'self';CSP frame-ancestors adalah kontrol modern untuk menentukan siapa boleh me-frame
halaman. Pasang keduanya untuk kompatibilitas browser lama.
/account/settings-secure.php mengirim:
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none';Percobaan framing terhadap endpoint ini gagal (iframe kosong / diblokir browser).
| Endpoint | Status |
|---|---|
/account/settings.php |
❌ Vulnerable (dapat di-frame) |
/account/settings-secure.php |
✅ Protected (framing diblokir) |
Setelah menyelesaikan lab, researcher diharapkan mampu:
- Mengidentifikasi endpoint yang terpapar framing
- Membuktikan tidak adanya proteksi anti-framing (XFO / CSP frame-ancestors)
- Mereproduksi framing via PoC lokal
- Menggunakan PoC untuk memahami UI redressing
- Menjelaskan dampak secara realistis tanpa melebih-lebihkan
- Memilih remediasi yang tepat
- Memverifikasi endpoint secure sebagai pembanding
- Target hanya
127.0.0.1— seluruh vulnerability sengaja dibuat untuk: Security Education, Bug Bounty Training, Authorized Testing, dan Secure Coding. - Jangan mengklaim account takeover / data theft bila lab tidak membuktikannya.
- Tidak ada request ke domain eksternal; tidak ada cookie harvesting; seluruh aksi di lab adalah demo yang aman.
- Selalu ajukan izin (authorization) sebelum menguji sistem yang bukan milik Anda.
