Fix: Prevent object injection via unserialize on LogViewer encrypted URL params - #1716
Open
pandigresik wants to merge 1 commit into
Open
Fix: Prevent object injection via unserialize on LogViewer encrypted URL params#1716pandigresik wants to merge 1 commit into
pandigresik wants to merge 1 commit into
Conversation
Contributor
|
🔄 AI PR Review sedang antri di server...
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request: fix: Prevent object injection via unserialize on LogViewer encrypted URL params
Description
Memperbaiki kerentanan CWE-502 (Deserialization of Untrusted Data) pada
LogViewerController. Empat pemanggilanCrypt::decrypt()yang memproses parameter URLf,l,dl,clean,deldari request user memakai mode defaultunserialize = true, sehingga penyerang yang memilikiAPP_KEYdapat mengirim serialized object berbahaya yang langsung di-unserialize(). Semua pemanggilan diganti keCrypt::decryptString()(tanpa unserialize) karena nilai yang diharapkan adalah string path, sekaligus menambahkan test regresi.Changes made:
app/Http/Controllers/LogViewerController.php— mengganti 4 pemanggilanCrypt::decrypt(...)pada input user menjadiCrypt::decryptString(...)(baris 84, 88, 146, dan 181 —pathFromInputuntuk flow download/clean/delete).resources/views/vendor/laravel-log-viewer/log.blade.php— mengganti 5 pemanggilanCrypt::encrypt(...)menjadiCrypt::encryptString(...)agar proses round-trip tetap konsisten dengandecryptString(menghindari double-serialization).tests/Feature/LogViewerControllerTest.php— test baru yang mengirim payload serialized object gadget (seolah-olah penyerang memilikiAPP_KEY) ke routesetting.info-sistemdan memastikan__wakeup()tidak terpanggil (object injection tidak terjadi).Reason for change:
Crypt::decrypt()secara default menjalankanunserialize()pada isi ciphertext. Karena payload berasal dari request user, penyerang yang memilikiAPP_KEYbisa menyisipkan serialized object berbahaya → POP-chain → potensi RCE.decryptString, nilai didekripsi sebagai string murni tanpa unserialize, sehingga seluruh attack vector object injection ditutup.encryptStringagar nilai yang dikirim adalah string path mentah, bukanserialize(path).Impact of change:
✅ Security: Menghilangkan
unserialize()pada data tidak tepercaya — menutup CWE-502 / OWASP A08:2021.✅ Attack surface reduction: Nilai terdekripsi kini hanya bisa berupa string path, memperkecil kemungkinan manipulasi tipe data.
✅ Regression guard: Test otomatis memastikan refactor tidak memperkenalkan kembali unserialize pada input user di masa depan.
Related Issue
Steps to Reproduce
Before fix (problem):
APP_KEY(mis. terbaca dari.env, repo, atau known-key).Crypt::encryptString(serialize(new Gadget)).setting/info-sistem?f=<payload>.Crypt::decrypt($f)→unserialize($f)→ object terinstansiasi (__wakeup/__destructterpanggil).After fix (solution):
Crypt::decryptString($f)→ nilai didekripsi sebagai string mentah tanpa unserialize.__wakeup()gadget tidak pernah terpanggil — object injection tertutup.Testing on related features:
?l=...) ✅ Working?dl=...) ✅ Working?clean=...) ✅ Working?del=...) ✅ Working?delall=true) ✅ WorkingChecklist
Technical Details
Technical Explanation
Akar masalah:
Illuminate\Encryption\Encrypter::decrypt($payload, $unserialize = true)mengembalikanunserialize($decrypted)secara default. Semua panggilan diLogViewerControllermemakai default ini pada input user, sehingga isi ciphertext — yang bisa berisi serialized object buatan penyerang — di-unserialize.decryptString()memanggildecrypt($payload, false)sehingga mengembalikan string mentah tanpa unserialize. Karena nilai yang dipakai seharusnya adalah path (string), ini tidak mengubah perilaku fungsional log viewer.Konsistensi view: Semula view memakai
Crypt::encrypt($value)=encrypt(serialize($value))(double-serialize). DigantiCrypt::encryptString($value)=encrypt($value, false)agar payload yang dikirim adalah string path mentah, yang konsisten dengandecryptString()di sisi server.Test regresi (
LogViewerControllerTest.php):ObjectInjectionGadgetmemiliki__wakeup()yang menandaistatic::$wokenUp = true.Crypt::encryptString(serialize(new ObjectInjectionGadget))— meniru penyerang yang memilikiAPP_KEY.decryptString,__wakeup()tidak terpanggil → test PASS. Jika dikembalikan keCrypt::decrypt(unserialize=true), test FAIL → terbukti menangkap regresi (red/green terverifikasi).Configuration changes
Tidak ada perubahan konfigurasi. (Catatan: perubahan
DB_PASSWORDdi.env.testinghanya untuk environment testing lokal dan bukan bagian dari PR ini.)Dependencies added
No new dependencies
Testing
Manual Testing
/setting/info-sistem)l)dl)clean)del)delall)Automated Testing
tests/Feature/LogViewerControllerTest.php— "user-supplied log params are decrypted without unserialization"Browser Compatibility (if applicable)
N/A — tidak ada perubahan visual UI
Screenshots / Video
Breaking Changes
Tidak ada perubahan perilaku fungsional. Satu catatan: URL bookmark/link lama yang dibuat dengan
Crypt::encrypt()(double-serialized) tidak lagi ter-resolve dengan benar setelahdecryptString(). Secara fungsional, link tersebut berasal dari halaman itu sendiri dan selalu di-render ulang denganencryptString, sehingga normalnya tidak bermasalah.Migration Guide
Not required
References
Additional notes:
Crypt::decrypt) test gagal (gadget__wakeupterpanggil), dengan kode baru (decryptString) test lulus.APP_KEYadalah secret yang tidak boleh bocor; fix ini mengurangi dampak bila key ter-expose (defense-in-depth), bukan pengganti untuk melindungiAPP_KEY.