PHP Tricks
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Posizione comune dei cookie:
Questo è valido anche per i cookie di phpMyAdmin.
Cookies:
Località:
Bypassare i confronti PHP
Confronti deboli/Type Juggling ( == )
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
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F197708944-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FE5VfhVAq0qYsgU9deMR8%252Fuploads%252Fgit-blob-53dd523e3097738b14730e72b491c182672a1fc0%252Fimage%2520%28567%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=43d8f507&sv=1)
"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 (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 su https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09
in_array()
Type Juggling influisce anche sulla funzione in_array()
per impostazione predefinita (devi impostare a true il terzo argomento per effettuare un confronto rigoroso):
strcmp()/strcasecmp()
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()
Juggling di tipo rigoroso
Anche se ===
è utilizzato, potrebbero esserci errori che rendono la comparazione vulnerabile al juggling di tipo. Ad esempio, se la comparazione converte i dati in un tipo di oggetto diverso prima di confrontare:
preg_match(/^.*/)
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).
Bypass della nuova riga
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
Bypass dell'errore di lunghezza
(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
Bypass ReDoS
Trick da: https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223 e https://mizu.re/post/pong
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F197708944-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FE5VfhVAq0qYsgU9deMR8%252Fuploads%252Fgit-blob-746083bbabdbedd055c5dddac1d3ebcce0f1f726%252Fimage%2520%2826%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=24d51d20&sv=1)
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 indietro):
Type Juggling per offuscamento PHP
Execute After Redirect (EAR)
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:
Path Traversal and File Inclusion Exploitation
Check:
File Inclusion/Path traversalMore tricks
register_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.
password_hash/password_verify
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:
HTTP headers bypass abusing PHP errors
Causing error after setting headers
Da questo thread di twitter puoi vedere che inviando più di 1000 parametri GET o 1000 parametri POST o 20 file, PHP non imposterà le intestazioni nella risposta.
Consentendo di bypassare, ad esempio, le intestazioni CSP impostate in codici come:
Riempire un corpo prima di impostare le intestazioni
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 generi 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):
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F197708944-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FE5VfhVAq0qYsgU9deMR8%252Fuploads%252Fgit-blob-14119d0754739cfdb01a8cdd752ea4a282899451%252Fimage%2520%281085%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=f0fd080e&sv=1)
SSRF nelle funzioni PHP
Controlla la pagina:
PHP SSRFEsecuzione di codice
system("ls"); `ls`; shell_exec("ls");
Controlla questo per altre funzioni PHP utili
RCE tramite preg_replace()
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.
RCE tramite Eval()
RCE tramite Assert()
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"
RCE tramite usort()
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.
RCE tramite .httaccess
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
RCE tramite variabili Env
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 chiamatophp.ini
. Se puoi caricare il tuo file di configurazione, allora, usaPHPRC
per puntare a esso. Aggiungi un'entrataauto_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 1Imposta 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 ilstdin
, essendo il corpo della richiesta inviata alstdin
: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.
XAMPP CGI RCE - CVE-2024-4577
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:
PHP Sanitization bypass & Brain Fuck
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:
PHP Static analysis
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
Deobfuscating PHP code
Puoi utilizzare il web www.unphp.net per deoffuscare il codice php.
PHP Wrappers & Protocols
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.
Xdebug unauthenticated RCE
Se vedi che Xdebug è abilitato nell'output di phpconfig()
, dovresti provare a ottenere RCE tramite https://github.com/nqxcode/xdebug-exploit
Variable variables
RCE abusando di nuovo $_GET["a"]($_GET["b")
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"])Eseguire PHP senza lettere
https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
Usando ottale
XOR
XOR easy shell code
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
Shellcode XOR (all'interno di eval)
Perl simile
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)
Last updated