¿Estoy previniendo correctamente XSS en PHP? [duplicar]

0

Mientras construía mi sitio web, armé una clase de seguridad que incluye dos funciones, una toma la entrada y la devuelve como una cadena que pasa por htmlentities function de PHP. El otro elimina las etiquetas XSS comunes, etc. Hasta ahora he estado usando ambas en conjunto al enviar los datos ingresados por el usuario al navegador Solo para dejarlo claro; Mi contexto es HTML, no pdf, xls, etc. (etiquetas de cadena I.E. luego htmlentities y luego echo). Mi pregunta es, ¿debo usar entidades HTML por sí mismas, es suficiente?

a continuación están las dos funciones que describí para referencia:

    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');
    }
    
pregunta sousdev 14.11.2013 - 13:45
fuente

1 respuesta

2

Sin descifrar tus expresiones regulares, te digo que estás haciendo esto mal, aquí hay algunos ejemplos de por qué:

  • Las entidades y atributos HTML están cambiando todo el tiempo, realmente no se pueden incluir en la lista negra.
  • Puedes filtrar la entrada para evitar las etiquetas HTML por completo. De esta manera, seguirá siendo vulnerable si, por ejemplo, coloca los datos filtrados dentro de las etiquetas de estilo o script.
  • Es posible que deba aceptar los datos proporcionados por el usuario con formato (piense en FCKEditor), y eliminaría el formato con sus filtros. En este punto, básicamente tendría que lidiar con XML que posiblemente no pueda analizar con expresiones regulares.
  • La base de datos de back-end u otros componentes del sistema pueden formatear la entrada ya filtrada de manera que se esté volviendo dañina en la salida (consulte la omisión del filtro ValidateRequest ).
  • También, ¡buena suerte con la depuración de tu código!

Recomendaría no reinventar la rueda y separar sus vistas de sus controladores. Usar algún motor / marco de plantillas que codifique en HTML todos los parámetros de la plantilla antes de la salida ayudará mucho. Si necesita mostrar contenido formateado, puede usar HTMLPurifier .

    
respondido por el buherator 14.11.2013 - 14:13
fuente

Lea otras preguntas en las etiquetas