flawopen.com/Deserialisasi tidak aman/PHP unserialize()
Apakah PHP unserialize() aman untuk input tak tepercaya?
Jangan berikan input tak tepercaya ke unserialize(), bahkan saat allowed_classes ditetapkan. PHP dapat memulihkan objek dan memanggil __unserialize() atau __wakeup(); penyerang dapat memanfaatkan kelas yang tersedia di aplikasi atau autoloader. Gunakan JSON untuk data tak tepercaya. Dengan decoding asosiatif, objek JSON menjadi array dan tidak membuat instance kelas aplikasi yang memiliki perilaku magic method.
<?php // Cookie content is controlled by the client. $input = $_COOKIE['prefs'] ?? ''; $data = unserialize($input); // Restoring an object may invoke its // __unserialize() or __wakeup() method. // Later object destruction may invoke __destruct(). // The risk depends on available classes, // their serialized state, and reachable behavior.
<?php
$input = $_POST['prefs'] ?? null;
if (!is_string($input)) {
http_response_code(400);
exit;
}
try {
$data = json_decode(
$input,
true,
512,
JSON_THROW_ON_ERROR
);
} catch (JsonException $e) {
http_response_code(400);
exit;
}
if (!is_array($data)) {
http_response_code(400);
exit;
}
// Validate required keys and value types here.
Syarat rantai injeksi objek PHP
Risiko injeksi objek tidak berarti kode otomatis dijalankan. Nilai serialisasi harus menyebut kelas yang dapat ditemukan PHP dan diizinkan oleh opsi; pemulihan atau penggunaan selanjutnya juga harus mencapai perilaku yang berdampak pada keamanan. PHP dapat memanggil __unserialize() atau __wakeup() saat memulihkan objek; __destruct() dapat berjalan saat objek dihancurkan dan __toString() hanya dalam konteks string.
Rantai Property-Oriented Programming (POP) menghubungkan perilaku yang sudah ada di aplikasi atau dependensi yang dimuat. Eksploitabilitas bergantung pada kelas nyata, properti serialisasi, jalur panggilan, dan kondisi runtime. Rantai gadget untuk target harus dibuktikan; keberadaan unserialize() saja tidak membuktikannya.
Mengapa filter string dan allowed_classes bukan perbaikan lengkap
Memblokir penanda seperti O:, memfilter nama kelas, atau membatasi panjang string tidak memvalidasi serialisasi PHP dengan aman. Yang lebih penting, PHP secara eksplisit memperingatkan agar input tak tepercaya tidak diberikan ke unserialize(), apa pun nilai allowed_classes. Kelas yang tidak diizinkan menjadi objek __PHP_Incomplete_Class, tetapi strukturnya tetap diparsing. Untuk data lama tepercaya, validasi bentuk hasil dan batasi kedalaman. Utamakan JSON untuk state dari klien.
Pertanyaan umum
Tidak. Opsi ini mencegah pemulihan normal kelas aplikasi; objek yang tidak diizinkan menjadi __PHP_Incomplete_Class. PHP tetap memperingatkan agar input tak tepercaya tidak diberikan ke unserialize(), meski opsi ini digunakan. Pakai hanya sebagai defense-in-depth untuk data lama tepercaya, validasi hasil, dan batasi max_depth. Manual PHP juga menyatakan opsi ini tidak memengaruhi enumerasi.
HMAC dapat mengautentikasi integritas data yang dibuat aplikasi jika kuncinya rahasia dan hash_equals() memeriksa tanda tangan sebelum deserialisasi. Tolak tanda tangan yang salah sebelum parsing. HMAC tidak mengenkripsi dan tidak mencegah pemutaran ulang; tambahkan masa berlaku atau nonce bila perlu. Jangan menandatangani data serialisasi pengguna sembarang agar tampak tepercaya.
Ketiganya memiliki risiko umum memulihkan objek dari data serialisasi, tetapi format, hook, aturan resolusi kelas, dan mitigasinya berbeda. Nilai setiap runtime dan kelas yang tersedia secara terpisah; jangan menganggap rantai gadget suatu platform berlaku di platform lain.
Referensi
- Manual PHP — unserialize()
- Manual PHP — magic methods
- Manual PHP — decoding JSON
- Manual PHP — __PHP_Incomplete_Class
- OWASP — injeksi objek PHP
- CWE-502 — deserialisasi data tak tepercaya
- Apakah Python pickle aman untuk data tak tepercaya?
- Apakah Java ObjectInputStream aman untuk data tak tepercaya?