PHP2Shell: come limitare i danni di una falla PHP con disable_functions e blocco dei file in uploads

Se hai letto la nostra guida su PHP2Shell, sai già che la prima cosa da fare è aggiornare PHP alle versioni corrette. Questo articolo parte da lì, perché la patch chiude la falla ma non dice nulla su cosa succede il giorno in cui ne esce un’altra. E succederà.

L’idea è semplice: se qualcuno riesce a far girare del codice sul tuo server, deve trovare poco con cui lavorare. Vediamo come si ottiene su un VPS Ubuntu con OpenLiteSpeed.

Cosa possono fare queste protezioni e cosa no

Una precisazione onesta prima di partire. PHP2Shell riguarda la gestione della memoria da parte di PHP. Un attacco che sfrutta un errore di memoria può in alcuni casi aggirare restrizioni come disable_functions, perché lavora a un livello più basso. Le misure che trovi qui non sostituiscono quindi l’aggiornamento.

Pubblicità

Servono soprattutto contro lo scenario più comune su WordPress: un plugin vulnerabile permette di caricare un file PHP malevolo (una webshell) e poi di eseguirlo. In quel caso queste protezioni fanno una differenza concreta.

1. Bloccare le funzioni pericolose con disable_functions

La direttiva disable_functions del php.ini impedisce a PHP di usare funzioni che lanciano comandi sul sistema. WordPress nel funzionamento normale non ne ha bisogno, mentre una webshell sì.

Per trovare il file giusto per la tua versione di lsphp:

/usr/local/lsws/lsphp83/bin/php --ini

Di solito si trova in /usr/local/lsws/lsphp83/etc/php/8.3/litespeed/php.ini. Apri il file e cerca la riga disable_functions:

disable_functions = exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec,dl,posix_kill,posix_mkfifo,posix_setsid,posix_setuid,show_source,proc_get_status,proc_terminate

Se usi aaPanel puoi fare la stessa cosa dal pannello, nelle impostazioni della versione di PHP, alla voce funzioni disabilitate.

Poi riavvia e ripeti l’operazione per ogni versione di PHP che usi:

sudo systemctl restart lsws

Per verificare che funzioni, crea un file temporaneo nella cartella del sito, con un nome che non sia indovinabile:

echo '<?php var_dump(function_exists("shell_exec"));' | sudo tee /var/www/miosito/prova-8f3k2.php
curl https://www.miosito.it/prova-8f3k2.php
sudo rm /var/www/miosito/prova-8f3k2.php

Se vedi bool(false) la funzione è disattivata. Non dimenticare di cancellare il file.

Qualche plugin di backup o di ottimizzazione immagini usa exec e smetterà di funzionare. Dopo la modifica fai un giro del sito e prova le funzioni principali. Se qualcosa si rompe, togli dalla lista solo la funzione necessaria, non tutto l’elenco.

2. Impedire l’esecuzione di PHP nella cartella uploads

Nella cartella wp-content/uploads devono stare immagini e documenti. Un file PHP lì dentro non ha alcun motivo di esistere, e vietarne l’esecuzione rende inutile gran parte delle webshell caricate tramite plugin vulnerabili.

Il metodo più solido su OpenLiteSpeed è una regola di rewrite a livello di Virtual Host. Dal pannello WebAdmin (porta 7080) vai nel tuo Virtual Host, sezione Rewrite, abilita il rewrite e aggiungi:

RewriteRule ^wp-content/uploads/.*\.(php|phtml|phar|php[0-9])$ - [F,L]

In alternativa puoi creare il file wp-content/uploads/.htaccess con questo contenuto:

RewriteEngine On
RewriteRule \.(php|phtml|phar|php[0-9])$ - [F,L]

Dopo la modifica fai un riavvio graceful:

sudo /usr/local/lsws/bin/lswsctrl restart

Poi controlla che la regola funzioni davvero:

echo '<?php echo "eseguito";' | sudo tee /var/www/miosito/wp-content/uploads/prova.php
curl -I https://www.miosito.it/wp-content/uploads/prova.php
sudo rm /var/www/miosito/wp-content/uploads/prova.php

