¿Existe una función de captura en algún lugar que funcione bien para desinfectar la entrada del usuario para la inyección SQL y los ataques XSS, al tiempo que permite ciertos tipos de etiquetas HTML?
php
security
xss
sql-injection
user-input
Brent
fuente
fuente
select * from users where name='$name'
, entonces no importa si usa PDO o MySQLi o MySQL. Sigues en peligro. Debe usar consultas parametrizadas o, si es necesario, usar mecanismos de escape en sus datos, pero eso es mucho menos preferible.Respuestas:
Es un error común pensar que la entrada del usuario se puede filtrar. PHP incluso tiene una "característica" (ahora obsoleta), llamada comillas mágicas , que se basa en esta idea. No tiene sentido. Olvídate de filtrar (o limpiar, o como lo llamen las personas).
Lo que debe hacer para evitar problemas es bastante simple: cada vez que inserte una cadena dentro del código extranjero, debe escapar de ella, de acuerdo con las reglas de ese idioma. Por ejemplo, si incrusta una cadena en algún SQL dirigido a MySQL, debe escapar de la cadena con la función de MySQL para este propósito (
mysqli_real_escape_string
). (O, en el caso de las bases de datos, el uso de declaraciones preparadas es un mejor enfoque, cuando sea posible).Otro ejemplo es HTML: si incrusta cadenas dentro del marcado HTML, debe escapar con
htmlspecialchars
. Esto significa que cada unoecho
oprint
declaración debe usarhtmlspecialchars
.Un tercer ejemplo podría ser los comandos de shell: si va a incrustar cadenas (como argumentos) en comandos externos y llamarlos con
exec
, entonces debe usarescapeshellcmd
yescapeshellarg
.Y así sucesivamente y así sucesivamente ...
El único caso en el que necesita filtrar datos de forma activa es si acepta entradas con formato previo. Por ejemplo, si deja que sus usuarios publiquen marcado HTML, que planea mostrar en el sitio. Sin embargo, debe ser prudente para evitar esto a toda costa, ya que no importa qué tan bien lo filtre, siempre será un agujero de seguridad potencial.
fuente
mysql_real_escape_string
está en desuso. Se considera una buena práctica hoy en día usar declaraciones preparadas para evitar la inyección de SQL. Entonces cambie a MySQLi o PDO.No intente evitar la inyección de SQL desinfectando los datos de entrada.
En cambio, no permita que se utilicen datos para crear su código SQL . Usar declaraciones preparadas (es decir, usar parámetros en una consulta de plantilla) que usa variables enlazadas. Es la única forma de garantizar la inyección SQL.
Consulte mi sitio web http://bobby-tables.com/ para obtener más información sobre cómo prevenir la inyección de SQL.
fuente
No. No puede filtrar datos genéricamente sin ningún contexto de para qué sirve. Algunas veces querrás tomar una consulta SQL como entrada y otras veces querrás tomar HTML como entrada.
Debe filtrar la entrada en una lista blanca: asegúrese de que los datos coincidan con alguna especificación de lo que espera. Luego, debe escapar antes de usarlo, dependiendo del contexto en el que lo esté usando.
El proceso de escape de datos para SQL, para evitar la inyección de SQL, es muy diferente del proceso de escape de datos para (X) HTML, para evitar XSS.
fuente
PHP tiene ahora las nuevas funciones agradables filter_input, que por ejemplo lo liberan de encontrar 'la máxima expresión regular de correo electrónico' ahora que hay un tipo FILTER_VALIDATE_EMAIL incorporado
Mi propia clase de filtro (usa JavaScript para resaltar campos defectuosos) puede iniciarse mediante una solicitud ajax o una publicación de formulario normal. (ver el ejemplo a continuación)
Por supuesto, tenga en cuenta que también debe hacer su escape de consulta sql dependiendo del tipo de db que esté usando (mysql_real_escape_string () es inútil para un servidor sql, por ejemplo). Probablemente desee manejar esto automáticamente en su capa de aplicación apropiada como un ORM. Además, como se mencionó anteriormente: para enviar a html, use las otras funciones dedicadas de php como htmlspecialchars;)
Para permitir realmente la entrada de HTML con clases o etiquetas despojadas similares, dependa de uno de los paquetes de validación xss dedicados. ¡NO ESCRIBA SUS PROPIOS REGEXOS PARA PARSE HTML!
fuente
No no hay.
En primer lugar, la inyección SQL es un problema de filtrado de entrada, y XSS es un problema de escape, por lo que ni siquiera ejecutaría estas dos operaciones al mismo tiempo en el ciclo de vida del código.
Reglas básicas de oro
mysql_real_escape_string()
)strip_tags()
para filtrar HTML no deseadohtmlspecialchars()
y tenga en cuenta los parámetros segundo y tercero aquí.fuente
Para abordar el problema de XSS, eche un vistazo a HTML Purifier . Es bastante configurable y tiene un historial decente.
En cuanto a los ataques de inyección SQL, asegúrese de verificar la entrada del usuario y luego ejecutarla a través de mysql_real_escape_string (). Sin embargo, la función no anulará todos los ataques de inyección, por lo que es importante que verifique los datos antes de descargarlos en su cadena de consulta.
Una mejor solución es usar declaraciones preparadas. La biblioteca PDO y la extensión mysqli son compatibles con estos.
fuente
PHP 5.2 introdujo la función filter_var .
Es compatible con una gran cantidad de filtros SANITIZE, VALIDATE.
http://php.net/manual/en/function.filter-var.php
fuente
Un truco que puede ayudar en las circunstancias específicas en las que tiene una página como
/mypage?id=53
y usa la identificación en una cláusula WHERE es asegurarse de que la identificación sea definitivamente un número entero, así:Pero, por supuesto, eso solo elimina un ataque específico, así que lea todas las otras respuestas. (Y sí, sé que el código anterior no es excelente, pero muestra la defensa específica).
fuente
$id = (int)$_GET['id']
y también$que = sprintf('SELECT ... WHERE id="%d"', $id)
es buenoUtilice versiones modernas de MySQL y PHP.
Establecer juego de caracteres explícitamente:
Use charsets seguros:
Usar función espacializada:
PDO :: quote () : coloca comillas alrededor de la cadena de entrada (si es necesario) y escapa caracteres especiales dentro de la cadena de entrada, utilizando un estilo de comillas apropiado para el controlador subyacente:
Declaraciones preparadas de PDO : las declaraciones preparadas de MySQLi admiten más controladores de bases de datos y parámetros con nombre:
mysql_real_escape_string[en desuso en PHP 5.5.0, eliminado en PHP 7.0.0].Verifique que la variable contenga lo que espera:
Usar función de filtro filter_var (): filtra una variable con un filtro especificado:
más filtros predefinidos
fuente
Lo que está describiendo aquí son dos cuestiones separadas:
1) Siempre se debe suponer que la entrada del usuario es mala.
Usar declaraciones preparadas, y / o filtrar con mysql_real_escape_string es definitivamente una necesidad. PHP también tiene incorporado filter_input, que es un buen lugar para comenzar.
2) Este es un tema amplio y depende del contexto de los datos que se emiten. Para HTML hay soluciones como htmlpurifier por ahí. como regla general, siempre escapa de todo lo que generes.
Ambas cuestiones son demasiado grandes para entrar en una sola publicación, pero hay muchas publicaciones que entran en más detalles:
Métodos de salida PHP
Salida PHP más segura
fuente
Si está utilizando PostgreSQL, la entrada de PHP se puede escapar con pg_escape_string ()
De la documentación ( http://php.net/manual/es/function.pg-escape-string.php ):
fuente
No hay una función catchall, porque hay múltiples preocupaciones que abordar.
Inyección SQL : en la actualidad, en general, todos los proyectos PHP deberían utilizar declaraciones preparadas a través de PHP Data Objects (PDO) como una mejor práctica, evitando un error de una cita perdida, así como una solución completa contra la inyección . También es la forma más flexible y segura de acceder a su base de datos.
Consulte el tutorial PDO (El único correcto) para obtener casi todo lo que necesita saber sobre PDO. (Un sincero agradecimiento al principal colaborador de SO, @YourCommonSense, por este gran recurso sobre el tema).
XSS - Desinfecte los datos en el camino en ...
HTML Purifier ha existido durante mucho tiempo y todavía se actualiza activamente. Puede usarlo para desinfectar entradas maliciosas, al tiempo que permite una lista blanca generosa y configurable de etiquetas. Funciona muy bien con muchos editores WYSIWYG, pero puede ser pesado para algunos casos de uso.
En otros casos, donde no queremos aceptar HTML / Javascript en absoluto, he encontrado útil esta función simple (y he pasado múltiples auditorías contra XSS):
/* Prevent XSS input */ function sanitizeXSS () { $_GET = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING); $_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING); $_REQUEST = (array)$_POST + (array)$_GET + (array)$_REQUEST; }
XSS: desinfecte los datos al salir ... a menos que garantice que los datos se desinfectaron correctamente antes de agregarlos a su base de datos, deberá desinfectarlos antes de mostrarlos a su usuario, podemos aprovechar estas útiles funciones PHP:
echo
oprint
muestre los valores proporcionados por el usuario, úselos ahtmlspecialchars
menos que los datos se hayan desinfectado de forma segura y se permita mostrar HTML.json_encode
es una forma segura de proporcionar valores proporcionados por el usuario desde PHP a Javascript¿Llama a comandos de shell externos usando
exec()
osystem()
funciones, o albacktick
operador? Si es así, además de SQL Injection y XSS, es posible que tenga una preocupación adicional para abordar, los usuarios que ejecutan comandos maliciosos en su servidor . Debe usarloescapeshellcmd
si desea escapar del comando completo Oescapeshellarg
para escapar de argumentos individuales.fuente
mb_encode_numericentity
se discute en elhtmlspecialchars
enlace en # 3 XSSLa forma más fácil de evitar errores al desinfectar la entrada y el escape de datos es usar el marco PHP como Symfony , Nette , etc. o parte de ese marco (motor de plantillas, capa de base de datos, ORM).
Templating motor como Twig o Latte tiene salida escaneada de forma predeterminada: no tiene que resolver manualmente si ha escapado adecuadamente su salida dependiendo del contexto (parte HTML o Javascript de la página web).
Framework está desinfectando automáticamente la entrada y no debe usar las variables $ _POST, $ _GET o $ _SESSION directamente, sino a través de mecanismos como enrutamiento, manejo de sesiones, etc.
Y para la capa de base de datos (modelo) hay marcos ORM como Doctrine o envoltorios alrededor de PDO como Nette Database.
Puede leer más sobre esto aquí: ¿Qué es un marco de software?
fuente
Solo quería agregar eso sobre el tema del escape de salida, si usa php DOMDocument para hacer que su salida html se escape automáticamente en el contexto correcto. Un atributo (valor = "") y el texto interno de un <span> no son iguales. Para estar seguro contra XSS, lea esto: OWASP XSS Prevention Cheat Sheet
fuente
Nunca desinfectas la entrada.
Siempre desinfectas la producción.
Las transformaciones que aplica a los datos para que sea seguro para su inclusión en una declaración SQL son completamente diferentes de las que solicita para su inclusión en HTML son completamente diferentes de las que solicita para su inclusión en Javascript son completamente diferentes de las que solicita para su inclusión en LDIF. completamente diferentes de los que aplica para la inclusión en CSS son completamente diferentes de los que aplica para la inclusión en un correo electrónico ...
De todos modos valide la entrada : decida si debe aceptarla para su posterior procesamiento o decirle al usuario que es inaceptable. Pero no aplique ningún cambio a la representación de los datos hasta que esté a punto de abandonar PHP.
Hace mucho tiempo, alguien trató de inventar un mecanismo único para todos los escapes de datos y terminamos con " magic_quotes ", que no escapó correctamente los datos para todos los objetivos de salida y resultó en una instalación diferente que requiere un código diferente para funcionar.
fuente
Nunca confíes en los datos del usuario.
La
trim()
función elimina espacios en blanco y otros caracteres predefinidos de ambos lados de una cadena.La
stripslashes()
función elimina las barras invertidasLa
htmlspecialchars()
función convierte algunos caracteres predefinidos en entidades HTML.Los caracteres predefinidos son:
fuente
clean_input
entonces? ¿Por qué querrías pelar barras?Existe la extensión de filtro ( howto-link , manual ), que funciona bastante bien con todas las variables GPC. Sin embargo, no es una cosa mágica, todavía tendrá que usarlo.
fuente