2009-07-20 17 views
7

Estoy trabajando con un equipo de desarrolladores en un sitio web. El sitio web usará clases. Estoy a cargo de crear la capa de acceso a datos para las clases. Existe un entendimiento de que se escapará toda la entrada del usuario al momento de la recuperación (desde la publicación o obtención). Teniendo poco control sobre el nivel de entrada (a menos que revise personalmente el código de todos), pensé que sería genial lanzar escapando también (justo antes de que llegue a la base de datos). El problema es que no sé cómo usar mysql_real_escape_string sin agregar aún más barras inclinadas.Escapar solo lo necesario, ¿es eso posible?

Dado que la entrada del usuario puede contener una barra oblicua, no puedo asegurarme de que tenga barras. Es posible que pueda verificar todas las cosas que necesitan escaparse y asegurarme de que tengan una barra delante de ellos, pero esa no parece la mejor manera de hacerlo.

¿Alguna sugerencia?

Respuesta

7

¿Ha considerado no escapando de los datos hasta que llegue a la capa de acceso a datos? Me pregunto, porque su son también algunas precauciones con el enfoque de su equipo está tomando:

  • Si se necesita mostrar los datos del formulario para el usuario (por ejemplo, para volver a mostrar el formulario con un mensaje de error debido a que algunos de validación no), se necesita escaparse de los datos (porque ' no es especial para HTML) y luego volver a escaparse de los datos (porque < es especial). Si necesita mostrar datos de formulario al usuario extraído de la base de datos, no debe hacer ese paso de escape (porque lo hizo la base de datos, cuando se guardaron los datos), pero aún debe hacer el escape de HTML paso. Si comete un error y realiza un procedimiento incorrecto, corrompe los datos o, peor aún, presenta problemas de seguridad.
  • Puede resolver los diferentes formatos de problemas de diferentes fuentes al decidir que todos los datos que se pasen alrededor de su aplicación serán escapados. Por lo tanto, su capa de acceso a datos volverá a escapar de los datos al obtenerlos de la base de datos. Pero, como diferentes partes de la aplicación necesitan escapes diferentes (o completamente), esto lleva rápidamente a muchas tonterías de escape/escape. Toma los datos de la base de datos, escápalos, descárgalos, escápalos en HTML y envíalos.
  • Su código de manejo de formulario de front-end debe tener un conocimiento profundo de su base de datos. Por ejemplo, ¿qué significa \' para su base de datos? ¿Cómo se pueden escapar ' o \, si es que se puede? Si alguna vez cambia su motor de base de datos, o incluso cambia su configuración, estos pueden cambiar. Y luego tiene un montón de código de escape/de-escape para encontrar. Perder un solo escape/escape puede conducir a la inyección de SQL.
  • Como alternativa, puede sacar ese conocimiento de la base de datos del código del front-end haciendo que la capa de la base de datos realice un ciclo de escape/escape para convertir la secuencia de escape estándar de su aplicación a la de su base de datos. ¡Pero esto parece bastante tonto!

Hay otra manera: dejar que cualquiera de las capas que necesita los datos escapados lo escape. Los datos siempre se pasan entre las capas en forma cruda, no escamada. Entonces, su capa de acceso a datos hace que toda la base de datos escape. Su código de salida HTML hace que todo el HTML escape. Cuando decide que desea generar archivos PDF, su código PDF hace que todo PDF escape.

  • Ahora, cuando se forma la salida, es claro qué hacer: siempre HTML escapan los datos. No importa de dónde vino. Nunca corras un escape.
  • Ahora no hay tonterías de escape/escape, ya que todo se pasa sin procesar. Solo se escapa cuando sea necesario.
  • Su código front-end no se preocupa por la implementación de la capa de acceso a datos. La capa de acceso a datos almacena y devuelve cualquier cadena arbitraria.
  • Usted tiene solo un lugar para buscar en su aplicación para asegurarse de que no tenga problemas de inyección de SQL.
  • Puede utilizar fácilmente las características del controlador de la base de datos, como los marcadores de posición. Entonces, ni siquiera su capa de acceso a datos debe conocer los requisitos de escape de cada base de datos; el controlador de la base de datos lo maneja.
7

No hay manera de que pueda agregar una decisión automática de escape o no si no sabe si la entrada se ha escapado. Puede intentar analizarlo, pero nunca será bueno y encontrará pares dobles de barras diagonales, etc.

Tome la decisión una vez que los datos enviados a su capa de acceso deben estar limpios y manejar el escape en un solo lugar. Si lo hace, los otros desarrolladores no tendrán que preocuparse (probablemente no lo quieran) y será mucho más fácil moverse a otra base de datos en el futuro. También le dará la libertad de pasar a las declaraciones preparadas en cualquier momento.

Editar: Olvidaste esto:

tener poco control sobre el nivel de entrada (a menos que personalmente revisión de código de todos)

creo que vale la pena tenerlos descubrirlo ellos mismos si simplemente deja en claro que escapar es algo que pertenece a la capa de la base de datos y no debería hacerse en ningún otro lado.

+3

+1 para "manejar el escape en un solo lugar". Desearía poder darte +5 por esto ;-) – Treb

0

Si estuviera en su posición, no sería tan flojo como para no revisar el código de todos. Incluso si no está revisando el escape de la entrada del usuario, aún puede querer ver si su código se realiza de manera eficiente. O tal vez, no es usted quien realiza la revisión, pero alguien tiene que hacerlo.

He experimentado una configuración casi similar no hace mucho tiempo donde dividimos las tareas por capas. Uno trabajó en el modelo, trabajé en el controlador y el otro trabajó en las vistas. Debido a que confiamos tanto en todos que el código de todos los demás funciona de la manera que esperábamos que funcionara, no nos molestamos en revisar el código del otro hasta el momento en que necesitábamos fusionarlos. Lo que sucedió fue que descubrimos un código ineficiente en el modelo al final del desarrollo. Y no solo fue ineficiente, ¡no funcionó! Debido a eso, tuvimos que reacondicionar grandes cantidades del código que nos costó más tiempo.

Sugiero que cree un documento de especificaciones de requisitos técnicos en el que se especifiquen las entradas aceptables de los usuarios. Este documento debe ser seguido por los que codificarán la parte que aceptará la entrada del usuario. Mejor aún, cree pruebas unitarias para ver si se siguen estrictamente esos requisitos, de modo que no tenga que preocuparse si los datos que le van a pasar no son válidos.

Otra cosa ... ya que estás usando PHP, ¿por qué no utilizar un buen framework? La mayoría de los marcos disponibles vienen con su propio DAL en el que ya no tiene que preocuparse mucho por escapar de la entrada de la base de datos (bueno, no tanto). Los marcos deberían hacerlo por usted.

Además, es posible que desee consultar "declaraciones preparadas".

Cuestiones relacionadas