In breve: CGI (Common Gateway Interface) è una vecchia interfaccia in cui il server web avvia un nuovo programma per ogni richiesta, con PHP il programma php-cgi. FastCGI ne è l'evoluzione: i processi PHP girano in modo permanente e accettano molte richieste tramite un socket. PHP-FPM è la più importante realizzazione FastCGI per PHP. Per la sicurezza contano soprattutto le impostazioni cgi.* e la regola per cui un accesso FastCGI non deve mai essere raggiungibile pubblicamente.
Che cos'è il CGI?
Il CGI è uno dei metodi più antichi con cui i server web generano contenuti dinamici. Il manuale PHP rimanda, per l'impostazione cgi.rfc2616_headers, alla RFC 3875, la specifica del Common Gateway Interface. Anche gli inizi di PHP erano programmi CGI: Rasmus Lerdorf scrisse nel 1994 i primi «Personal Home Page Tools» come binari CGI in C.
Il principio: per ogni richiesta il server web avvia un nuovo processo, passa i dati della richiesta tramite variabili d'ambiente e standard input e legge la risposta dallo standard output. Poi il processo termina. Secondo il manuale PHP, con CGI e CLI PHP rilegge il proprio php.ini a ogni chiamata, con i moduli del server solo all'avvio.
Questo rende il CGI robusto, perché ogni richiesta parte con un processo nuovo. Ma lo rende anche lento: avvio del processo, caricamento della configurazione e inizializzazione delle estensioni costano tempo a ogni richiesta.
Che cos'è FastCGI?
FastCGI risolve il problema delle prestazioni tenendo vivi i processi. Il server web si collega tramite un socket Unix o una porta TCP a un processo in esecuzione e gli invia la richiesta nel protocollo FastCGI. Il processo la elabora e attende la successiva.
| Caratteristica | CGI | FastCGI con php-cgi | FastCGI con PHP-FPM |
|---|---|---|---|
| Processo per richiesta | sì | no | no |
| Nome SAPI | cgi-fcgi |
cgi-fcgi |
fpm-fcgi |
| Pool con utente proprio | no | no | sì |
| Controllo dei processi | server web | modulo del server web, ad es. mod_fcgid | processo master proprio |
.user.ini viene letto |
sì | sì | sì |
Secondo il manuale PHP-FPM è l'implementazione FastCGI primaria di PHP. Integra il protocollo con gestione dei processi, pool, pagine di stato e uno slowlog. I dettagli sono in PHP-FPM spiegato.
Le impostazioni cgi nel php.ini
Per l'esecuzione CGI PHP conosce impostazioni proprie. I valori e le descrizioni seguenti provengono dal manuale PHP:
cgi.force_redirect(predefinito 1,INI_SYSTEM): secondo il manuale necessario per gestire PHP come CGI in sicurezza con la maggior parte dei server web. Disattivarlo solo «a proprio rischio»; con IIS deve essere disattivato.cgi.fix_pathinfo(predefinito 1,INI_SYSTEM): garantisce valori corretti diPATH_INFOePATH_TRANSLATED. Gli script dovrebbero usareSCRIPT_FILENAMEinvece diPATH_TRANSLATED.cgi.discard_path(predefinito 0,INI_SYSTEM): consente di collocare il binario CGI in sicurezza fuori dalla directory web, senza che la protezione di.htaccesspossa essere aggirata.fastcgi.impersonate(predefinito 0,INI_SYSTEM): rilevante solo per IIS su Windows.user_ini.filenameeuser_ini.cache_ttl(predefiniti.user.inie 300 secondi): controllano se e quanto spesso PHP legge i file.user.ini.
Con Nginx serve inoltre un passaggio pulito del percorso dello script. Un modello di base leggibile, senza garanzia per ogni ambiente:
location ~ \.php$ {
try_files $uri =404; # passare a PHP solo file esistenti
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
La riga try_files $uri =404; impedisce che richieste verso percorsi .php inesistenti vengano inoltrate a PHP.
Perché un accesso FastCGI aperto è pericoloso
Il manuale PHP avverte espressamente: chi può aprire una connessione FastCGI verso PHP controlla la configurazione della richiesta, ad esempio auto_prepend_file, e può quindi eseguire codice arbitrario. Il motivo è che i server web possono inviare impostazioni PHP tramite parametri FastCGI come PHP_VALUE e PHP_ADMIN_VALUE.
Ne derivano regole chiare:
- Collegare PHP-FPM o php-cgi in modalità FastCGI solo tramite un socket Unix, se il server web gira sullo stesso host.
- Con TCP impostare
listen.allowed_clientse bloccare la porta nel firewall; indicazioni nell'articolo Firewall per server web. - Mantenere strettamente limitati i permessi del socket con
listen.owner,listen.groupelisten.mode.
Verifichi con ss -lntp | grep -i php se un processo PHP è in ascolto su un indirizzo TCP. Un binding a 0.0.0.0 o a un indirizzo pubblico è un caso di intervento urgente.
CGI, FastCGI e PHP2Shell
PHP2Shell interessa sia php-cgi sia PHP-FPM. Per entrambi vale: aggiornamento a 8.5.12, 8.4.27, 8.3.36 o 8.2.35 oppure a un backport confermato, poi terminare e riavviare tutti i processi PHP in esecuzione. Nei setup FastCGI con php-cgi i processi spesso continuano a girare inosservati, perché nessun servizio proprio li gestisce. Come trovare e sostituire questo retaggio è spiegato in php-cgi: un retaggio con rischi. In Plesk le varianti si chiamano in modo diverso; un aiuto è Plesk: capire i gestori PHP.
Come aiuta concretamente PHP SOS?
- Rilevare i gestori: accertiamo se i Suoi siti web girano tramite CGI, FastCGI con php-cgi o PHP-FPM.
- Chiudere gli accessi: verifichiamo socket, porte e regole del firewall, perché nessun accesso FastCGI sia raggiungibile dall'esterno.
- Aggiornare e ripulire: aggiorniamo PHP e terminiamo tutti i vecchi processi, anche le istanze php-cgi orfane.
- Sostituire: nell'ambito dell'hardening del server sostituiamo i retaggi CGI con PHP-FPM con pool propri.
Domande frequenti
FastCGI è la stessa cosa di PHP-FPM?
No. FastCGI è un protocollo con cui un server web dialoga con un processo applicativo. PHP-FPM è un programma che realizza questo protocollo per PHP e gestisce i processi. Anche php-cgi può parlare FastCGI, ma non offre pool.
Perché il CGI puro è considerato obsoleto?
Con il CGI il server web avvia un nuovo processo per ogni richiesta e PHP legge ogni volta la propria configurazione. Ciò costa tempo e risorse. FastCGI e PHP-FPM tengono i processi sempre pronti e sono perciò molto più efficienti.
Che cos'è un .user.ini?
Un .user.ini è un piccolo file di configurazione in una directory web. Secondo il manuale PHP viene letto solo dalle SAPI CGI e FastCGI, quindi anche da PHP-FPM. Può contenere solo impostazioni con le modalità INI_PERDIR, INI_USER o INI_ALL.
Come capisco se sul mio server gira php-cgi?
Con comandi in sola lettura come ps o pgrep si cercano processi di nome php-cgi e nella configurazione del server web si cercano voci come mod_fcgid, Action o ScriptAlias con php-cgi. Nei pannelli di hosting la modalità si chiama spesso CGI o applicazione FastCGI.