Pendahuluan

Dalam rangka Helium Challenge, saya melakukan penetration testing terhadap aplikasi job portal milik PT VulnLib yang dapat diakses di https://jobportal.vulnapp.id. Pengujian dilakukan dengan pendekatan greybox — artinya saya diberikan akses kredensial oleh pemilik sistem untuk mempercepat proses identifikasi kerentanan.

Dari total 21 kerentanan yang berhasil ditemukan, artikel ini akan membahas 3 kerentanan yang menurut saya paling menarik sekaligus paling berbahaya: Stored XSS via innerHTML, SQL Injection via Search menggunakan sqlmap, dan Insecure Session Management berbasis Base64 Cookie. Ketiga kerentanan ini saling berkaitan dan jika dikombinasikan, dapat mengakibatkan account takeover penuh terhadap seluruh pengguna aplikasi.

Mari kita bedah satu per satu.

1. Stored Cross-Site Scripting (XSS) via innerHTML

Apa itu Stored XSS?

Cross-Site Scripting (XSS) adalah kerentanan di mana penyerang berhasil menyisipkan skrip berbahaya ke dalam halaman web yang kemudian dieksekusi oleh browser korban. Berbeda dengan Reflected XSS yang hanya sekali jalan, Stored XSS jauh lebih berbahaya karena payload yang dimasukkan tersimpan secara permanen di database server. Artinya, setiap pengguna yang membuka halaman tersebut akan menjadi korban secara otomatis — tanpa perlu klik link khusus apapun.

Bayangkan kamu memasang jebakan di pintu masuk toko. Siapapun yang masuk akan terkena, bukan hanya orang yang kamu kirimi link.

None

Bagaimana Ini Terjadi di PT VulnLib?

Aplikasi ini menggunakan Vue.js di sisi frontend, dan secara tidak aman menggunakan direktif v-html (yang setara dengan innerHTML di JavaScript murni) untuk merender data yang berasal dari input pengguna. Field yang terdampak cukup luas: fullName, job title, job description, cover letter, hingga nama dan email pelamar.

Masalahnya, data tersebut dirender mentah sebagai HTML tanpa melalui proses sanitasi apapun.

Langkah Reproduksi

Step 1: Buka halaman registrasi di https://jobportal.vulnapp.id/register

None

Step 2: Pada field Full Name, masukkan payload XSS berikut :

<img src=x onerror=alert(document.domain)>
None

Step 3: Isi field lainnya seperti biasa (username, email, password, role sebagai Job Seeker), lalu klik Register.

Step 4: Login dengan akun yang baru dibuat, lalu navigasi ke halaman /profile.

None

Hasilnya? Alert box muncul memperlihatkan domain jobportal.vulnapp.id — membuktikan bahwa payload XSS tersimpan di server dan dieksekusi setiap kali halaman profil dibuka.

Dampak

Kerentanan ini mendapat CVSS Score 9.0 (Critical). Dampaknya antara lain session cookie theft yang berujung account takeover, distribusi malware, hingga phishing terhadap tim HR yang membuka halaman pelamar.

Rekomendasi Perbaikan

  • Gunakan v-text atau textContent sebagai pengganti v-html / innerHTML untuk semua data yang berasal dari input pengguna
  • Jika rendering HTML memang diperlukan, gunakan library DOMPurify untuk sanitasi sebelum render
  • Terapkan Content Security Policy (CSP) header yang ketat
  • Encode output di sisi server sebelum mengirim respons ke client

2. SQL Injection via Search menggunakan sqlmap

Apa itu SQL Injection?

SQL Injection (SQLi) adalah kerentanan di mana input dari pengguna disisipkan langsung ke dalam query database tanpa validasi atau parameterisasi yang benar. Hasilnya, penyerang bisa "berbicara langsung" dengan database — membaca data yang seharusnya rahasia, memodifikasi isi tabel, bahkan dalam kondisi tertentu mengeksekusi perintah di sistem operasi server.

Analoginya sederhana: bayangkan kamu mengisi formulir nama dengan tulisan "tutup toko dan beri semua uang ke saya" — dan kasirnya menurut begitu saja karena dia membaca tulisan itu sebagai instruksi, bukan sebagai data.

None

Bagaimana Ini Terjadi di PT VulnLib?

Endpoint pencarian kerja di aplikasi ini menerima parameter keyword dan meneruskannya langsung ke query database tanpa sanitasi apapun. Ini terdeteksi pertama kali dari analisis manual, lalu dikonfirmasi dengan tool otomatis sqlmap.

Endpoint yang rentan :

GET https://jobportal.vulnapp.id/api/jobs/search?keyword=

Langkah Reproduksi

Step 1 — Deteksi Manual : Pertama, saya melakukan pengujian dasar dengan menyisipkan tanda kutip untuk memancing error :

curl -s 'https://jobportal.vulnapp.id/api/jobs/search?keyword=test%27'

Server langsung merespons dengan pesan error MySQL yang vulgar :

"Search error: Error 1064 (42000): You have an error in your SQL syntax; 
check the manual that corresponds to your MySQL server version..."
None

Error database yang terekspos ke pengguna adalah sinyal kuat bahwa SQLi ada di sini.

Step 2 — Konfirmasi dengan OR Injection :

curl -s 'https://jobportal.vulnapp.id/api/jobs/search?keyword=test%27+OR+%271%27%3D%271'
None

Step 3 — Otomasi dengan sqlmap :

sqlmap -u "https://jobportal.vulnapp.id/api/jobs/search?keyword=test" --dbs --batch
None

