Drupal filtra XSS con expresiones regulares. ¿Qué podría evitarlo?

9

Drupal filtra las cadenas HTML contra ataques XSS usando expresiones regulares: enlace

Sin embargo, como mucha gente sabe, HTML no se puede analizar con expresiones regulares .

Lo que me hace pensar que la función filter_xss podría permitir que un código HTML no válido pase una etiqueta script , por lo que es un defecto de seguridad.

Pero no soy lo suficientemente eficiente con expresiones regulares. Tal vez alguien pueda encontrar algo que pase? Si es así, haría un parche para usar simplexml (o algo mejor si existe) en lugar de expresiones regulares.

FWIW, aquí está el código de la función:

function filter_xss($string, $allowed_tags = array('a', 'em', 'strong', 'cite', 'blockquote', 'code', 'ul', 'ol', 'li', 'dl', 'dt', 'dd')) {
  // Only operate on valid UTF-8 strings. This is necessary to prevent cross
  // site scripting issues on Internet Explorer 6.
  if (!drupal_validate_utf8($string)) {
    return '';
  }
  // Store the text format.
  _filter_xss_split($allowed_tags, TRUE);
  // Remove NULL characters (ignored by some browsers).
  $string = str_replace(chr(0), '', $string);
  // Remove Netscape 4 JS entities.
  $string = preg_replace('%&\s*\{[^}]*(\}\s*;?|$)%', '', $string);

  // Defuse all HTML entities.
  $string = str_replace('&', '&', $string);
  // Change back only well-formed entities in our whitelist:
  // Decimal numeric entities.
  $string = preg_replace('/&#([0-9]+;)/', '&#', $string);
  // Hexadecimal numeric entities.
  $string = preg_replace('/&#[Xx]0*((?:[0-9A-Fa-f]{2})+;)/', '&#x', $string);
  // Named entities.
  $string = preg_replace('/&([A-Za-z][A-Za-z0-9]*;)/', '&', $string);

  return preg_replace_callback('%
    (
    <(?=[^a-zA-Z!/])  # a lone <
    |                 # or
    <!--.*?-->        # a comment
    |                 # or
    <[^>]*(>|$)       # a string that starts with a <, up until the > or the end of the string
    |                 # or
    >                 # just a >
    )%x', '_filter_xss_split', $string);
}

Y esta función utiliza _filter_xss_split :

function _filter_xss_split($m, $store = FALSE) {
  static $allowed_html;

  if ($store) {
    $allowed_html = array_flip($m);
    return;
  }

  $string = $m[1];

  if (substr($string, 0, 1) != '<') {
    // We matched a lone ">" character.
    return '&gt;';
  }
  elseif (strlen($string) == 1) {
    // We matched a lone "<" character.
    return '&lt;';
  }

  if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?|(<!--.*?-->)$%', $string, $matches)) {
    // Seriously malformed.
    return '';
  }

  $slash = trim($matches[1]);
  $elem = &$matches[2];
  $attrlist = &$matches[3];
  $comment = &$matches[4];

  if ($comment) {
    $elem = '!--';
  }

  if (!isset($allowed_html[strtolower($elem)])) {
    // Disallowed HTML element.
    return '';
  }

  if ($comment) {
    return $comment;
  }

  if ($slash != '') {
    return "</$elem>";
  }

  // Is there a closing XHTML slash at the end of the attributes?
  $attrlist = preg_replace('%(\s?)/\s*$%', '', $attrlist, -1, $count);
  $xhtml_slash = $count ? ' /' : '';

  // Clean up attributes.
  $attr2 = implode(' ', _filter_xss_attributes($attrlist));
  $attr2 = preg_replace('/[<>]/', '', $attr2);
  $attr2 = strlen($attr2) ? ' ' . $attr2 : '';

  return "<$elem$attr2$xhtml_slash>";
}
    
pregunta Florian Margaine 02.11.2012 - 16:43
fuente

2 respuestas

3

Consulte ¿Es el filter_xss de Drupal suficiente para filtrar HTML? , que analiza la seguridad de Drupal's filter_xss() . Asegúrese de leer el análisis de Mike Samuel, que identifica una serie de deficiencias de filter_xss() . No sé si los clasificaría exactamente como vulnerabilidades, pero son fallas / fallas de diseño que podrían hacer que filter_xss() sea menos efectivo de lo que los desarrolladores podrían esperar.

La documentación del desarrollador para filter_xss() es atrozmente mala.

Hay una suma total de dos oraciones: "Filtra HTML para evitar vulnerabilidades entre scripts de sitios (XSS)". y "Use check_markup o filter_xss para el marcado que contiene texto". Cuando la documentación no explica cómo usar filter_xss() correctamente, no debería sorprenderse si los desarrolladores no lo usan correctamente. Esto podría provocar vulnerabilidades, por ejemplo, del tipo que Rook identifica.

(Drupal también tiene un documento titulado Maneja el texto de manera segura , pero ni siquiera menciona filter_xss() . )

También sugeriría que cualquier persona que llame a filter_xss() debería asegurarse de no incluir !-- en la lista de etiquetas permitidas. El código para validar comentarios (que está habilitado si agrega !-- a la lista de etiquetas permitidas) me parece muy simple: no hace nada para validar el contenido del comentario, que intuitivamente parece que puede ' t posiblemente sea seguro.

    
respondido por el D.W. 02.11.2012 - 20:53
fuente
0

XSS es un problema de salida, no hay una función mágica que pueda prevenir todas las vulnerabilidades de XSS. La raíz de todas las vulnerabilidades es usar la funcionalidad de una manera que nunca fue pensada.

Estos dos son bastante obvios:

print "<script>".filter_xss($_GET['still_xss1'])."</script>"; 
print "<a href=".filter_xss($_GET['still_xss2']).">xss</a>";

PoC:

?still_xss1=alert(1)
?still_xss2=javascript:alert(1)

También parece que puedes inyectar controladores de eventos: ' onclick=alert(1) ' , aunque no lo he probado ...

    
respondido por el rook 02.11.2012 - 20:13
fuente

Lea otras preguntas en las etiquetas