Skip to content

Repository files navigation

image

HelpDesk Portal — HTML Injection Lab

Training lab keamanan web: HTML Injection (Client-side) — php -S + SQLite, tanpa framework.

1. Tentang Lab

Aplikasi HelpDesk Portal yang sengaja dibuat rentan terhadap HTML Injection (rendering markup HTML tanpa sanitasi/output encoding). Merupakan lab mandiri untuk praktik: mengamati reflected, stored, dan cross-user HTML Injection, lalu membandingkannya dengan endpoint yang sudah di-escape dan menulis laporan.

Vulnerability : CWE-79 Improper Neutralization (konteks: HTML / markup injection)
Target        : HelpDesk Portal
Cakupan Web   : Klien (browser rendering)

Lab ini disusun hanya untuk riset & edukasi. Jangan dipakai pada sistem/produksi milik orang lain tanpa izin. Tidak ada request keluar ke internet dari aplikasi.

2. Daftar Isi

  1. Tentang Lab
  2. Daftar Isi
  3. Teknologi
  4. Cara Menjalankan
  5. Akun & Kredensial
  6. Struktur Project
  7. Peta Halaman (Endpoint)
  8. Alur Data Input
  9. Kerentanan Utama
  10. Contoh Payload
  11. Verifikasi Vuln (Reflected)
  12. Verifikasi Vuln (Stored)
  13. Verifikasi Vuln (Cross-User)
  14. Panduan Laporan (Report)
  15. QA Otomatis
  16. Catatan Termux & Troubleshooting

3. Teknologi

  • PHP 8.x (built-in development server php -S)
  • SQLite via PDO (pdo_sqlite)
  • HTML / CSS vanilla (tanpa framework, tanpa bundler)
  • Session PHP (cookie PHPSESSID)

Tidak ada dependensi composer / npm / internet.

4. Cara Menjalankan

Prasyarat: sudah terpasang php (8+), php-pdo-sqlite, dan curl.

bash jalankan.sh                # seeded + jalan di http://127.0.0.1:8010
bash jalankan.sh 8080           # port kustom
bash jalankan.sh stop           # matikan server

Database database/lab.sqlite dibuat otomatis pertama kali (seed). Untuk reset ke kondisi awal:

bash jalankan.sh stop
rm -f database/lab.sqlite
bash jalankan.sh

Di Termux chmod +x tidak berarti apa-apa — selalu jalankan dengan bash.

5. Akun & Kredensial

Kredensial default hanya dicantumkan di dokumentasi ini:

Role Username Password
admin admin Admin123!
user alice Password123!

User lain bisa didaftarkan lewat halaman registrasi (role otomatis user).

6. Struktur Project

lab-html-injection/
├── jalankan.sh            # start/stop server + seed
├── index.php              # landing (public)
├── register.php           # daftar akun baru
├── login.php / logout.php
├── dashboard.php          # beranda user + soal riset
├── profile.php            # edit profil
├── user.php               # lihat profil user lain (public)
├── tickets.php            # daftar ticket saya
├── create-ticket.php      # input description (VULN)
├── ticket.php             # detail ticket (VULN - raw render)
├── ticket-secure.php      # detail ticket (secure - escaped)
├── search.php             # pencarian ticket (VULN - reflected)
├── security-info.php      # HTML Injection vs XSS
├── report.php             # template laporan bug bounty
├── remediation.php        # cara memperbaiki
├── admin/index.php        # dashboard admin
├── admin/tickets.php      # semua ticket (cross-user meta)
├── admin/preview.php      # preview ticket admin (VULN)
├── includes/
│   ├── db.php             # SQLite + seed (users, profiles, tickets)
│   ├── auth.php           # session, login/logout, guard role
│   └── functions.php      # e(), redirect(), flash(), layout
├── assets/style.css
└── tools/ujilab.sh        # QA otomatis

7. Peta Halaman (Endpoint)

Endpoint Metode Auth Keterangan
/index.php GET publik landing page
/register.php GET/POST publik registrasi (role user)
/login.php GET/POST publik login
/logout.php GET login logout
/dashboard.php GET login beranda + 7 pertanyaan riset
/profile.php GET/POST login edit profil sendiri (DISAFE)
/user.php?id= GET publik lihat profil user lain
/tickets.php GET login daftar ticket milik sendiri
/create-ticket.php GET/POST login buat ticket (input vuln)
/ticket.php?id= GET login detail ticket (render vuln)
/ticket-secure.php?id= GET login detail ticket (escape)
/search.php?q= GET login cari ticket (reflected vuln)
/admin/* GET admin area admin (preview vuln)
/security-info.php GET login materi HTML Injection vs XSS
/report.php GET login template laporan
/remediation.php GET login panduan remediasi

profile.php dan daftar ticket sudah di-escape — dipakai untuk membandingkan perilaku safe path. Nomor role admin di-seed hanya melalui SQL.

8. Alur Data Input

  1. POST /create-ticket.php → menyimpan subject + description (plain, tanpa sanitasi) ke tabel tickets.
  2. GET /ticket.php?id=N → membaca baris tersebut dan mencetaknya mentah: <?= $ticket['description'] ?>.
  3. GET /admin/preview.php?id=N → admin membuka ticket user yang sama dengan cara render yang sama (raw) → cross-user impact.
  4. GET /search.php?q=... → mengembalikan nilai q langsung ke halaman hasil (reflected).

Perbandingan: GET /ticket-secure.php?id=N menampilkan payload sebagai teks karena htmlspecialchars(..., ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8').

9. Kerentanan Utama

  • Reflected HTML Injection/search.php?q=<payload>
  • Stored HTML Injectiondescription ticket ditampilkan mentah di /ticket.php?id= dan /admin/preview.php?id=
  • Cross-user — satu attacker (user biasa) membuat ticket berisi markup; saat admin membuka preview, markup tersebut ikut dirender di browser admin.

Catatan penting (lihat security-info.php):

HTML Injection membuktikan render markup tanpa encoding (vulnerability). Belum tentu otomatis XSS — untuk klaim XSS perlu membuktikan eksekusi JavaScript di konteks korban. Eksekusi JS bukan bagian dari lab ini.

10. Contoh Payload

Gunakan kode di bawah pada q (reflected) atau description (stored). Semua hanya markup, tanpa JavaScript.

<h2>Injected Heading</h2>
<b>Bold injected text</b>
<br>line break injected
<details><summary>Spoiler injected</summary>Hello researcher</details>
<marquee>Injected marquee</marquee>
<table border=1><tr><td>Injected table</td></tr></table>
<ul><li>Item injected 1</li><li>Item injected 2</li></ul>
<img src="http://nonexistent.invalid/x.png">       <!-- broken icon: proof of render -->
<iframe src="/">                                    <!-- embeds halaman -->
<style>body{background:#fdd}</style>
<div style="position:fixed;inset:0;background:#fff;z-index:9999">overlay</div>

Cara cepat lewat cURL (ingat: URL harus di-encode):

BASE=http://127.0.0.1:8010
J=/data/data/com.termux/files/usr/tmp/opencode/ck.curl
curl -s -c $J -b $J --data-urlencode 'username=alice' --data-urlencode 'password=Password123!' $BASE/login.php >/dev/null
# Stored:
curl -s -c $J -b $J --data-urlencode 'subject=Test' --data-urlencode 'description=<h2>Injected</h2>' $BASE/create-ticket.php -D - -o /dev/null | grep -i location
# Reflected:
curl -s -c $J -b $J "$BASE/search.php?q=%3Ch2%3EInjected%3C/h2%3E" | grep -o '<h2>Injected</h2>'

11. Verifikasi Vuln (Reflected)

  1. Login sebagai alice.
  2. Buka:
    http://127.0.0.1:8010/search.php?q=%3Ch2%3EInjected%3C%2Fh2%3E
    
  3. Amati: <h2>Injected</h2> dirender sebagai heading di blok hasil pencarian. Nilai q tidak di-escape sama sekali.

12. Verifikasi Vuln (Stored)

  1. Login sebagai alice.
  2. create-ticket.php → subject bebas, description:
    <h2>Injected from ticket</h2>
    
  3. Buka /ticket.php?id=<id ticket> → description dirender sebagai heading.
  4. Bandingkan /ticket-secure.php?id=<id> → tampil sebagai teks (&lt;h2&gt;...).

13. Verifikasi Vuln (Cross-User)

  1. Sebagai alice, buat ticket dengan description berisi markup (langkah 12).
  2. Logout, login sebagai admin (admin / Admin123!).
  3. Buka /admin/tickets.php → lihat subject ticket milik alice.
  4. Buka /admin/preview.php?id=<id> → markup dari akun alice ikut dirender di browser sesi admin.
  5. Impact: attacker user biasa dapat memodifikasi penampilan halaman yang dikonsumsi user lain / admin (defacing ringan, konten menyesatkan, potensi naik kelas ke XSS tergantung konteks).

14. Panduan Laporan (Report)

Template siap salin ada di /report.php (endpoint dalam aplikasi). Struktur:

TITLE: Stored HTML Injection in Support Ticket Description Allows Arbitrary HTML Rendering
SEVERITY: Low (default) — naik bergantung dampak
AFFECTED ENDPOINT: /create-ticket.php (input) ? /ticket.php?id= & /admin/preview.php?id= (render)
PARAMETER: description
DESCRIPTION / STEPS TO REPRODUCE / IMPACT / REMEDIATION

Rekomendasi bagi researcher: selalu sertakan Steps to Reproduce yang bisa dijalankan ulang, bukti render (screenshot atau curl), dan perbandingan dengan endpoint yang sudah di-escape.

15. QA Otomatis

Server sedang berjalan, cek seluruh flow + reproduksi vuln sekaligus:

bash tools/ujilab.sh

QA: register → login → logout → profil → create ticket → render stored (ticket vs ticket-secure) → reflected search → cross-user admin → role check (403 untuk user biasa) → support pages → bebas warning/fatal. Server di-log ke php-server.log.

16. Catatan Termux & Troubleshooting

  • /tmp tak bisa ditulis di Termux — cookie jar QA memakai /data/data/com.termux/files/usr/tmp/opencode. Set T di tools/ujilab.sh bila pindah mesin.
  • chmod +x tidak berfungsi di Termux — selalu bash jalankan.sh.
  • Port default 8010 (hindari 8000 yang sering dipakai server lain). Jika bentrok: bash jalankan.sh 8080, lalu ubah B di tools/ujilab.sh.
  • Reset penuh: stop server, hapus database/lab.sqlite, mulai lagi.
  • Resolver Android mengabaikan /etc/hosts; pakai --resolve bila butuh test domain fiktif (tidak relevan untuk lab ini).
  • Ingat: komputer admin mengirim <form> ber-action — deskripsi yang Anda lihat di /admin/preview.php adalah render dari data user tanpa filter.

Lisensi: Untuk keperluan riset & edukasi. Jangan digunakan untuk menyerang sistem yang bukan milik Anda. Namun ISI materi, kode, atau alur pengujian di lab ini boleh disalin & dikembangkan dengan menyebutkan sumber.

About

lab-html-injection: HelpDesk Portal (PHP8 + SQLite + php -S) - reflected, stored, dan cross-user HTML Injection + endpoint secure, security-info, report template, dan QA tools

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages