El escenario simplista sería intentar y enviar --><?php phpinfo();?><!--
. Si se escapa la etiqueta <?php
, esto daría como resultado
<!-- -->
<?php phpinfo();
<!-- -->
(nuevas líneas agregadas para mayor claridad). Pero la presencia de <?php ...?>
en la página HTML podría no ser suficiente; el código PHP debe ser interpretado del lado del servidor, no solo enviado de vuelta al cliente.
Al examinar más de cerca el principio de la cadena resultante:
<!--?
está claro que no es la etiqueta de PHP, sino el <
solo lo que activa el escape, y esto probablemente sea una defensa HTML / XML / XSS. Lo que significa que no puede enviar contenidos activos y hacer que se ejecuten, o se procesen en forma ejecutable por el cliente.
Nuevamente, puedes intentar con "pre-escape", enviando
< --><hr><!-- >
y viendo si esto se transforma ingenuamente en
<!----><hr><!-- -->
que se representaría como HTML, o se modifica más a fondo en
<!-- -- --><!-- hr --><!-- !-- -->
que no sirve para nada útil. Esto depende completamente de cómo se realiza la detección de etiqueta abierta HTML y cómo funciona. A veces, preg_replace
se usa con expresiones regulares incorrectas, incompletas o no lo suficientemente codiciosas, que pueden desfigurar solo la primera o la última etiqueta, o desfigurar ciegamente la primera abertura con el último cierre, ignorando cualquier cosa que se encuentre en el medio. Si ese es el caso, entonces la página es vulnerable a la inyección de Javascript y una variedad de ataques relacionados.
¿El código de desinfección está disponible para inspección?
Ejemplo de validación ingenua
Por ejemplo, este código aparentemente desinfecta la salida HTML.
preg_replace("/<(.*)>/", "<!-- \1 -->", $input);
pero (aparte de ser una medida mal pensada), ¿la falta de un operador que no se siente bien? lo deja vulnerable a un simple ataque preescape:
<?php
$params = array(
"<script>alert('FAIL');</script>",
"< --><script>alert('Success');</script><!-- >",
);
foreach($params as $param)
print preg_replace("/<(.*)>/", "<!-- \1 -->", $param) . "\n\n\n";
?>
hace que el primer ataque ingenuo falle, mientras que el segundo tiene éxito:
<!-- script>alert('FAIL');</script -->
<!-- --><script>alert('Success');</script><!-- -->
Lamentablemente, esta opción preg_replace
a menudo se sugiere o implementa como una "solución rápida" para los ataques de inyección HTML, y como la mayoría de las "soluciones temporales" suelen hacerlo, puede convertirse en permanente .
Una mejor estrategia sería filtrar cualquier cosa que no pertenezca al parámetro original (por ejemplo, reemplazar [^A-Za-z0-9_]
por nada en absoluto), o suponer que la presencia de caracteres prohibidos significa que Algo malo viene de esta manera , y por lo tanto, la reacción más segura es descartar la solicitud por completo (tal vez informar al usuario, en caso de que ocurra por accidente o debido a un problema, por ejemplo, un enlace sintácticamente incorrecto, en otro lugar, por lo que se recomienda encarecidamente el registro de HTTP_REFERER
).