xss - sheet - sql injection example
¿Cuándo es mejor higienizar la entrada del usuario? (14)
El usuario es igual a no confiable. Nunca confíes en la entrada de usuarios no confiables. Lo entiendo. Sin embargo, me pregunto cuándo es el mejor momento para desinfectar la información. Por ejemplo, ¿almacena ciegamente la entrada del usuario y luego la desinfecta siempre que se accede / usa, o desinfecta la entrada inmediatamente y luego almacena esta versión "limpia"? Tal vez también hay otros enfoques que no he tenido en cuenta además de estos. Me estoy inclinando más hacia el primer método, porque cualquier información que provenga de la entrada del usuario debe abordarse con cautela, donde los datos "limpios" pueden ser aún peligrosos, sin saberlo o accidentalmente. De cualquier manera, ¿qué método piensa la gente que es mejor y por qué?
¡Los usuarios son malvados!
Bueno, quizás no siempre, pero mi enfoque es sanar de inmediato para garantizar que nada arriesgado llegue a mi back-end.
El beneficio adicional es que puede proporcionar retroalimentación al usuario si desinfecta en el punto de entrada.
Encuentro que limpiarlo inmediatamente tiene dos ventajas. Uno, puede validar en su contra y proporcionar comentarios al usuario. Dos, no tienes que preocuparte por consumir la información en otros lugares.
La entrada del usuario siempre debe tratarse como maliciosa antes de bajarla a las capas inferiores de su aplicación. Siempre maneje la entrada de desinfección tan pronto como sea posible y, por alguna razón, no debe guardarse en su base de datos antes de buscar intenciones maliciosas.
Limpie los datos antes de almacenarlos. En general, no debe realizar CUALQUIER acción SQL sin antes limpiar la entrada. No desea someterse a un ataque de inyección SQL.
De alguna manera sigo estas reglas básicas.
- Solo modifique las acciones SQL, como INSERT, UPDATE, DELETE a través de POST. Nunca OBTENGA.
- Escape todo
- Si espera que la entrada del usuario sea algo, asegúrese de verificar que sea ese algo. Por ejemplo, está solicitando un número, luego asegúrese de que sea un número. Usa validaciones.
- Usa filtros Limpie los caracteres no deseados.
Lo más importante es ser siempre coherente cuando escapas. La desinfección doble accidental es coja y no desinfectar es peligroso.
Para SQL, solo asegúrese de que su biblioteca de acceso a la base de datos sea compatible con las variables de vinculación que escapan automáticamente los valores. Cualquiera que concatena manualmente la entrada del usuario en cadenas de SQL debería saberlo mejor.
Para HTML, prefiero escapar en el último momento posible. Si destruyes las entradas de los usuarios, nunca podrás recuperarlas, y si se equivocan, pueden editarlas y corregirlas más tarde. Si destruyes su entrada original, se va para siempre.
Lo temprano es bueno, definitivamente antes de intentar analizarlo. Todo lo que va a salir más tarde, o especialmente pasar a otros componentes (es decir, shell, SQL, etc.) debe ser desinfectado.
Pero no se exceda: por ejemplo, las contraseñas son hash antes de almacenarlas (¿verdad?). Las funciones hash pueden aceptar datos binarios arbitrarios. Y nunca imprimirás una contraseña (¿verdad?). Así que no analice las contraseñas, ni las desinfecte.
Además, asegúrese de que está desinfectando desde un proceso confiable: JavaScript / cualquier cosa del lado del cliente es peor que inútil seguridad / integridad. (Podría proporcionar una mejor experiencia de usuario para fallar temprano, sin embargo, solo hazlo en ambos lugares).
Me gusta desinfectarlo lo antes posible, lo que significa que la desinfección ocurre cuando el usuario intenta ingresar datos no válidos. Si hay un TextBox para su edad, y escriben cualquier otro que sea un número, no dejo que la pulsación de la letra vaya.
Entonces, sea lo que sea que lea los datos (a menudo un servidor), hago una verificación de cordura cuando leo los datos, solo para asegurarme de que nada se desliza debido a un usuario más determinado (como editar manualmente archivos o incluso modificar paquetes). !
Editar: en general, desinfecte temprano y desinfecte cada vez que haya perdido de vista los datos, incluso por un segundo (por ejemplo, Guardar archivo -> Abrir archivo)
Perl tiene una opción de contaminación que considera que toda la entrada del usuario está "contaminada" hasta que se haya verificado con una expresión regular. Los datos contaminados pueden usarse y transmitirse, pero contaminan cualquier dato con el que entre en contacto hasta que no esté contaminado. Por ejemplo, si la entrada del usuario se agrega a otra cadena, la nueva cadena también está contaminada. Básicamente, cualquier expresión que contenga valores contaminados emitirá un resultado contaminado.
Los datos contaminados se pueden lanzar a voluntad (los datos contaminados a medida que avanzan), pero tan pronto como es utilizado por un comando que tiene efecto en el mundo exterior, el script de Perl falla. Entonces, si uso datos corruptos para crear un archivo, construir un comando de shell, cambiar el directorio de trabajo, etc., Perl fallará con un error de seguridad.
No conozco otro idioma que tenga algo así como "contaminación", pero su uso ha sido muy revelador. Es sorprendente la rapidez con la que se difunden los datos contaminados si no se soluciona de inmediato. Las cosas que son naturales y normales para un programador, como establecer una variable según los datos del usuario o abrir un archivo, parecen peligrosas y arriesgadas con la contaminación activada. Entonces, la mejor estrategia para lograr que se hagan las cosas es deshacerse tan pronto como obtengas datos del exterior.
Y sospecho que esa es la mejor manera en otros idiomas también: valide los datos del usuario de inmediato para que los errores y agujeros de seguridad no se puedan propagar demasiado. Además, debería ser más fácil auditar el código para los agujeros de seguridad si los agujeros potenciales están en un solo lugar. Y nunca se puede predecir qué datos se usarán para qué propósito más adelante.
Sano mis datos justo antes de procesarlos. Es posible que necesite tomar los campos de Nombre y Apellido y concatenarlos en un tercer campo que se inserta en la base de datos. Voy a desinfectar la entrada antes de hacer la concatenación para no obtener ningún tipo de procesamiento o errores de inserción. Cuanto antes mejor. Incluso el uso de Javascript en el front-end (en una configuración web) es ideal porque eso ocurrirá sin que al principio lleguen datos al servidor.
La parte más aterradora es que incluso podría comenzar a desinfectar los datos que salen de su base de datos. El reciente aumento de los ataques de inyección de ASPRox SQL que han estado dando vueltas es doblemente letal porque infectará todas las tablas de la base de datos en una base de datos dada. Si su base de datos está alojada en algún lugar donde hay varias cuentas alojadas en la misma base de datos, sus datos se corrompen debido a un error ajeno, pero ahora se ha unido a las filas de alojar malware a sus visitantes debido a que no tiene una falla inicial. .
Claro que esto hace mucho trabajo por adelantado, pero si la información es crítica, entonces es una inversión digna.
Supongamos que todos los usuarios son maliciosos. Desinfecte toda la entrada tan pronto como sea posible. Punto final.
Depende del tipo de desinfección que esté haciendo.
Para proteger contra la inyección SQL, no haga nada con los datos en sí. Simplemente use declaraciones preparadas, y de esa manera, no tiene que preocuparse por jugar con los datos que el usuario ingresó, y que esto afecte negativamente su lógica. Tienes que desinfectar un poco, para asegurarte de que los números sean números y las fechas sean fechas, ya que todo es una cadena como viene de la solicitud, pero no intentes hacer ninguna comprobación para hacer cosas como bloquear palabras clave ni nada.
Para protegerse contra ataques XSS, probablemente sería más fácil corregir los datos antes de que se almacenen. Sin embargo, como otros mencionaron, a veces es bueno tener una copia prístina de lo que el usuario ingresó, porque una vez que la cambias, se pierde para siempre. Es casi una lástima que no haya una manera infalible de garantizar que la aplicación solo eche HTML desinfectado de la misma forma en que puede asegurarse de no ser atrapado por la inyección SQL mediante el uso de consultas preparadas.
Mi opinión es que sanear la entrada del usuario tan pronto como sea posible del lado del cliente y del lado del servidor, lo estoy haciendo así
- (lado del cliente), permite al usuario ingresar solo claves específicas en el campo.
- (lado del cliente), cuando el usuario va al siguiente campo usando onblur, prueba la entrada que ingresó contra una expresión regular, y nota al usuario si algo no es bueno.
- (lado del servidor), pruebe la entrada nuevamente, si el campo debe ser INTEGER, verifique eso (en PHP puede usar is_numeric ()), si el campo tiene un formato conocido, fíjelo contra una expresión regular, todos los demás (como comentarios de texto), solo escapa de ellos. Si algo es sospechoso, detenga la ejecución del script y devuelva un aviso al usuario de que los datos que ingresó son inválidos.
Si algo realmente parece un posible ataque, el script me envía un correo electrónico y un mensaje de texto, para que pueda verificarlo y evitarlo lo antes posible, solo necesito verificar el registro donde estoy registrando todas las entradas del usuario, y los pasos que hizo el script antes de aceptar la entrada o rechazarla.
Desafortunadamente, casi ninguno de los participantes alguna vez entiende claramente de qué están hablando. Literalmente. Solo @Kibbee logró hacerlo directo.
Este tema trata sobre la desinfección. Pero la verdad es que algo así como el amplio término "sanitización de propósito general" del que todos están tan ansiosos por hablar simplemente no existe.
Hay un trillón de medios diferentes , cada uno requiere su propio formato de datos. Además, incluso un solo medio determinado requiere un formato diferente para sus partes . Digamos, el formato HTML es inútil para javascript incrustado en la página HTML. O bien, el formateo de cadenas no sirve para los números en la consulta SQL.
De hecho, una "desinfección tan temprana como sea posible", como se sugiere en la mayoría de las respuestas subidas de tono, es simplemente imposible . Como uno simplemente no puede decir en qué parte del medio o medio se usarán los datos. Diga, nos estamos preparando para defendernos de la "inyección sql", escapando de todo lo que se mueve. Pero ¡Ups! - algunos campos obligatorios no se completaron y tenemos que completar los datos en forma en lugar de en la base de datos ... con todas las barras agregadas.
Por otro lado, escapamos diligentemente a toda la "entrada del usuario" ... pero en la consulta SQL no tenemos citas, ya que es un número o identificador. Y ninguna "desinfección" alguna vez nos ayudó.
Por otro lado, está bien, hicimos nuestro mejor esfuerzo para desinfectar la "entrada del usuario" terrible, indigna de confianza y desdeñada ... pero en algún proceso interno usamos esta misma información sin ningún formato (¡ya lo hicimos lo mejor posible!) - y ¡Ups! han recibido una inyección de segundo orden en todo su esplendor.
Entonces, desde el punto de vista del uso de la vida real, la única forma adecuada sería
- formateo, no importa lo que sea "desinfección"
- justo antes de usar
- de acuerdo con ciertas reglas medianas
- e incluso siguiendo sub-reglas requeridas para las diferentes partes de este medio.
Sano mis datos de usuario al igual que Radu ...
El primer lado del cliente usa ambos regex y toma el control de la entrada de caracteres permitidos en campos de formulario dados usando javascript o jQuery vinculado a eventos, como onChange o OnBlur, que elimina cualquier entrada no permitida antes de que pueda enviarse. Sin embargo, tenga en cuenta que esto solo tiene el efecto de informar a los usuarios de que los datos también se verificarán en el servidor. Es más una advertencia que cualquier protección real.
Segundo, y rara vez veo esto hecho en estos días, que el primer cheque que se realiza en el servidor es verificar la ubicación desde donde se envía el formulario. Al permitir solo el envío de formularios desde una página que haya designado como una ubicación válida, puede eliminar el script ANTES de haber leído datos. Por supuesto, eso en sí mismo es insuficiente, ya que un buen pirata informático con su propio servidor puede "falsificar" tanto el dominio como la dirección IP para hacer que su script vea que proviene de una ubicación de formulario válida.
A continuación, y ni siquiera debería tener que decir esto, pero siempre, y me refiero a SIEMPRE , ejecutar sus scripts en modo de contaminación. Esto te obliga a no ponerte perezoso y a ser diligente con el paso número 4.
Desinfecte los datos del usuario tan pronto como sea posible utilizando expresiones regulares bien formadas apropiadas para los datos que se esperan de cualquier campo dado en el formulario. No tome atajos como el infame " cuerno mágico del unicornio " para soplar a través de sus comprobaciones de corrupción ... o puede simplemente desactivar la comprobación de manchas en primer lugar por todo lo bueno que hará por su seguridad. Es como darle un cuchillo afilado a un psicópata, llevándote la garganta y diciendo: "Realmente no me vas a lastimar con eso".
Y aquí es donde difiero más que la mayoría de los demás en este cuarto paso, ya que solo saneo los datos del usuario que voy a usar realmente de una manera que puede presentar un riesgo de seguridad, como cualquier llamada al sistema, asignaciones a otras variables, o cualquier escritura para almacenar datos. Si solo estoy usando la información ingresada por un usuario para hacer una comparación con los datos que he almacenado en el sistema (por lo tanto, sabiendo que los datos que tengo son seguros), entonces no me molesto en desinfectar los datos del usuario, ya que nunca nos irá, es una forma que se presenta como un problema de seguridad. Por ejemplo, tome una entrada de nombre de usuario como ejemplo. Utilizo el nombre de usuario ingresado por el usuario solo para verificarlo contra una coincidencia en mi base de datos, y si es verdadero, después de eso uso los datos de la base de datos para realizar todas las otras funciones que pueda solicitar en el script, sabiendo que es seguro , y nunca use los datos de los usuarios después de eso.
Por último, debe filtrar todos los intentos de autoenvío por parte de los robots en estos días, con un sistema de "autenticación humana", como Captcha. Esto es lo suficientemente importante en la actualidad que me tomé el tiempo de escribir mi propio esquema de "autenticación humana" que usa fotos y una entrada para que el "humano" ingrese lo que ven en la imagen. Hice esto porque descubrí que los sistemas de tipo Captcha realmente molestan a los usuarios (se puede decir por sus ojos entrecerrados que intentan descifrar las letras distorsionadas ... por lo general una y otra vez). Esto es especialmente importante para los scripts que usan SendMail o SMTP para correo electrónico, ya que estos son favoritos para sus hambrientos spam-bots.
Para resumir en pocas palabras, lo explicaré como lo hago con mi esposa ... tu servidor es como un club nocturno popular, y mientras más gorilas tengas, menos problemas tendrás en la discoteca. Tengo dos gorilas afuera de la puerta (validación del lado del cliente y autenticación humana), un gorila justo dentro de la puerta (verificando la ubicación válida para la presentación del formulario ... ''¿Es usted realmente el que está en esta identificación?), Y varios gorilas más cerca proximidad a la puerta (funcionamiento del modo de atenuación y uso de buenas expresiones regulares para verificar los datos del usuario).
Sé que esta es una publicación más antigua, pero la considero lo suficientemente importante para que cualquiera que la lea después de mi visita aquí se dé cuenta de que no es una " bala mágica " cuando se trata de seguridad, y lleva todo esto en conjunción uno con el otro para garantizar la seguridad de los datos proporcionados por el usuario. Solo el uso de uno o dos de estos métodos es prácticamente inútil, ya que su poder solo existe cuando todos se unen.
O en resumen, como mi mamá solía decir ... ''Mejor prevenir que lamentar''.
ACTUALIZAR:
Una cosa más que estoy haciendo en estos días es que Base64 codifique todos mis datos y luego encripte los datos de Base64 que residen en mis bases de datos SQL. Se necesita aproximadamente un tercio más de bytes totales para almacenarlo de esta manera, pero los beneficios de seguridad superan el tamaño extra de los datos, en mi opinión.