Sto evitando correttamente XSS in PHP? [duplicare]

0

Durante la creazione del mio sito web ho messo insieme una classe di sicurezza che include due funzioni, una prende l'input e la restituisce come una stringa passata attraverso htmlentities function di PHP. L'altro rimuove i tag XSS comuni ecc., Fino ad ora ho usato entrambi in congiunzione quando si inviavano i dati immessi dall'utente al browser Solo per chiarire; il mio contesto è HTML, non pdf, xls ecc. (tag delle stringhe I.E. quindi htmlentities, quindi echo). La mia domanda è, dovrei semplicemente usare le entità HTML da sola, è sufficiente?

di seguito sono le due funzioni che ho descritto come riferimento:

    public function SanitiseXSS($data)
    {
        // If its empty there is no point cleaning it 
        if(empty($data))
        {
            return $data;
        }

        // Recursive loop for arrays
        if(is_array($data))
        {
            foreach($data as $key => $value)
            {
                $data[$key] = $this->SanitiseXSS($data);
            }

            return $data;
        }

        // Fix &entity\n;
        $data = str_replace(array('&','<','>'), array('&','<','>'), $data);
        $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
        $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
        $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');

        // Remove any attribute starting with "on" or xmlns
        $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);

        // Remove javascript: and vbscript: protocols
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*(['\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);

        // Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*['\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*['\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*['\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);

        // Remove namespaced elements (we do not need them)
        $data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);

        do
        {
            // Remove really unwanted tags
            $old_data = $data;
            $data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
        }
        while ($old_data !== $data);

        return $data;
    }

    public function EscapeOutput($input)
    {
        return htmlentities($input, ENT_QUOTES, 'UTF-8');
    }
    
posta sousdev 14.11.2013 - 13:45
fonte

1 risposta

2

Senza decifrare le tue espressioni regolari ti dico che stai sbagliando, ecco alcuni esempi del perché:

  • Le entità HTML e gli attributi cambiano continuamente, non è possibile inserire nella lista nera le cose.
  • Puoi filtrare l'input per evitare del tutto i tag HTML. In questo modo sarai comunque vulnerabile se metti i dati filtrati all'interno di script o tag di stile, ad esempio.
  • Potrebbe essere necessario accettare i dati forniti dall'utente formattati (si pensi a FCKEditor), e si ucciderà la formattazione con i filtri. A questo punto dovresti fondamentalmente avere a che fare con XML che non puoi assolutamente analizzare con espressioni regolari.
  • Il database di back-end o altri componenti di sistema possono formattare l'input già filtrato in modo tale da risultare dannoso per l'output (vedere l'esclusione del filtro ValidateRequest ).
  • Inoltre, buona fortuna con il debug del tuo codice!

Raccomando di non reinventare la ruota e separare le viste dai controller. L'utilizzo di alcuni template engine / framework che HTML-codifica tutti i parametri del template prima dell'output aiuterà molto. Se hai bisogno di visualizzare contenuti formattati, puoi utilizzare HTMLPurifier .

    
risposta data 14.11.2013 - 14:13
fonte

Leggi altre domande sui tag