PHP2Shell: come verificare e correggere le falle RCE di PHP
Il 21 ottobre 2026 il progetto PHP ha rilasciato le versioni 8.5.12, 8.4.27, 8.3.36 e 8.2.35 per correggere due falle in PHP stesso, soprannominate PHP2Shell. Entrambe permettono a una richiesta di chi non ha effettuato l'accesso di eseguire codice come worker PHP. Il bug è nel runtime, non in WordPress, Drupal o Joomla, quindi aggiornare il CMS o i suoi plugin non lo chiude. Questa guida mostra chi è colpito, come verificare un server con un solo comando, cosa fare oggi se non puoi ancora aggiornare e come aggiornare in sicurezza.
Quali sono le due falle
- CVE-2026-109618, corruzione per memoria esaurita - quando un'allocazione di memoria fallisce, PHP può interrompere una richiesta mentre i suoi dati interni sono pronti solo a metà, e la pulizia che segue si fida di quei dati corrotti. Una richiesta multipart costruita ad arte può innescarla anche entro i limiti di dimensione che hai configurato.
- CVE-2026-109619, stato globale obsoleto - lo stato che appartiene a una richiesta può sopravvivere alla memoria su cui si appoggia. La richiesta successiva servita dallo stesso worker può usare quella memoria liberata prima che venga reimpostata (un use-after-free). Il percorso confermato passa per la funzione session upload progress e per gli errori fatali.
Entrambe hanno un punteggio di 9.2 (critico) in CVSS 4.0. L'annuncio di PHP dice che durante la ricerca è stato costruito un exploit funzionante e che il rischio è più alto per Apache con mod_php, dove l'attacco viene eseguito prima di qualsiasi codice applicativo. In pochi giorni sono comparsi diversi exploit proof-of-concept pubblici; Rapid7 riferisce che ognuno funziona solo per una combinazione di sistema operativo, versione di PHP e web server, e ha osservato tentativi di sfruttamento. Trattala come una patch d'emergenza.
Chi è colpito
Ogni installazione PHP che serve richieste web: PHP-FPM, Apache con mod_php, php-cgi, FrankenPHP e LiteSpeed. Questo copre quasi ogni server con WordPress, WooCommerce, Drupal, Joomla, Magento, Laravel e Nextcloud.
| Ramo PHP | Colpite | Prima versione corretta |
|---|---|---|
| 8.5 | 8.5.0 - 8.5.11 | 8.5.12 |
| 8.4 | 8.4.0 - 8.4.26 | 8.4.27 |
| 8.3 | 8.3.0 - 8.3.35 | 8.3.36 |
| 8.2 | 8.2.0 - 8.2.34 | 8.2.35 |
| 7.4, 8.0, 8.1 | tutte | nessun rilascio su php.net; backport nei sorgenti, pacchetti della distribuzione o di un fornitore LTS |
| 7.3 e precedenti | tutte | nessuna correzione |
Le distribuzioni spesso mantengono il vecchio numero di versione e riportano la correzione con un backport (per esempio un pacchetto Debian o Ubuntu che indica ancora 8.2.x), quindi con PHP da pacchetti controlla il pacchetto nel security tracker della tua distribuzione, non solo il numero.
Verificare un server con un solo comando
Salva questo come php2shell-check.php ed eseguilo con lo stesso PHP che serve il tuo sito. Stampa la versione, se quella versione è precedente alla correzione e le due impostazioni che le misure tampone qui sotto modificano.
<?php
// PHP2Shell check: is this PHP build older than the October 21, 2026 fixes?
$fixed = ['8.5' => '8.5.12', '8.4' => '8.4.27', '8.3' => '8.3.36', '8.2' => '8.2.35'];
$branch = PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION;
echo "PHP " . PHP_VERSION . " (" . PHP_SAPI . ")\n";
if (!isset($fixed[$branch])) {
echo "Branch $branch gets no php.net release: check your distro or LTS vendor, or upgrade to 8.4.\n";
} elseif (version_compare(PHP_VERSION, $fixed[$branch], '<')) {
echo "VULNERABLE: upgrade to {$fixed[$branch]} or later (or a distro build with the backport).\n";
} else {
echo "Patched upstream version ({$fixed[$branch]}+).\n";
}
echo "session.upload_progress.enabled = " . (ini_get('session.upload_progress.enabled') ? 'On' : 'Off') . "\n";
echo "post_max_size = " . ini_get('post_max_size') . ", memory_limit = " . ini_get('memory_limit') . "\n";
php php2shell-check.php
Output verificato il 2026-10-24 nelle immagini Docker ufficiali php:
PHP 8.3.30 (cli)
VULNERABLE: upgrade to 8.3.36 or later (or a distro build with the backport).
session.upload_progress.enabled = On
post_max_size = 8M, memory_limit = 128M
PHP 8.4.27 (cli)
Patched upstream version (8.4.27+).
PHP 7.2.34 (cli)
Branch 7.2 gets no php.net release: check your distro or LTS vendor, or upgrade to 8.4.
Il php da riga di comando può essere una build diversa da quella dietro il sito. Per verificare il lato web, esegui php-fpm -v (o php-fpm8.3 -v su Debian e Ubuntu), oppure metti lo script nella web root per una sola richiesta e cancellalo subito dopo.
Se oggi non puoi aggiornare: misure tampone
Il team di PHP è chiaro: non esiste una mitigazione completa e aggiornare è l'unica scelta sicura. Queste impostazioni restringono l'attacco mentre pianifichi l'aggiornamento. Impostale dove l'applicazione non può sovrascriverle - in php.ini o nel pool FPM con php_admin_value -, perché ini_set() e .user.ini si applicano troppo tardi. Poi riavvia ogni worker.
; FPM pool, e.g. /etc/php/8.3/fpm/pool.d/zz-php2shell.conf (the [www] section of your pool)
[www]
php_admin_value[session.upload_progress.enabled] = 0
php_admin_value[post_max_size] = 32M
php_admin_value[upload_max_filesize] = 30M
php-fpm8.3 -t && systemctl restart php8.3-fpm
Abbiamo verificato questo file di pool con php-fpm -t su PHP 8.4 (configuration test successful). Cosa fa ogni riga:
session.upload_progress.enabled = 0blocca il percorso confermato di CVE-2026-109619, non ogni variante. Disattivalo a meno che una barra di avanzamento dell'upload non ne dipenda.post_max_sizea 8M senza upload, o 32M se il sito accetta file, conupload_max_filesizeal di sotto, come raccomanda il team di PHP. Limita anche la dimensione delle richieste in nginx (client_max_body_size 32m;) o Apache (LimitRequestBody).- Solo su PHP 8.5, aggiungi
fatal_error_backtraces = 0. - PHP suggerisce anche
memory_limit = -1impostato dall'amministratore, così che il limite di memoria stesso non possa essere usato per innescare CVE-2026-109618. Fallo solo con un limite di memoria del container o del cgroup attorno a PHP, altrimenti una sola richiesta malevola può prendersi tutta la RAM del server. Non usareRLIMIT_ASoRLIMIT_DATAper questo: possono innescare la falla.
Nascondere gli errori (display_errors, error_reporting, @) non aiuta, e un log degli errori vuoto non dimostra che un server non sia stato attaccato.
Come aggiornare
- PHP da pacchetti (Debian, Ubuntu, RHEL, AlmaLinux). Installa l'aggiornamento di sicurezza (
apt update && apt upgrade, odnf upgrade 'php*'), poi riavvia PHP-FPM o Apache, perché i worker in esecuzione mantengono il vecchio codice. Verifica che il changelog del pacchetto citi CVE-2026-109618. - Immagini Docker. Ricostruisci su un tag corretto (
php:8.4-fpmora corrisponde a 8.4.27) condocker compose build --pull, poi ricrea i container. Un container in esecuzione mantiene il vecchio PHP finché non viene sostituito. - PHP 7.4 - 8.1. Usa il pacchetto con backport del tuo fornitore o passa a 8.4. PHP 7.3 e precedenti non riceveranno mai una correzione: metti il sito dietro una allow-list o una VPN finché non è migrato.
- Dopo l'aggiornamento, esegui di nuovo lo script di verifica e controlla il log del web server alla ricerca di richieste POST multipart insolite e crash dei worker PHP dal 21 ottobre.
Se ti serve una mano, l'amministrazione gestita dei server copre patch come questa, e la nostra guida al server cloud per WordPress mostra una configurazione PHP-FPM che tiene queste impostazioni nel pool. Prima di aggiornare un sito in produzione, fai uno snapshot: backup e ripristino di una VM spiega come.
Cosa abbiamo fatto
La stessa settimana abbiamo controllato ogni servizio DCXV che usa PHP e applicato le misure di questa guida. I server dei clienti sono gestiti dai loro proprietari: se usi PHP su un server cloud o dedicato DCXV, esegui oggi stesso la verifica qui sopra. Un nuovo server cloud riceve i pacchetti aggiornati al primo apt upgrade.
Fonti (verificate il 2026-10-24): l'annuncio dei rilasci di sicurezza di PHP 8.x del 21 ottobre 2026, gli advisory PHP GHSA-w8hw-w9fx-j79w e GHSA-6wmf-4rv5-p3rp e l'analisi di Rapid7.