Devi ottenere un errore 403. Se vedi 200, la regola non è attiva.

Se sul server hai anche Nginx, l’equivalente è:

location ~* ^/wp-content/uploads/.*\.(php|phtml|phar|php[0-9])$ { deny all; }

Lo stesso ragionamento vale per ogni altra cartella in cui PHP può scrivere, come le cache di alcuni plugin o le cartelle dei backup.

3. Permessi e proprietario dei file

Se l’utente con cui gira PHP è anche il proprietario di tutti i file del sito, una webshell può modificare qualsiasi file di WordPress, plugin compresi. Conviene separare i ruoli: il codice appartiene a un utente amministrativo e PHP può scrivere solo dove serve davvero.

Sostituisci UTENTE_ADMIN con il tuo utente e UTENTE_PHP con quello con cui gira PHP:

cd /var/www/miosito
sudo chown -R UTENTE_ADMIN:UTENTE_PHP .
sudo find . -type d -exec chmod 755 {} \;
sudo find . -type f -exec chmod 644 {} \;
sudo chmod 640 wp-config.php
sudo chown -R UTENTE_PHP:UTENTE_PHP wp-content/uploads

Se alcuni plugin hanno bisogno di scrivere altrove, come nelle cartelle di cache, assegna a quelle cartelle lo stesso proprietario di uploads.

C’è un effetto collaterale da conoscere: dalla dashboard non potrai più installare o aggiornare plugin e temi. Dovrai farlo da terminale con WP-CLI, usando l’utente amministrativo. In cambio, un attaccante non può più modificare i file del sito. Se non l’hai già fatto, aggiungi anche DISALLOW_FILE_EDIT come spiegato nella guida ai comandi per wp-config.php.

4. Un utente di sistema per ogni sito

Se sul VPS ospiti più siti, ognuno dovrebbe avere il proprio utente e PHP dovrebbe girare con quell’utente. Così, se un sito viene compromesso, l’attaccante non può leggere né modificare gli altri. OpenLiteSpeed permette di farlo con la modalità UID dell’applicazione esterna lsphp, mentre aaPanel e CyberPanel lo gestiscono in automatico quando crei un sito.

Se nel tuo VPS tutti i siti girano con lo stesso utente, vale la pena sistemarlo. Un sito dimenticato e mai aggiornato diventa altrimenti la porta d’ingresso per tutti gli altri.

5. Accorgersi in fretta di un file sospetto

Anche con il blocco attivo, un file PHP in uploads resta un segnale di allarme, perché vuol dire che qualcuno è riuscito a caricarlo. Un controllo ogni dieci minuti scrive nel log di sistema i nuovi file sospetti. Aggiungilo con sudo crontab -e:

*/10 * * * * find /var/www -path "*/wp-content/uploads/*" -type f \( -name "*.php" -o -name "*.phtml" -o -name "*.phar" \) -mmin -10 2>/dev/null | logger -t php-uploads

Per leggere i risultati:

sudo journalctl -t php-uploads

Se compare qualcosa, non cancellare e basta: controlla da dove arriva il file e segui i passaggi della nostra guida su come verificare da terminale se il server è stato infettato.

L’aggiornamento di PHP resta la priorità, e per farlo senza rischi trovi la procedura con snapshot e rollback nella guida all’aggiornamento di lsphp su OpenLiteSpeed. Subito dopo, mezz’ora di lavoro sulle quattro protezioni qui sopra riduce parecchio ciò che un attaccante può fare, anche quando la falla è ancora aperta.

Leggi anche: PHP, aggiornamento di sicurezza critico: cosa fare su aaPanel e sul proprio server

Altro per te

PHP
PHP Compatibility Checker
Controlla il tuo plugin WordPress prima di aggiornare PHP Verifica la compatibilità con PHP 8.0–8.5 Scopri eventuali problemi nel codice PHP Analizza il tuo plugin WordPress online Preparati a PHP 8.5
Verifica ora →
PDF Strumenti PDF gratis Nel browser, senza upload Apri gli strumenti

🔒

Contenuto riservato

Per scaricare questo file devi prima registrarti oppure accedere con il tuo account.

XWhatsAppTelegram