FlawOpen

flawopen.com/Deserialisasi tidak aman/PHP unserialize()

Apakah PHP unserialize() aman untuk input tak tepercaya?

CWE-502: Deserialization of Untrusted DataHalaman referensi
Jawaban singkat

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.

RENTAN
<?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.
DIPERBAIKI
<?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

Apakah allowed_classes => false membuat input tak tepercaya aman?

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.

Apakah HMAC membuat data serialisasi aman?

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.

Apakah risikonya sama dengan Python pickle atau Java ObjectInputStream?

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

Lihat juga Deserialisasi tidak aman: risiko dan mitigasi Python pickle.load(): risiko data tak tepercaya Apakah Ruby YAML.load aman? Versi Psych dan safe_load .NET BinaryFormatter: Risiko dan Migrasi Keamanan ObjectInputStream Java: Cegah Risiko Deserialisasi Newtonsoft.Json TypeNameHandling: konfigurasi aman?