PHP Tricks
Posizione comune dei Cookies:
Questo è valido anche per i cookies di phpMyAdmin.
Cookies:
Luoghi:
Eludere le comparazioni in PHP
Comparazioni 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 si desidera anche confrontare che il tipo dei dati confrontati sia lo stesso è necessario utilizzare ===
.
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 vengono 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 è possibile controllare l'input della stringa "0" e alcuni contenuti che vengono hashati e confrontati con esso. Pertanto, se è possibile fornire un valore che creerà un hash che inizia con "0e" e senza alcuna lettera, è possibile eludere il confronto. È possibile trovare stringhe già hashate con questo formato qui: https://github.com/spaze/hashes"X" == 0 --> True
Qualsiasi lettera in una stringa è uguale a 0 come intero
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 (è necessario 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 uno dei lati del confronto, può inviare un array vuoto invece di una stringa come valore della password (https://example.com/login.php/?username=admin&password[]=
) e aggirare questo controllo:
Già si verifica lo stesso errore con strcasecmp()
strcasecmp()
Tipizzazione rigorosa
Anche se viene utilizzato ===
, potrebbero verificarsi errori che rendono il confronto vulnerabile al type juggling. Ad esempio, se il confronto sta convertendo i dati in un tipo di oggetto diverso prima di confrontarli:
preg_match(/^.*/)
preg_match()
potrebbe essere utilizzato per validare l'input dell'utente (controlla se c'è una parola/espressione regolare da una lista nera presente nell'input dell'utente e se non c'è, il codice può continuare la sua esecuzione).
Bypass della nuova riga
Tuttavia, quando si delimita l'inizio dell'espressione regolare, preg_match()
controlla solo la prima riga dell'input dell'utente, quindi se in qualche modo riesci a inviare l'input in più righe, potresti essere in grado di aggirare questo controllo. Esempio:
Per aggirare questo controllo potresti inviare il valore con new-lines urlencoded (%0A
) oppure, se puoi inviare dati JSON, inviali in più righe:
Trova un esempio qui: https://ramadistra.dev/fbctf-2019-rceservice
Bypass 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 riesci a inviare a preg_match()
un input molto grande e valido, non sarà in grado di elaborarlo e sarai in grado di bypassare il controllo. Ad esempio, se sta mettendo in blacklist un JSON potresti inviare:
Bypass ReDoS
Trucco 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 utilizzano molto spazio di stack. È possibile impostare un limite sul numero di ricorsioni consentite, ma in PHP questo limite predefinito è di 100.000 che è più grande dello spazio di stack disponibile.
Questo thread di Stackoverflow è stato anche collegato nel post dove si parla più approfonditamente di questo problema. Il nostro compito era ora chiaro:
Inviare un input che avrebbe fatto eseguire più di 100.000 ricorsioni alla regex, causando SIGSEGV, facendo sì che la funzione preg_match()
restituisse false
, facendo così credere all'applicazione che il nostro input non è dannoso, lanciando alla fine del payload una sorpresa come {system(<comandomoltocattivo>)}
per ottenere SSTI --> RCE --> bandiera :).
Beh, in termini di regex, in realtà non stiamo facendo 100k "ricorsioni", ma stiamo contando "passaggi di backtracking", che come la documentazione di PHP afferma che predefinito è di 1.000.000 (1M) nella variabile pcre.backtrack_limit
.
Per raggiungere questo, 'X'*500_001
produrrà 1 milione di passaggi di backtracking (500k in avanti e 500k all'indietro):
Tipizzazione debole per l'offuscamento PHP
Esegui Dopo il Reindirizzamento (EAR)
Se PHP sta reindirizzando a un'altra pagina ma nessuna funzione die
o exit
viene chiamata dopo che l'intestazione Location
è impostata, il PHP continua ad eseguire e ad aggiungere i dati al corpo:
Sfruttamento della Traversata di Percorso e Inclusione di File
Controlla:
pageFile Inclusion/Path traversalAltri trucchi
register_globals: In PHP < 4.1.1.1 o se configurato in modo errato, register_globals potrebbe essere attivo (o il loro comportamento viene emulato). Ciò implica che nelle variabili globali come $_GET se hanno un valore ad es. $_GET["param"]="1234", è possibile accedervi tramite $param. Pertanto, inviando parametri HTTP è possibile sovrascrivere le variabili utilizzate nel codice.
I cookie PHPSESSION dello stesso dominio sono memorizzati nello stesso posto, quindi se all'interno di un dominio vengono utilizzati cookie diversi in percorsi diversi è possibile fare in modo che un percorso acceda al cookie del percorso impostando il valore dell'altro cookie del percorso. In questo modo, se entrambi i percorsi accedono a una variabile con lo stesso nome è possibile fare in modo che il valore di quella variabile in path1 si applichi a path2. E quindi path2 considererà valide le variabili di path1 (dando al cookie il nome corrispondente in path2).
Quando si hanno gli username degli utenti della macchina. Controllare l'indirizzo: /~<USERNAME> per vedere se le directory php sono attivate.
password_hash/password_verify
Queste funzioni vengono tipicamente utilizzate in PHP per generare hash da password e per verificare se una password è corretta rispetto a un hash.
Gli algoritmi supportati sono: PASSWORD_DEFAULT
e PASSWORD_BCRYPT
(inizia con $2y$
). Notare che PASSWORD_DEFAULT è spesso lo stesso di PASSWORD_BCRYPT. E attualmente, PASSWORD_BCRYPT ha un limite di dimensione in input di 72 byte. Pertanto, quando si cerca di fare l'hash di qualcosa di più grande di 72 byte con questo algoritmo, verranno utilizzati solo i primi 72 byte:
Bypass degli header HTTP sfruttando gli errori di PHP
Se una pagina PHP stampa errori ed eco di alcuni input forniti dall'utente, l'utente può far sì che il server PHP stampi del contenuto abbastanza lungo in modo che quando cerca di aggiungere gli header alla risposta il server generi un errore. Nello scenario seguente, l'attaccante ha fatto sì che il server generasse alcuni errori consistenti, e come si può vedere nello screenshot, quando PHP ha provato a modificare le informazioni degli header, non è riuscito (quindi ad esempio l'header CSP non è stato inviato all'utente):
Esecuzione del codice
system("ls"); `ls`; shell_exec("ls");
Controlla qui per ulteriori funzioni utili di PHP
RCE tramite preg_replace()
Per eseguire il codice nell'argomento "replace" è necessario 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 ti permette di eseguire codice scritto in una stringa per restituire true o false (e in base a questo alterare l'esecuzione). Di solito la variabile dell'utente verrà inserita nel mezzo di una stringa. Per esempio:
assert("strpos($_GET['page']),'..') === false")
--> In questo caso per ottenere RCE potresti fare:
Avrai bisogno di rompere la sintassi del codice, aggiungere il tuo payload, e poi ripararlo di nuovo. Puoi utilizzare operazioni logiche come "and" o "%26%26" o "|". Nota che "or", "||" non funzionano perché se la prima condizione è vera il nostro payload non verrà eseguito. Allo stesso modo ";" non funziona poiché il nostro payload non verrà eseguito.
Un'altra opzione è aggiungere all'interno della stringa l'esecuzione del comando: '.highlight_file('.passwd').'
Un'altra opzione (se hai il codice interno) è modificare qualche variabile 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 utilizzare // per commentare il resto del codice.
Per scoprire il numero di parentesi che devi chiudere:
?order=id;}//
: otteniamo un messaggio di errore (Errore di analisi: errore di sintassi, ';' imprevisto
). Probabilmente ci manca una o più parentesi.?order=id);}//
: otteniamo un avviso. Questo sembra corretto.?order=id));}//
: otteniamo un messaggio di errore (Errore di analisi: errore di sintassi, ')' imprevisto
). Probabilmente abbiamo troppi parentesi di chiusura.
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).
È possibile trovare diverse shell .htaccess qui
RCE tramite Variabili d'Ambiente
Se trovi una vulnerabilità che ti permette di modificare le variabili d'ambiente in PHP (e un'altra per caricare file, anche se con ulteriori ricerche potrebbe essere aggirata), potresti sfruttare questo comportamento per ottenere RCE.
LD_PRELOAD
: Questa variabile d'ambiente consente di caricare librerie arbitrarie durante l'esecuzione di altri binari (anche se in questo caso potrebbe non funzionare).PHPRC
: Istruisce PHP su dove individuare il suo file di configurazione, di solito chiamatophp.ini
. Se puoi caricare il tuo file di configurazione, allora usaPHPRC
per puntare PHP su di esso. Aggiungi una voceauto_prepend_file
specificando un secondo file caricato. Questo secondo file contiene del codice PHP normale, che viene quindi eseguito dal runtime di PHP prima di qualsiasi altro codice.
Carica un file PHP contenente il nostro codice shell
Carica un secondo file, contenente una direttiva
auto_prepend_file
istruendo il preprocessore PHP ad eseguire il file che abbiamo caricato al passo 1Imposta la variabile
PHPRC
sul file che abbiamo caricato al passo 2.
Ottieni ulteriori informazioni su come eseguire questa catena dal report originale.
PHPRC - un'altra opzione
Se non puoi caricare file, potresti utilizzare in FreeBSD il "file"
/dev/fd/0
che contiene lostdin
, essendo il corpo della richiesta inviata allostdin
: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 anteporre un file con codice PHP in 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 report.
Analisi Statica di PHP
Verifica 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 riavviare apache: sudo systemctl restart apache2
Deobfuscating PHP code
Puoi utilizzare il web www.unphp.net per deobfuscate il codice PHP.
PHP Wrappers & Protocols
I wrapper e i protocolli PHP potrebbero consentirti di bypassare le protezioni di scrittura e lettura in un sistema e comprometterlo. Per ulteriori informazioni controlla questa pagina.
Xdebug unauthenticated RCE
Se noti che Xdebug è abilitato in un output di phpconfig()
, dovresti provare a ottenere RCE tramite https://github.com/nqxcode/xdebug-exploit
Variable variables
RCE sfruttando il 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:
pagePHP - RCE abusing object creation: new $_GET["a"]($_GET["b"])Eseguire PHP senza lettere
https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
Utilizzando ottale
XOR
Codice shell XOR semplice
Secondo questo articolo, è possibile generare un codice shell semplice 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
XOR Shellcode (all'interno di eval)
Simile a Perl
Last updated