Deserialisasi tidak aman: risiko dan mitigasi
Risiko data pickle, Java serialization, dan PHP unserialize yang tidak tepercaya serta cara mengganti atau membatasinya.
💡 Penjelasan sederhana (ELI5)
Serialization seperti mengirim petunjuk merakit model melalui pos. Deserialization mengikuti petunjuk itu untuk membangun kembali data. Sebagian format juga dapat menunjuk kelas atau memanggil hook saat rekonstruksi. Menerima instruksi yang tidak tepercaya dapat memicu perilaku tak diinginkan; dampaknya bergantung pada format, runtime, kelas yang tersedia, dan konteks aplikasi.
Core Concepts & Key Terms
- Serialization / deserialization
- Mengubah data atau objek menjadi representasi untuk disimpan atau dikirim, lalu mengurai atau membangunnya kembali di program.
- Hook deserialization
- Callback seperti Python __reduce__, Java readObject, atau PHP __wakeup / __unserialize yang dapat berjalan saat objek direkonstruksi.
- Gadget chain
- Rangkaian perilaku library yang sudah tersedia untuk menghasilkan efek tak diinginkan. Ketersediaannya bergantung pada aplikasi dan versi.
- Filter deserialization
- Kebijakan untuk membatasi kelas atau metrik graf saat membaca object stream. Ini mengurangi risiko tetapi tidak menjadikan stream objek native tak tepercaya sebagai pilihan utama.
How Unsafe Deserialization Can Become an Exploit Chain
Byte tak tepercaya mencapai decoder
Cookie, body API, pesan antrean, atau catatan tersimpan berisi data yang dapat dipengaruhi penyerang.
Aplikasi memanggil format objek native
Kode meneruskan byte itu ke decoder seperti Python pickle, Java ObjectInputStream, atau PHP unserialize().
Rekonstruksi memicu perilaku khusus format
Bergantung pada format dan kelas yang dapat dijangkau, constructor, hook, autoloading, atau metode library dapat berjalan sebelum validasi aplikasi.
Dampak bergantung pada perilaku yang tersedia
Gadget atau hook yang dapat dipakai mungkin menimbulkan efek tanpa izin; input lain hanya gagal atau menghabiskan sumber daya. Eksekusi kode tidak otomatis terjadi di semua kasus.
Python / Flask: Unsafe Object Loading vs. Primitive JSON Validation
# VULNERABLE: pickle can execute behavior during unpickling.
from flask import Flask, request
import pickle
app = Flask(__name__)
@app.post("/api/session")
def load_session():
# Never deserialize attacker-controlled bytes with pickle.
session = pickle.loads(request.get_data())
return {"user_id": session.user_id}
# SAFER: parse JSON primitives, then validate expected shape.
from flask import Flask, abort, request
app = Flask(__name__)
app.config["MAX_CONTENT_LENGTH"] = 16 * 1024
@app.post("/api/session")
def load_session():
payload = request.get_json()
if not isinstance(payload, dict):
abort(400, "Expected a JSON object")
user_id = payload.get("user_id")
if type(user_id) is not int or user_id <= 0:
abort(400, "Invalid user_id")
# Resolve authorization and session state server-side.
return {"user_id": user_id}
Daftar periksa penguatan keamanan
JSON juga tetap memerlukan batas ukuran input dan validasi struktur. Untuk format objek lama, jangan hanya mengandalkan allowlist kelas: autentikasi byte serialisasi yang persis sebelum deserialisasi dan lindungi kuncinya. MAC tidak mengenkripsi data atau mencegah replay.
- Jangan deserialisasi native object stream yang tidak tepercaya dengan Python pickle atau PHP unserialize; pilih data primitif seperti JSON dengan validasi schema dan ukuran.
- Jika Java serialization belum dapat dihapus, konfigurasi allowlist ObjectInputFilter dan batas graf; filter tidak otomatis aktif di semua deployment.
- Untuk integritas payload lama, autentikasi byte persis sebelum deserialization dengan kunci MAC yang dikelola aman; MAC bukan enkripsi dan tidak mencegah replay.
- Simpan otoritas sesi di server atau gunakan token bertanda tangan dari framework terpelihara dengan expiry, audience, dan rotasi kunci.