Seguimiento de los intentos XSS reflejados

1

Entonces, aquí hay un pedazo de código que encontré.

<?php

    $name = $_GET['name'];

    if (!empty($name)) {
            $name = str_replace("<", "&lt;", $name);    //line 1
            $name = str_replace(">", "&gt;", $name);    //line 2
            $name = urldecode($name);                   //line 3

            echo $name;

    }

    ?>

Este código lo encontré en uno de los marcos de práctica de piratería ética llamados bWAPP en el nivel de seguridad 1. La solución potencial para evitar esta técnica es a URL encode la cadena XSS dos veces.

Supongamos que mi cadena XSS es

<script>alert('XSS');</script>       //checkpoint alpha

Entonces, codificarlo una vez debería darme

%3Cscript%3Ealert%28%27XSS%27%29%3C%2fscript%3E  //checkpoint beta

PROBLEMA 1:
Si lo trazo hacia abajo, en la línea 1 y 2 no pasa nada. Pero en la línea 3 se decodifica. Y así, la cadena resultante que recupero se convierte en checkpoint alpha . Entonces, cuando lo repito, debería aparecer una alerta.

CONTRADICCIÓN 1:
No ocurre nada de esto y acabo de mostrar checkpoint alpha en texto claro.

PROBLEMA 2:
Cuando, lo doble codificando, (que es la solución potencial a este problema), obtengo,

%253Cscript%253Ealert%2528%2527XSS%2527%2529%253C%252fscript%253E 

Ahora, esta declaración pasa nuevamente por las líneas 1 y 2, y al tropezar con la línea 3, se decodifica a checkpoint beta y se hace eco.

CONTRADICCIÓN 2:
Cuando se hace eco, debería obtener checkpoint beta en texto claro, pero de repente el navegador abre el cuadro de alerta con XSS funcionando perfectamente.

Soy nuevo en este campo y actualmente estoy intentando borrar mis conceptos básicos relacionados con el desarrollo web. Por favor, perdonen mi incorrecta declaración de formación. Gracias.

    
pregunta M.S.P 31.03.2017 - 11:29
fuente

2 respuestas

3

Cuando PHP recupera el parámetro GET con $name = $_GET['name'] , realiza una decodificación de URL implícita. PHP no requiere que usted decodifique un parámetro de URL.

Ambos resultados tienen el mismo valor exacto para $name :

http://yourapp/?name=<script>alert(1);</script>
http://yourapp/?name=%3Cscript%3Ealert%281%29%3C%2fscript%3E

Entonces, incluso si < se ve como %3c en su URL, se almacenará como un literal < en $name . En consecuencia, la parte str_replace() reconoce correctamente < y > y filtra estos caracteres, evitando así que XSS.

La parte vulnerable es el urldecode() explícito al final.

Si proporciona la URL http://yourapp/?name=%253c , entonces la variable $name contendrá literalmente %3c (que son tres caracteres) y las funciones str_replace() la ignorarán porque ninguna de % , 3 , c parece un soporte de ángulo. Luego, al final, urldecode() realiza innecesariamente otra decodificación y convierte la secuencia %3c en un < literal después de que ya haya pasado el filtro de reemplazo.

Si aún no te queda claro, reemplaza $name = $_GET['name'] con esto:

$name = urldecode('%253Cscript%253Ealert%25281%2529%253C%252fscript%253E')

Verá que esto tiene el mismo efecto que proporcionar la cadena como el parámetro de la URL y muestra que dos códigos urldec son redundantes.

    
respondido por el Arminius 31.03.2017 - 13:59
fuente
1

Está bien, no soy un desarrollador de PHP (o un desarrollador), pero probé esto.

tldr: $ _GET ['name'] codifica el nombre del parámetro

Utilicé tu código pero puse un:

echo $name;

En cada línea.

Probé lo siguiente:

  • < test >, el parámetro $ name comienza como y termina con caracteres de escape
  • % 3Ctest% 3E, el parámetro $ name comienza como después de $ _GET, por lo que inmediatamente el parámetro ya está urldecoded una vez
  • % 253Ctest% 253E, el parámetro $ name comienza como% 3Ctest% 3E después de $ _GET, por lo que se decodifica una vez. Luego, la validación falla y la segunda decodificación decodifica el parámetro para

Para responder a tus contradicciones:

Contradicción 1 mire lo que realmente obtiene usando Firebug o un proxy o un solicitante de http. Su navegador dice que le muestra, pero lo que realmente obtuvo fue < prueba > e interpretó que para. Esto puede ser confuso, pero el navegador recuperó su esencia escapada.

Contradicción 2 Beta se codifica una vez, se decodifica una vez en la solicitud de inicio ($ _GET), luego < y > cambiar a < y & gt ;.

    
respondido por el Wealot 31.03.2017 - 12:27
fuente

Lea otras preguntas en las etiquetas