Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
PHP_CVE-2012-1823 — PoC educativo e analisi di CVE-2012-1823, una vulnerabilità di esecuzione remota di codice PHP-CGI. Include ambiente di test basato su Docker, dimostrazione dell'exploit e analisi tecnica dettagliata della causa principale e dei bypass. | Kitploit
Strumenti/GitHubGitHub/cyberharsh/php_cve-2012-1823
Analisi delle VulnerabilitàAnalisi del CodiceExploitSfruttamento di Applicazioni WebPenetration TestingApprendimento e Formazione
GitHubcyberharsh/php_cve-2012-1823

PHP_CVE-2012-1823

PoC educativo e analisi di CVE-2012-1823, una vulnerabilità di esecuzione remota di codice PHP-CGI. Include ambiente di test basato su Docker, dimostrazione dell'exploit e analisi tecnica dettagliata della causa principale e dei bypass.

Vedi Repository
1126 anni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Vulnerabilità di esecuzione remota di codice PHP-CGI (CVE-2012-1823)

Principio

  • Articolo di riferimento: http://eindbazen.net/2012/05/php-cgi-advisory-cve-2012-1823/
  • Versioni interessate: php < 5.3.12 oppure php < 5.4.2

Ambiente di test

Ambiente di compilazione ed esecuzione:

root@kitploit:~
docker-compose build
docker-compose up -d

Dopo l'avvio dell'ambiente, visitando http://your-ip:8080/ si può vedere la scritta "Hello".

Visitando http://your-ip:8080/index.php?-s viene esposto il codice sorgente, a dimostrazione che la vulnerabilità esiste. Inviando il seguente pacchetto, si può vedere che il codice nel Body è stato eseguito:

root@kitploit:~
POST /index.php?-d+allow_url_include%3don+-d+auto_prepend_file%3dphp%3a//input HTTP/1.1
Host: example.com
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 31

<?php echo shell_exec("id"); ?>

Analisi della vulnerabilità

PHP SAPI e modalità di esecuzione

Innanzitutto, introduciamo le modalità di esecuzione di PHP.

Scaricando il codice sorgente di PHP, si può notare che esiste una directory chiamata sapi. Il ruolo di sapi in PHP è simile a quello di un "trasportatore" di messaggi. Ad esempio, il fpm che ho introdotto nell'articolo "Analisi del protocollo Fastcgi && Vulnerabilità di accesso non autorizzato a PHP-FPM && Scrittura di Exp" ha la funzione di ricevere i dati incapsulati dal container web tramite il protocollo fastcgi e di consegnarli all'interprete PHP per l'esecuzione.

Oltre a fpm, la sapi più comune è probabilmente mod_php per Apache, utilizzata per lo scambio di dati tra PHP e Apache.

Anche php-cgi è una sapi. Agli albori del web, il modo di eseguire le applicazioni web era molto semplice: il container web riceveva il pacchetto HTTP, prendeva il file richiesto dall'utente (script cgi) e faceva fork di un processo figlio (l'interprete) per eseguire quel file, quindi otteneva il risultato dell'esecuzione e lo restituiva direttamente all'utente, mentre il processo figlio dell'interprete terminava. La maggior parte delle applicazioni web basate su linguaggi come bash, perl, ecc. venivano eseguite proprio in questo modo; questa modalità di esecuzione è generalmente chiamata cgi. Quando si installa Apache, è presente una directory cgi-bin predefinita, che in origine serviva proprio a contenere questi script cgi.

Ma la modalità cgi ha un difetto fatale: come tutti sanno, la creazione e la pianificazione dei processi comportano un certo costo e il numero di processi non è illimitato. Pertanto, i siti web che girano in modalità cgi di solito non possono accettare un gran numero di richieste contemporaneamente; altrimenti, generando un processo figlio per ogni richiesta, il server potrebbe essere sovraccaricato. Così in seguito è nato fastcgi: il processo fastcgi può rimanere in esecuzione in background, ricevere pacchetti tramite il protocollo fastcgi, eseguire e restituire il risultato, ma senza terminare se stesso.

PHP ha una sapi chiamata php-cgi, che ha due funzioni: la prima è fornire l'interazione in modalità cgi, la seconda è fornire l'interazione in modalità fastcgi. In altre parole, possiamo, come con perl, far sì che il container web faccia direttamente fork di un processo php-cgi per eseguire uno script; oppure eseguire in background php-cgi -b 127.0.0.1:9000 (php-cgi come gestore fastcgi) e far interagire il container web con la porta 9000 tramite il protocollo fastcgi.

Allora, cos'è il fpm di cui ho parlato prima? Perché PHP ha due gestori fastcgi? PHP ha effettivamente due gestori fastcgi: php-cgi può girare in modalità fastcgi, e anche fpm gira in modalità fastcgi. Ma fpm è stato introdotto in PHP a partire dalla versione 5.3 ed è un gestore fastcgi più efficiente; non starò a elencare i suoi numerosi vantaggi, potete andare a vedere voi stessi il codice sorgente. Poiché fpm ha più vantaggi, oggi sempre più applicazioni web usano php-fpm per eseguire PHP.

Cause storiche

Torniamo a questa vulnerabilità. CVE-2012-1823 è una vulnerabilità emersa nella sapi php-cgi; sopra ho introdotto le due modalità di esecuzione offerte da php-cgi: cgi e fastcgi. Questa vulnerabilità si manifesta solo in PHP eseguito in modalità cgi.

In parole povere, questa vulnerabilità consiste nel fatto che la querystring della richiesta dell'utente viene passata come parametro a php-cgi, portando infine a una serie di conseguenze.

