Skip to content

fix: cegah false positive polyglot scan pada PNG/gambar biner - #3

Merged
andifahruddinakas merged 1 commit into
masterfrom
fix/png-upload-false-positive
Sep 12, 2026
Merged

andifahruddinakas merged 1 commit into
masterfrom
fix/png-upload-false-positive

Conversation

@andifahruddinakas

Copy link
Copy Markdown
Member

Deskripsi

Memperbaiki dua bug yang dilaporkan pada OpenSID/premium#6987 (review komentar https://github.com/OpenSID/premium/pull/6987#issuecomment-5630635765): unggahan PNG ditolak dengan "Wrong extension" secara tidak konsisten, dan pesan galat batas ukuran menampilkan placeholder mentah %d.

1. False positive pada polyglot scan (root cause "PNG gak bisa upload")

FileContentValidator::POLYGLOT_PATTERN memindai seluruh isi berkas untuk menangkap PHP/HTML yang disisipkan. Dua alternatifnya — <? polos dan <?= — hanya 2-3 byte literal, yang ternyata cocok secara kebetulan pada data biner terkompresi milik gambar raster asli (PNG/JPEG/WebP), terutama gambar berentropi tinggi seperti foto atau hasil AI image generator.

Diverifikasi dengan 3000 PNG bernoise nyata (dibuat via GD, bukan payload buatan): pola lama menolak ~13% di antaranya sebagai false positive; setelah perbaikan, 0/3000.

Perbaikan: kedua alternatif sekarang mensyaratkan rentetan byte yang tampak seperti kode sungguhan tepat setelah penanda (MIN_CODE_RUN_AFTER_SHORT_TAG = 10 byte printable/whitespace berturut-turut) — payload PHP asli selalu punya ini, data biner acak nyaris tidak pernah.

Seluruh test keamanan yang ada tetap lolos (webshell disamarkan sebagai .jpg, HTML smuggling, bare short tag yang disisipkan ke gambar asli, dll).

2. Pesan galat max_size_reached menampilkan %d mentah

UploadController memanggil trans('filemanager::filemanager.max_size_reached') tanpa parameter, padahal string lang-nya memakai placeholder gaya sprintf (%d) yang tidak pernah disubstitusi oleh trans() Laravel — sehingga pengguna melihat teks literal "...maximale size of %d MB." alih-alih angka yang sebenarnya.

Perbaikan: string lang memakai placeholder :size ala Laravel, dan controller mengirim nilai max_upload_size yang terkonfigurasi lewat FilemanagerConfig::maxUploadSizeMb() (baru).

Test

  • Menambah accepts_real_noisy_pngs_without_false_positives (20 iterasi PNG bernoise nyata) di FileContentValidatorTest.
  • Menambah reports_the_actual_size_limit_when_a_file_is_too_large di UploadRouteTest.
  • vendor/bin/phpunit: 91 tests, 210 assertions, OK.
  • vendor/bin/pint --test: passed.
  • vendor/bin/phpstan analyse: No errors.

Checklist

  • Menjalankan test suite lengkap
  • Menjalankan Pint & PHPStan

Alternatif <?= dan <? polos di FileContentValidator::POLYGLOT_PATTERN
hanya 2-3 byte literal, cocok secara kebetulan pada data terkompresi
gambar raster asli (terutama PNG/foto berentropi tinggi) sehingga
unggahan gambar sah ditolak sebagai "wrong extension"
(OpenSID/premium#6987 - komentar review).

Kedua alternatif sekarang mensyaratkan rentetan byte mirip kode
sungguhan tepat setelah penanda, terverifikasi 0 false positive dari
3000 PNG bernoise vs ~13% sebelumnya, tanpa melemahkan deteksi payload
PHP/HTML yang sungguhan disisipkan.

Turut memperbaiki pesan galat max_size_reached yang memakai placeholder
gaya sprintf (%d) yang tidak pernah disubstitusi trans(), sehingga
pengguna melihat teks mentah alih-alih ukuran batas sebenarnya.
@andifahruddinakas
andifahruddinakas merged commit 83deb8a into master Sep 12, 2026
7 checks passed
@andifahruddinakas
andifahruddinakas deleted the fix/png-upload-false-positive branch September 12, 2026 05:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant