PHP Tricks
Last updated
Last updated
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ottieni la prospettiva di un hacker sulle tue app web, rete e cloud
Trova e segnala vulnerabilità critiche e sfruttabili con un reale impatto sul business. Usa i nostri oltre 20 strumenti personalizzati per mappare la superficie di attacco, trovare problemi di sicurezza che ti permettano di elevare i privilegi e utilizzare exploit automatizzati per raccogliere prove essenziali, trasformando il tuo duro lavoro in report persuasivi.
Questo è valido anche per i cookie di phpMyAdmin.
Cookies:
Località:
Se ==
viene utilizzato in PHP, ci sono casi inaspettati in cui il confronto non si comporta come previsto. Questo perché "==" confronta solo i valori trasformati nello stesso tipo, se vuoi anche confrontare che il tipo dei dati confrontati sia lo stesso devi usare ===
.
Tabelle di confronto PHP: https://www.php.net/manual/en/types.comparisons.php
"string" == 0 -> True
Una stringa che non inizia con un numero è uguale a un numero
"0xAAAA" == "43690" -> True
Stringhe composte da numeri in formato decimale o esadecimale possono essere confrontate con altri numeri/stringhe con True come risultato se i numeri erano gli stessi (i numeri in una stringa sono interpretati come numeri)
"0e3264578" == 0 --> True
Una stringa che inizia con "0e" e seguita da qualsiasi cosa sarà uguale a 0
"0X3264578" == 0X --> True
Una stringa che inizia con "0" e seguita da qualsiasi lettera (X può essere qualsiasi lettera) e seguita da qualsiasi cosa sarà uguale a 0
"0e12334" == "0" --> True
Questo è molto interessante perché in alcuni casi puoi controllare l'input della stringa di "0" e qualche contenuto che viene hashato e confrontato con esso. Pertanto, se puoi fornire un valore che creerà un hash che inizia con "0e" e senza alcuna lettera, potresti bypassare il confronto. Puoi trovare stringhe già hashate con questo formato qui: https://github.com/spaze/hashes
"X" == 0 --> True
Qualsiasi lettera in una stringa è uguale a int 0
Ulteriori informazioni in https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09
Juggling di tipo influisce anche sulla funzione in_array()
per impostazione predefinita (devi impostare a true il terzo argomento per effettuare un confronto rigoroso):
Se questa funzione viene utilizzata per qualsiasi controllo di autenticazione (come il controllo della password) e l'utente controlla un lato del confronto, può inviare un array vuoto invece di una stringa come valore della password (https://example.com/login.php/?username=admin&password[]=
) e bypassare questo controllo:
Lo stesso errore si verifica con strcasecmp()
Anche se ===
viene utilizzato, potrebbero esserci errori che rendono la comparazione vulnerabile al gioco di tipi. Ad esempio, se la comparazione sta convertendo i dati in un diverso tipo di oggetto prima di confrontare:
preg_match()
potrebbe essere utilizzato per validare l'input dell'utente (controlla se qualche parola/regex da una blacklist è presente nell'input dell'utente e se non lo è, il codice può continuare la sua esecuzione).
Tuttavia, quando si delimita l'inizio della regexp preg_match()
controlla solo la prima riga dell'input dell'utente, quindi se in qualche modo puoi inviare l'input in più righe, potresti essere in grado di eludere questo controllo. Esempio:
Per bypassare questo controllo potresti inviare il valore con nuove righe urlencoded (%0A
) oppure se puoi inviare dati JSON, invialo in più righe:
Trova un esempio qui: https://ramadistra.dev/fbctf-2019-rceservice
(Questo bypass è stato provato apparentemente su PHP 5.2.5 e non sono riuscito a farlo funzionare su PHP 7.3.15)
Se puoi inviare a preg_match()
un input valido molto grande, non sarà in grado di elaborarlo e potrai bypassare il controllo. Ad esempio, se sta bloccando un JSON potresti inviare:
From: https://medium.com/bugbountywriteup/solving-each-and-every-fb-ctf-challenge-part-1-4bce03e2ecb0
Trick da: https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223 e https://mizu.re/post/pong
In breve, il problema si verifica perché le funzioni preg_*
in PHP si basano sulla libreria PCRE. In PCRE alcune espressioni regolari vengono abbinate utilizzando molte chiamate ricorsive, che consumano molto spazio nello stack. È possibile impostare un limite sul numero di ricorsioni consentite, ma in PHP questo limite è impostato di default a 100.000 che è più di quanto possa contenere lo stack.
Questo thread di Stackoverflow è stato anche collegato nel post dove si parla più in dettaglio di questo problema. Il nostro compito era ora chiaro:
Inviare un input che avrebbe fatto fare 100_000+ ricorsioni all'espressione regolare, causando SIGSEGV, facendo restituire alla funzione preg_match()
false
, facendo così pensare all'applicazione che il nostro input non è malevolo, lanciando la sorpresa alla fine del payload qualcosa come {system(<verybadcommand>)}
per ottenere SSTI --> RCE --> flag :).
Bene, in termini di regex, in realtà non stiamo facendo 100k "ricorsioni", ma stiamo contando i "passi di backtracking", che come afferma la documentazione PHP è impostata di default a 1_000_000 (1M) nella variabile pcre.backtrack_limit
.\ Per raggiungere questo, 'X'*500_001
risulterà in 1 milione di passi di backtracking (500k in avanti e 500k all'indietro):
Se PHP sta reindirizzando a un'altra pagina ma nessuna funzione die
o exit
è chiamata dopo che l'intestazione Location
è impostata, PHP continua a eseguire e ad aggiungere i dati al corpo:
Check:
File Inclusion/Path traversalregister_globals: In PHP < 4.1.1.1 o se mal configurato, register_globals potrebbe essere attivo (o il loro comportamento è imitato). Questo implica che nelle variabili globali come $_GET se hanno un valore ad esempio $_GET["param"]="1234", puoi accedervi tramite $param. Pertanto, inviando parametri HTTP puoi sovrascrivere variabili che vengono utilizzate all'interno del codice.
I cookie PHPSESSION dello stesso dominio sono memorizzati nello stesso posto, quindi se all'interno di un dominio cookie diversi vengono utilizzati in percorsi diversi puoi fare in modo che un percorso acceda al cookie dell'altro percorso impostando il valore del cookie dell'altro percorso. In questo modo, se entrambi i percorsi accedono a una variabile con lo stesso nome puoi fare in modo che il valore di quella variabile in path1 si applichi a path2. E poi path2 considererà validi le variabili di path1 (dando al cookie il nome che corrisponde a esso in path2).
Quando hai i nomi utente degli utenti della macchina. Controlla l'indirizzo: /~<USERNAME> per vedere se le directory php sono attivate.
Queste funzioni sono tipicamente utilizzate in PHP per generare hash dalle password e per verificare se una password è corretta rispetto a un hash.
Gli algoritmi supportati sono: PASSWORD_DEFAULT
e PASSWORD_BCRYPT
(inizia con $2y$
). Nota che PASSWORD_DEFAULT è frequentemente lo stesso di PASSWORD_BCRYPT. E attualmente, PASSWORD_BCRYPT ha una limitazione di dimensione nell'input di 72byte. Pertanto, quando provi a fare hash di qualcosa di più grande di 72byte con questo algoritmo, verranno utilizzati solo i primi 72B:
Da questo thread di twitter puoi vedere che inviando più di 1000 parametri GET o 1000 parametri POST o 20 file, PHP non imposterà gli header nella risposta.
Consentendo di bypassare, ad esempio, gli header CSP impostati in codici come:
Se una pagina PHP sta stampando errori e restituendo alcuni input forniti dall'utente, l'utente può far stampare al server PHP un contenuto sufficientemente lungo in modo che quando cerca di aggiungere le intestazioni nella risposta, il server genererà un errore. Nello scenario seguente, l'attaccante ha fatto generare al server alcuni grandi errori, e come puoi vedere nello schermo, quando PHP ha cercato di modificare le informazioni dell'intestazione, non ci è riuscito (quindi, ad esempio, l'intestazione CSP non è stata inviata all'utente):
Controlla la pagina:
PHP SSRFsystem("ls"); `ls`; shell_exec("ls");
Controlla questo per altre utili funzioni PHP
Per eseguire il codice nell'argomento "replace" è necessaria almeno una corrispondenza. Questa opzione di preg_replace è stata deprecata a partire da PHP 5.5.0.
Questa funzione all'interno di php consente di eseguire codice scritto in una stringa per restituire true o false (e a seconda di questo alterare l'esecuzione). Di solito, la variabile utente verrà inserita nel mezzo di una stringa. Ad esempio:
assert("strpos($_GET['page']),'..') === false")
--> In questo caso, per ottenere RCE potresti fare:
Dovrai rompere la sintassi del codice, aggiungere il tuo payload e poi aggiustarlo di nuovo. Puoi usare operazioni logiche come "and" o "%26%26" o "|". Nota che "or", "||" non funziona perché se la prima condizione è vera, il nostro payload non verrà eseguito. Allo stesso modo, ";" non funziona poiché il nostro payload non verrà eseguito.
Altra opzione è aggiungere alla stringa l'esecuzione del comando: '.highlight_file('.passwd').'
Altra opzione (se hai il codice interno) è modificare alcune variabili per alterare l'esecuzione: $file = "hola"
Questa funzione viene utilizzata per ordinare un array di elementi utilizzando una funzione specifica. Per abusare di questa funzione:
Puoi anche usare // per commentare il resto del codice.
Per scoprire il numero di parentesi che devi chiudere:
?order=id;}//
: otteniamo un messaggio di errore (Parse error: syntax error, unexpected ';'
). Probabilmente ci manca una o più parentesi.
?order=id);}//
: otteniamo un avviso. Sembra corretto.
?order=id));}//
: otteniamo un messaggio di errore (Parse error: syntax error, unexpected ')' i
). Probabilmente abbiamo troppe parentesi chiuse.
Se puoi caricare un .htaccess, allora puoi configurare diverse cose e persino eseguire codice (configurando che i file con estensione .htaccess possono essere eseguiti).
Diverse shell .htaccess possono essere trovate qui
Se trovi una vulnerabilità che ti consente di modificare le variabili env in PHP (e un'altra per caricare file, anche se con ulteriori ricerche forse questo può essere aggirato), potresti abusare di questo comportamento per ottenere RCE.
LD_PRELOAD
: Questa variabile env ti consente di caricare librerie arbitrarie durante l'esecuzione di altri binari (anche se in questo caso potrebbe non funzionare).
PHPRC
: Istruisce PHP su dove trovare il suo file di configurazione, di solito chiamato php.ini
. Se puoi caricare il tuo file di configurazione, allora, usa PHPRC
per puntare a esso. Aggiungi un'entrata auto_prepend_file
specificando un secondo file caricato. Questo secondo file contiene codice PHP normale, che viene poi eseguito dal runtime PHP prima di qualsiasi altro codice.
Carica un file PHP contenente il nostro shellcode
Carica un secondo file, contenente una direttiva auto_prepend_file
che istruisce il preprocessore PHP a eseguire il file che abbiamo caricato nel passo 1
Imposta la variabile PHPRC
sul file che abbiamo caricato nel passo 2.
Ottieni ulteriori informazioni su come eseguire questa catena dal rapporto originale.
PHPRC - un'altra opzione
Se non puoi caricare file, potresti usare in FreeBSD il "file" /dev/fd/0
che contiene il stdin
, essendo il corpo della richiesta inviata al stdin
:
curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'
Oppure per ottenere RCE, abilita allow_url_include
e prepende un file con codice PHP base64:
curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary $'allow_url_include=1\nauto_prepend_file="data://text/plain;base64,PD8KICAgcGhwaW5mbygpOwo/Pg=="'
Tecnica da questo rapporto.
Il server web analizza le richieste HTTP e le passa a uno script PHP eseguendo una richiesta come http://host/cgi.php?foo=bar
come php.exe cgi.php foo=bar
, il che consente un'iniezione di parametri. Questo consentirebbe di iniettare i seguenti parametri per caricare il codice PHP dal corpo:
Inoltre, è possibile iniettare il parametro "-" utilizzando il carattere 0xAD a causa della successiva normalizzazione di PHP. Controlla l'esempio di exploit da questo post:
In questo post è possibile trovare ottime idee per generare un codice PHP brain fuck con pochissimi caratteri consentiti. Inoltre, viene proposta anche un'interessante modalità per eseguire funzioni che consentono di bypassare diversi controlli:
Guarda se puoi inserire codice nelle chiamate a queste funzioni (da qui):
Se stai eseguendo il debug di un'applicazione PHP, puoi abilitare globalmente la stampa degli errori in /etc/php5/apache2/php.ini
aggiungendo display_errors = On
e riavviando apache: sudo systemctl restart apache2
Puoi utilizzare il web www.unphp.net per deoffuscare il codice php.
I PHP Wrappers e i protocolli potrebbero consentirti di bypassare le protezioni di scrittura e lettura in un sistema e comprometterlo. Per maggiori informazioni controlla questa pagina.
Se vedi che Xdebug è abilitato nell'output di phpconfig()
, dovresti provare a ottenere RCE tramite https://github.com/nqxcode/xdebug-exploit
Se in una pagina puoi creare un nuovo oggetto di una classe arbitraria potresti essere in grado di ottenere RCE, controlla la seguente pagina per imparare come:
PHP - RCE abusing object creation: new $_GET["a"]($_GET["b"])https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
Secondo questo writeup è possibile generare un easy shellcode in questo modo:
Quindi, se puoi eseguire PHP arbitrario senza numeri e lettere puoi inviare una richiesta come la seguente abusando di quel payload per eseguire PHP arbitrario:
Per una spiegazione più approfondita, controlla https://ctf-wiki.org/web/php/php/#preg_match
Ottieni la prospettiva di un hacker sulle tue app web, rete e cloud
Trova e segnala vulnerabilità critiche e sfruttabili con un impatto reale sul business. Usa i nostri oltre 20 strumenti personalizzati per mappare la superficie di attacco, trovare problemi di sicurezza che ti permettano di elevare i privilegi e utilizzare exploit automatizzati per raccogliere prove essenziali, trasformando il tuo duro lavoro in report persuasivi.
Impara e pratica l'Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Impara e pratica l'Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)