Approfondiamo il principio: la RFC3875 stabilisce che, quando la querystring non contiene un segno = non decodificato, la querystring deve essere passata come parametro cgi. Pertanto, il server Apache ha implementato questa funzionalità come richiesto.

Ma PHP non ha tenuto conto di questa regola della RFC; forse in passato l'aveva notata e gestita, con il metodo di non consentire il passaggio di parametri nel contesto web. Tuttavia, nel 2004 un certo sviluppatore pubblicò questa dichiarazione:

root@kitploit:~
From: Rasmus Lerdorf <rasmus <at> lerdorf.com>
Subject: [PHP-DEV] php-cgi command line switch memory check
Newsgroups: gmane.comp.php.devel
Date: 2004-02-04 23:26:41 GMT (7 years, 49 weeks, 3 days, 20 hours and 39 minutes ago)
 
In our SAPI cgi we have a check along these lines:
 
    if (getenv("SERVER_SOFTWARE")
        || getenv("SERVER_NAME")
        || getenv("GATEWAY_INTERFACE")
        || getenv("REQUEST_METHOD")) {
        cgi = 1;
    }
 
    if(!cgi) getopt(...)
 
As in, we do not parse command line args for the cgi binary if we are 
running in a web context.  At the same time our regression testing system 
tries to use the cgi binary and it sets these variables in order to 
properly test GET/POST requests.  From the regression testing system we 
use -d extensively to override ini settings to make sure our test 
environment is sane.  Of course these two ideas conflict, so currently our 
regression testing is somewhat broken.  We haven't noticed because we 
don't have many tests that have GET/POST data and we rarely build the cgi 
binary.
 
The point of the question here is if anybody remembers why we decided not 
to parse command line args for the cgi version?  I could easily see it 
being useful to be able to write a cgi script like:
 
  #!/usr/local/bin/php-cgi -d include_path=/path
  <?php
      ...
  ?>
 
and have it work both from the command line and from a web context.
 
As far as I can tell this wouldn't conflict with anything, but somebody at 
some point must have had a reason for disallowing this.
 
-Rasmus

Ovviamente, questo sviluppatore voleva facilitare i test utilizzando una sintassi come #!/usr/local/bin/php-cgi -d include_path=/path, ritenendo che non si dovesse limitare la possibilità di php-cgi di accettare parametri da riga di comando, e che questa funzionalità non entrasse in conflitto con nessun altro codice.

Così, if(!cgi) getopt(...) venne eliminato.

Ma è evidente che, secondo la spiegazione della RFC riguardo alla riga di comando, i parametri della riga di comando non possono essere passati a php-cgi solo tramite #!/usr/local/bin/php-cgi -d include_path=/path, ma anche tramite la querystring.

Questa è la causa storica di questa vulnerabilità.

Sfruttamento della vulnerabilità

Allora, cosa si può fare controllando i parametri della riga di comando?

Leggendo il codice sorgente, ho scoperto che in modalità cgi sono disponibili i seguenti parametri:

  • -c specifica la posizione del file php.ini
  • -n non caricare il file php.ini
  • -d specifica un elemento di configurazione
  • -b avvia il processo fastcgi
  • -s mostra il codice sorgente del file
  • -T esegue il file un numero specificato di volte
  • -h e -? mostrano l'aiuto

Il modo di sfruttamento più semplice è ovviamente -s, che può mostrare direttamente il codice sorgente:

Ma chi ha letto il mio articolo su fastcgi dovrebbe subito pensare a un metodo di sfruttamento migliore: usando -d per specificare auto_prepend_file, si crea una vulnerabilità di inclusione arbitraria di file ed è possibile eseguire codice arbitrario:

Nota: gli spazi vengono sostituiti con + o %20, e = va sostituito con la codifica URL.

CVE-2012-2311

Dopo che questa vulnerabilità venne alla luce, il team ufficiale di PHP la corresse rilasciando le nuove versioni 5.4.2 e 5.3.12, ma questa correzione era incompleta e poteva essere aggirata, dando origine alla vulnerabilità CVE-2012-2311.

Il metodo di correzione di PHP è stato quello di controllare il carattere -:

root@kitploit:~
if(query_string = getenv("QUERY_STRING")) {
	decoded_query_string = strdup(query_string);
	php_url_decode(decoded_query_string, strlen(decoded_query_string));
	if(*decoded_query_string == '-' && strchr(decoded_query_string, '=') == NULL) {
		skip_getopt = 1;
	}
	free(decoded_query_string);
}

Si vede che, dopo aver ottenuto e decodificato la querystring, se il primo carattere è - viene impostato skip_getopt, ovvero non si acquisiscono i parametri della riga di comando.

Il punto non sicuro di questa correzione è che, se l'amministratore di sistema ha applicato un wrapper a php-cgi:

root@kitploit:~
#!/bin/sh

exec /usr/local/bin/php-cgi $*

Usando uno spazio bianco seguito da -, è comunque possibile passare parametri. In questo caso il primo carattere della querystring è uno spazio bianco invece di -, aggirando il controllo di cui sopra.

Così, in PHP 5.4.3 e 5.3.13 si è continuato a modificare:

root@kitploit:~
if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) {
	/* we've got query string that has no = - apache CGI will pass it to command line */
	unsigned char *p;
	decoded_query_string = strdup(query_string);
	php_url_decode(decoded_query_string, strlen(decoded_query_string));
	for (p = decoded_query_string; *p &&  *p <= ' '; p++) {
		/* skip all leading spaces */
	}
	if(*p == '-') {
		skip_getopt = 1;
	}
	free(decoded_query_string);
}

Prima vengono saltati tutti i caratteri di spazio bianco (tutti i caratteri minori o uguali allo spazio), poi si verifica se il primo carattere è -.

Scarica lo strumento