Insecure Deserialization — Security

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

Insecure deserialization terjadi kalau aplikasi mengubah data dari sumber yang gak dipercaya (cookie, body, header) kembali menjadi object pakai fungsi "native" yang bukan cuma membaca data, tapi juga membangun ulang object dan menjalankan method-nya. Bayangin paket pos: isi kardusnya bisa sekadar barang, atau bisa berupa robot yang begitu kardusnya dibuka langsung bergerak sendiri. json_decode membuka kardus berisi barang biasa; unserialize dan pickle.loads membuka kardus yang isinya bisa bergerak begitu dibuka.

🧪 Tebakan cepat: mana yang lebih berbahaya untuk data dari cookie, json_decode($cookie, true) atau unserialize($cookie)? Tebak dulu, jawabannya ada di bagian "Kenapa deserialization native berbahaya".

Serialization dan deserialization

Serialization mengubah object jadi teks atau bytes supaya bisa disimpan atau dikirim. Deserialization kebalikannya: dari teks kembali jadi object. Masalahnya bukan pada ide ini, tapi pada siapa yang mengirim datanya dan fungsi apa yang dipakai untuk membacanya kembali.

Kenapa deserialization native berbahaya

Lihat satu baris yang membaca preferensi user dari cookie:

// RENTAN: cookie dikontrol user
$pref = unserialize($_COOKIE["pref"]);

Cookie dikontrol user, jadi isinya bisa apa saja. unserialize gak sekadar membaca; dia membangun ulang object sesuai yang tertulis di teksnya, termasuk class dan nilainya. Saat object dibangun atau dihancurkan, PHP otomatis memanggil "magic method" seperti __wakeup (dipanggil saat object dipulihkan) dan __destruct (dipanggil saat object dibuang). Kalau di dalam kode ada class yang magic method-nya melakukan sesuatu yang kuat (menulis file, menjalankan perintah), penyerang bisa menyusun teks yang mengarah ke situ. Jadi isi cookie yang menentukan object mana yang dibangun dan method apa yang jalan.

Bandingkan dengan json_decode($_COOKIE["pref"], true): hasilnya cuma array biasa. Gak ada class yang dibangun, gak ada method yang jalan. Itu jawaban tebakannya: unserialize jauh lebih berbahaya, karena dia bisa membangun object dan memicu kode, sementara json_decode cuma menghasilkan data.

Perbaikan: JSON plus validasi

Aturan pertama: jangan deserialisasi data dari user dengan fungsi native. Untuk transport data, pakai JSON, lalu periksa isinya sebelum dipakai:

$data = json_decode($_COOKIE["pref"], true);

if (!is_array($data) || !isset($data["theme"])) {
  throw new InvalidArgumentException("Cookie tidak valid");
}

$theme = in_array($data["theme"], ["light", "dark"], true) ? $data["theme"] : "light";

Di Python, pola yang sama: json.loads(...) menggantikan pickle.loads(...). Di YAML, pakai yaml.safe_load(...), bukan yaml.load(...), karena safe_load cuma membaca data dan gak membangun object sembarang class.

Kalau terpaksa pakai format binary

Kadang kamu memang butuh menyimpan object, bukan cuma data. Kalau begitu:

⚠️ Jebakan yang sering ketemu

TL;DR: Insecure deserialization terjadi kalau data dari user dibaca dengan fungsi native yang membangun ulang object dan memicu kode, seperti unserialize, pickle.loads, ObjectInputStream.readObject, Marshal.load, atau yaml.load. Dengan unserialize($_COOKIE["pref"]), isi cookie menentukan object mana yang dibangun dan magic method (__wakeup, __destruct) apa yang jalan. Cegah dengan JSON plus validasi: json_decode, lalu periksa bentuk dan nilainya; di Python json.loads, di YAML yaml.safe_load. Kalau terpaksa pakai format binary, tanda tangani datanya dan whitelist class yang boleh dibangun.

Yang akan kamu pelajari