Filtri drupali XSS con regex. Cosa potrebbe bypassarlo?

9

Drupal filtra le stringhe HTML contro gli attacchi XSS usando espressioni regolari: link

Tuttavia, come molti sanno, HTML non può essere analizzato con espressioni regolari .

Il che mi fa pensare che la funzione filter_xss possa consentire ad alcuni HTML non validi di passare un tag script , rappresentando quindi un difetto di sicurezza.

Ma non sono abbastanza efficiente con le regex. Forse qualcuno può trovare qualcosa che passa? Se c'è, creo una patch per usare simplexml (o qualcosa di meglio se c'è) invece di espressioni regex.

FWIW, ecco il codice della funzione:

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);
}

E questa funzione utilizza _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>";
}
    
posta Florian Margaine 02.11.2012 - 16:43
fonte

2 risposte

3

Vedi Drupal's filter_xss è abbastanza per filtrare HTML? , che ha qualche discussione sulla sicurezza di% co_de di Drupal %. Assicurati di leggere l'analisi di Mike Samuel, che identifica un numero di difetti di filter_xss() . Non so se li classificheresti come vulnerabilità, esattamente, ma sono difetti di progettazione / mancanze che potrebbero rendere il filter_xss() meno efficace di quanto gli sviluppatori potrebbero aspettarsi.

La documentazione dello sviluppatore per filter_xss() è terribilmente pessima.

Esiste una somma totale di due frasi: "Filtra l'HTML per impedire le vulnerabilità di cross-site-scripting (XSS)." e "Usa check_markup o filter_xss per il markup contenente testo.". Quando la documentazione non spiega come utilizzare correttamente filter_xss() , non dovresti sorprendervi se gli sviluppatori non riescono a utilizzarlo correttamente. Ciò potrebbe portare a vulnerabilità, ad es., Del tipo che Rook identifica.

(Drupal ha anche un documento intitolato Gestisci il testo in modo sicuro , ma non menziona nemmeno filter_xss() . )

Suggerirei inoltre che chiunque chiami filter_xss() si assicuri di non includere filter_xss() nell'elenco dei tag consentiti. Il codice per la validazione dei commenti (che è abilitato se si aggiunge !-- alla lista dei tag permessi) mi sembra super-abbozzato: non fa nulla per convalidare il contenuto del commento, che intuitivamente sembra possa " forse è sicuro.

    
risposta data 02.11.2012 - 20:53
fonte
0

XSS è un problema di output, non esiste una funzione magica che possa prevenire tutte le vulnerabilità XSS. La radice di tutte le vulnerabilità sta usando la funzionalità in un modo che non è mai stata concepita.

Questi due sono piuttosto ovvi:

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)

Sembra anche che tu possa iniettare gestori di eventi: ' onclick=alert(1) ' , anche se non l'ho provato ...

    
risposta data 02.11.2012 - 20:13
fonte

Leggi altre domande sui tag