CODEBOOK
Website Platform Belajar Dan Edukasi
By Shadownex 2025-2026
← Kembali ke Katalog Lab
File Upload & RCEUNSOLVEDReward: +150 XP

Lab 4: Arbitrary file upload allowing webshell remote code execution

Formulir upload foto profil tidak memvalidasi ekstensi file maupun MIME type, serta menyimpan file langsung di folder publik web server.

TARGET OBJECTIVE & BRIEFING

Objective:

Unggah file script eksekutabel backdoor (.php) untuk mendapatkan webshell remote terminal dan dapatkan file flag.

Fitur pengubahan avatar pada portal pengguna menyimpan file yang diunggah langsung ke direktori publik `/uploads/`. Karena web server dikonfigurasi untuk mengeksekusi skrip PHP pada direktori tersebut, file PHP yang diunggah akan dieksekusi sebagai Remote Code Execution (RCE).

PENTESTING METHODOLOGY
1. Buka halaman pengubahan foto profil pengguna.
2. Pilih file skrip backdoor berformat `.php` (misal: `backdoor_webshell.php`).
3. Unggah file dan perhatikan lokasi URL file yang dikembalikan oleh server.
4. Akses webshell yang aktif dan jalankan perintah terminal seperti `cat /var/www/flag.txt` untuk mendapatkan Flag.
CODE SECURITY INSPECTION

Apabila web server mengeksekusi file .php di folder uploads publik, penyerang mendapatkan kendali RCE (Remote Code Execution) penuh. CodeBook merandomisasi nama file ke UUID dan menyimpannya di Cloud Bucket non-executable.

VULNERABLE CODE

// KODE RENTAN (No File Type / Extension Sanitize)
app.post('/upload', (req, res) => {
  const file = req.files.avatar;
  // DANGEROUS: Menyimpan file asli langsung di folder publik web server!
  file.mv('./public/uploads/' + file.name, () => {
    res.json({ url: '/uploads/' + file.name });
  });
});

SECURE CODEBOOK IMPLEMENTATION

// KODE AMAN CODEBOOK STANDARD (UUID, Magic Bytes & Cloud Storage)
app.post('/upload', async (req, res) => {
  const file = req.files.avatar;
  
  // SAFE 1: Validasi Header Binary (Magic Bytes)
  if (!isImageMagicBytes(file.data)) return res.status(400).send('Invalid Image');
  
  // SAFE 2: Nama acak UUID + Simpan di Storage Terisolasi Non-Executable
  const safeFilename = `${uuidv4()}.jpg`;
  const url = await uploadToS3Sandbox(safeFilename, file.data);
  res.json({ url });
});