Pada 21 Oktober 2026, pasukan PHP menerbitkan pembaikan kecemasan bagi dua kelemahan kritikal yang dikenali sebagai PHP2Shell: CVE-2026-109618 dan CVE-2026-109619. Kedua-duanya boleh membuka laluan pelaksanaan kod jauh tanpa pengesahan dalam keadaan yang terjejas. Pentadbir perlu menyemak enjin PHP yang benar-benar melayan laman, bukan sekadar versi CMS atau arahan PHP dalam terminal.
CVE-2026-109618 melibatkan keadaan memori tidak sah selepas kegagalan peruntukan memori. CVE-2026-109619 pula melibatkan keadaan global yang masih merujuk memori permintaan terdahulu. Permintaan berikutnya pada worker yang sama boleh mengakses keadaan lapuk tersebut. Laluan eksploit bergantung pada SAPI, konfigurasi, sambungan PHP dan aplikasi; jangan menganggap semua persekitaran mempunyai rantaian serangan yang sama.
Untuk OpenLiteSpeed/LSAPI, jangan anggap penggunaan LiteSpeed memberikan imuniti. Advisori PHP menerangkan keadaan berpotensi terjejas, termasuk laluan yang bergantung pada aplikasi atau konfigurasi. Tiada respons HTTP biasa yang boleh membuktikan semua laluan eksploit sudah ditutup.
Sumber teknikal: advisori OOM corruption dan advisori stale global state.
| Cabang PHP | Versi pembaikan minimum upstream |
|---|---|
| 8.2 | 8.2.35 |
| 8.3 | 8.3.36 |
| 8.4 | 8.4.27 |
| 8.5 | 8.5.12 |
Kemas kini kepada versi yang mengandungi pembaikan dan mulakan semula semua worker PHP. Untuk pakej distro yang menggunakan backport, semak notis keselamatan dan changelog pembekal; nombor versi upstream sahaja tidak mencukupi. Cabang lama memerlukan penilaian sokongan vendor atau migrasi kepada cabang disokong.
WAF ialah pertahanan tambahan. Patch PHP ialah pembaikan utama. Rujuk pengumuman keselamatan rasmi PHP sebelum membuat keputusan pemulihan.
Simpan skrip berikut sebagai check-php2shell.php di luar webroot. Jalankan dengan setiap binari PHP yang digunakan oleh laman. Skrip ini hanya membandingkan versi upstream; ia tidak menghantar payload eksploit atau membuktikan backport vendor.
<?php
if (PHP_SAPI !== 'cli') { http_response_code(404); exit; }
$fixed = ['8.2' => '8.2.35', '8.3' => '8.3.36',
'8.4' => '8.4.27', '8.5' => '8.5.12'];
$branch = PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION;
$minimum = $fixed[$branch] ?? null;
$status = $minimum === null ? 'SEMAK SOKONGAN / ADVISORI VENDOR' :
(version_compare(PHP_VERSION, $minimum, '>=') ?
'VERSI UPSTREAM MEMENUHI MINIMUM' : 'PERLU PATCH ATAU BUKTI BACKPORT');
echo PHP_BINARY, " | ", PHP_VERSION, " | ", $status, PHP_EOL;
echo 'upload_progress=', ini_get('session.upload_progress.enabled'), PHP_EOL;
php check-php2shell.php
# Contoh OpenLiteSpeed: guna binari yang dipetakan kepada vhost.
/usr/local/lsws/lsphp82/bin/php check-php2shell.php
# Lihat fail INI bagi binari tersebut.
/usr/local/lsws/lsphp82/bin/php --iniCLI dan web worker boleh menggunakan konfigurasi berlainan. Semak pemetaan handler/vhost, pool serta worker yang masih hidup selepas kemas kini. Jangan menerbitkan phpinfo() secara terbuka untuk tujuan semakan.
Contoh di bawah ialah polisi pertahanan tambahan tempatan, bukan signature yang meliputi semua eksploit PHP2Shell. Ia memerlukan ModSecurity aktif dengan pemeriksaan badan permintaan sebelum trafik sampai kepada PHP. Pastikan ID tidak bertindih, sahkan sintaks dan uji dalam staging dahulu.
# PHP2Shell defence in depth, 2026-10-22. NOT a replacement for patched PHP.
# CVE-2026-109618 / CVE-2026-109619. Local policy, not an exploit signature.
# Keep ordinary multipart uploads working. No payload contents in logdata.
SecRule REQUEST_HEADERS:Content-Type "@rx (?i)^multipart/form-data(?:s*;|$)" "id:1006200,phase:1,pass,nolog,setvar:tx.php2shell_multipart=1"
# A usable declared size is required for multipart uploads on this deployment.
SecRule TX:php2shell_multipart "@eq 1" "id:1006201,phase:1,deny,status:403,log,msg:'PHP2Shell guard: multipart without declared size',tag:'php2shell-guard',severity:'CRITICAL',chain"
SecRule &REQUEST_HEADERS:Content-Length "@eq 0"
# Disable the default PHP session upload-progress input at the edge.
# If session.upload_progress.name is customized, add that name here too.
SecRule TX:php2shell_multipart "@eq 1" "id:1006202,phase:2,deny,status:403,log,msg:'PHP2Shell guard: session upload progress field',tag:'php2shell-guard',severity:'CRITICAL',chain"
SecRule ARGS_NAMES "@rx ^PHP_SESSION_UPLOAD_PROGRESS(?:[|$)" "t:none"
# Reject bodies the WAF could not parse; do not forward uninspected multipart.
SecRule TX:php2shell_multipart "@eq 1" "id:1006203,phase:2,deny,status:403,log,msg:'PHP2Shell guard: multipart parser error',tag:'php2shell-guard',severity:'CRITICAL',chain"
SecRule REQBODY_ERROR "!@eq 0"
# Bound parsed form fields. Existing upload byte limits remain unchanged.
SecRule TX:php2shell_multipart "@eq 1" "id:1006204,phase:2,deny,status:403,log,msg:'PHP2Shell guard: excessive multipart fields',tag:'php2shell-guard',severity:'CRITICAL',chain"
SecRule &ARGS "@gt 1000"
# Reject chunked multipart where the connector preserves Transfer-Encoding.
SecRule TX:php2shell_multipart "@eq 1" "id:1006205,phase:1,deny,status:403,log,msg:'PHP2Shell guard: chunked multipart upload',tag:'php2shell-guard',severity:'CRITICAL',chain"
SecRule REQUEST_HEADERS:Transfer-Encoding "@rx (?i)(?:^|[,s])chunked(?:$|[,s])"
Peraturan ini memerlukan SecRuleEngine On dan SecRequestBodyAccess On. Arahan log merekodkan padanan dalam log ralat WAF/server; lokasi fail bergantung pada connector dan konfigurasi. Jika menggunakan audit log, sediakan akses dan putaran log yang sesuai serta elakkan menyimpan kandungan borang sensitif.
Kesan keserasian: muat naik multipart tanpa Content-Length (seperti dilihat connector), chunked multipart yang headernya dikekalkan, borang melebihi 1,000 medan dan ciri session upload progress lalai akan disekat. Nama progress yang telah diubah mesti ditambah kepada polisi. Connector boleh menyahkod chunked dan membina Content-Length sebelum WAF; uji tingkah laku frontend sebenar dan kuatkuasakan had saiz decoded. Had ini tidak mengesan setiap cara kehabisan memori, semua header multipart atau semua varian stale state. Uji borang, API dan muat naik sebenar sebelum menggunakan polisi secara meluas.
Gunakan hanya domain sendiri dan endpoint ujian yang tidak mengubah data. Permintaan berikut menghantar satu medan kecil; ia menguji peraturan 1006202, bukan cuba mendapatkan shell atau menyebabkan kehabisan memori.
curl --max-time 15 -sS -o /dev/null -w 'HTTP %{http_code}n'
-F 'PHP_SESSION_UPLOAD_PROGRESS=php2shell-safe-check'
'https://example.com/waf-test'
# Kawalan: medan biasa pada endpoint ujian yang sama.
curl --max-time 15 -sS -o /dev/null -w 'HTTP %{http_code}n'
-F 'ordinary_field=php2shell-safe-check'
'https://example.com/waf-test'
# Contoh lokasi log OpenLiteSpeed; laraskan ikut pemasangan.
grep '1006202' /usr/local/lsws/logs/error.log | tail -n 5Jangkaan bagi probe pertama ialah HTTP 403 dengan rekod ID 1006202 pada masa dan URI yang sepadan. HTTP 403 tanpa log padanan mungkin datang daripada aplikasi atau peraturan lain. Probe kawalan patut sampai ke endpoint; kodnya mengikut aplikasi. Untuk cluster, uji setiap backend sambil mengekalkan hostname dan SNI, kemudian semak laluan awam.
Lulus ujian ini hanya membuktikan polisi tertentu telah dimuatkan dan menyekat input ujian. Ia tidak membuktikan PHP sudah ditampal, tidak mengesahkan tiada kompromi terdahulu dan tidak menguji semua laluan CVE.
Utamakan inventori semua runtime dan pakej, pemasangan patch yang sesuai serta penggantian worker lama. Selepas itu, semak fungsi laman, log ralat dan aliran muat naik. Rekod bukti versi aktif dan keputusan ujian setiap node supaya satu server lama tidak tersembunyi di belakang load balancer.
Semakan sumber: 22 Oktober 2026. Artikel teknikal disediakan dengan bantuan AI berdasarkan advisori rasmi; contoh kod pemeriksaan dan polisi WAF ialah contoh defensif tempatan.