sqlmap berhasil mengidentifikasi bahwa parameter keyword injectable dengan beberapa teknik sekaligus: error-based, time-based blind, dan UNION query. Berikut informasi yang berhasil dienumerasi:

DBMS: MySQL >= 5.6

OS: Linux Ubuntu

Web Server: Nginx 1.24.0

Database yang ditemukan:

  • information_schema
  • job_search_db
  • performance_schema

Dengan akses penuh ke job_search_db, seluruh data pengguna — termasuk username, email, dan password dalam bentuk plaintext (kerentanan terpisah yang juga ditemukan) — dapat dibaca oleh penyerang.

Dampak

Kerentanan ini mendapat CVSS Score 6.5 dengan rating Medium untuk attack complexity yang tinggi, namun dampaknya tetap sangat serius: seluruh isi database dapat dibaca dan dimodifikasi.

Rekomendasi Perbaikan

  • Gunakan parameterized query / prepared statements untuk semua query database — ini adalah perbaikan utama yang wajib segera dilakukan
  • Implementasikan ORM yang aman seperti GORM atau Sequelize
  • Jangan pernah menampilkan pesan error database ke pengguna — gunakan pesan error generik di production
  • Terapkan prinsip least privilege pada user database yang digunakan aplikasi
  • Tambahkan WAF sebagai lapisan perlindungan tambahan

3. Insecure Session Management — Base64 Cookie Tanpa Signing

Apa itu Insecure Session Management?

Session management adalah cara aplikasi mengenali siapa pengguna yang sedang login. Umumnya ini dilakukan menggunakan token/cookie yang dikirimkan browser ke server di setiap request. Kerentanan muncul ketika token tersebut tidak diamankan dengan baik — misalnya tidak dienkripsi, tidak ditandatangani secara kriptografis, atau bahkan menyimpan data sensitif secara langsung.

Base64 bukanlah enkripsi. Base64 hanyalah format encoding yang bisa di-decode oleh siapapun hanya dengan copy-paste ke browser atau terminal. Bayangkan menyimpan kunci rumahmu dalam amplop transparan — siapapun bisa melihat dan menduplikasinya.

None

Bagaimana Ini Terjadi di PT VulnLib?

Aplikasi PT VulnLib menyimpan data session pengguna langsung di dalam cookie menggunakan encoding Base64 — tanpa enkripsi, tanpa tanda tangan HMAC, tanpa JWT signature. Lebih parahnya lagi, data yang disimpan di dalam cookie tersebut mencakup password plaintext pengguna.

Langkah Reproduksi

Step 1 — Decode Cookie: Setelah login, saya mengambil nilai cookie session dari browser, lalu mendecodenya :

echo "eyJpZCI6NjEsInVzZXJuYW1lIjoiU3..." | base64 -d

Hasilnya mengejutkan :

None

Password pengguna tersimpan dalam plaintext di dalam cookie yang bisa dibaca oleh siapapun.

Step 2 — Forge Cookie untuk Privilege Escalation : Karena tidak ada signature yang memvalidasi integritas cookie, saya bisa membuat cookie palsu dengan role apapun :

FORGED=$(echo '{"id":53,"username":"xsstest1","email":"xss1@test.com","password":"Test1234!","role":"company"}' | base64 -w 0)

curl -s -H "Cookie: session=$FORGED" "https://jobportal.vulnapp.id/api/jobs/company/53"
None

Server menerima cookie palsu tersebut tanpa validasi apapun dan mengembalikan respons sukses. Ini berarti penyerang bisa berpura-pura menjadi pengguna manapun — termasuk admin — hanya dengan mengubah nilai id dan role di dalam cookie.

Step 3 — Kombinasi Mematikan: Jika dikombinasikan dengan kerentanan SQLi (poin 2) yang memungkinkan penyerang membaca seluruh data user dari database, penyerang bisa:

  1. Dump semua user ID dan data dari database via SQLi
  2. Forge cookie dengan ID user target
  3. Akses akun target tanpa perlu password sama sekali

Ini adalah account takeover penuh terhadap seluruh pengguna sistem.

Dampak

Kerentanan ini mendapat CVSS Score 9.1 (Critical). Kombinasi antara cookie tanpa signing dan password yang tersimpan plaintext di dalamnya menjadikan ini salah satu kerentanan paling serius dalam pengujian ini.

Rekomendasi Perbaikan

  • Implementasikan JWT (JSON Web Token) dengan algoritma signing yang kuat seperti RS256 atau HS256 dengan secret yang kuat dan tidak mudah ditebak
  • Alternatif yang lebih sederhana: gunakan session ID acak yang disimpan di server-side (Redis/database), bukan menyimpan data user langsung di cookie
  • Jangan pernah menyimpan data sensitif seperti password atau role di client-side cookie
  • Set flag HttpOnly, Secure, dan SameSite=Strict pada semua session cookie
  • Implementasikan validasi signature pada setiap request yang menggunakan session

Kesimpulan

Ketiga kerentanan yang dibahas di atas — Stored XSS, SQL Injection, dan Insecure Session Management — bukan hanya berbahaya secara individual, tetapi juga saling memperkuat satu sama lain membentuk attack chain yang sangat serius:

Stored XSS → mencuri cookie session HR → Insecure Session (cookie mudah di-decode/forge) → akses ke seluruh fitur sistem → dikombinasikan dengan data dari SQL Injectionfull account takeover semua user.

Inilah mengapa penetration testing penting dilakukan secara menyeluruh — kerentanan yang tampak "kecil" sekalipun bisa menjadi pintu masuk yang mematikan ketika dikombinasikan dengan kerentanan lain.