2008-08-09 21 views
10

Al escribir código, usted conscientemente programa a la defensiva para garantizar la alta calidad del programa y para evitar la posibilidad de que su código sea explotado maliciosamente, p. a través de exploits de desbordamiento de búfer o inyección de código?Programación defensiva

¿Cuál es el nivel de calidad "mínimo" que siempre se aplicará a su código?

Respuesta

12

En mi trabajo, nuestro código tiene que ser de alta calidad.
Por lo tanto, nos centramos en dos cosas principales: revisa

  1. Prueba
  2. Código

Aquellos llevar a casa el dinero.

0

Siempre trabajo para evitar cosas como ataques de inyección. Sin embargo, cuando trabajas en un sitio interno de intranet, la mayoría de las características de seguridad parecen un esfuerzo desperdiciado. Todavía los hago, tal vez simplemente no tan bien.

0

Bueno, hay un cierto conjunto de mejores prácticas para la seguridad. Como mínimo, para las aplicaciones de bases de datos, debe tener cuidado con la inyección SQL.

Otras cosas como contraseñas hash, encriptación de cadenas de conexión, etc. también son un estándar.

A partir de ahora, depende de la aplicación real.

Afortunadamente, si trabaja con frameworks como .Net, mucha protección de seguridad viene incorporada.

0

Siempre tienes que programar a la defensiva, diría incluso para las aplicaciones internas, simplemente porque los usuarios podrían simplemente por pura suerte escribir algo que rompa tu aplicación. De acuerdo, probablemente no tengas que preocuparte por tratar de estafarte sin dinero, pero aún así. Siempre programe a la defensiva y suponga que la aplicación fallará.

4

Similar a abyx, en el equipo en el que estoy, los desarrolladores siempre usan pruebas unitarias y revisiones de código. Además de eso, también intento asegurarme de que no incorporo código que las personas pueden usar - Tiendo a escribir código solo para el conjunto básico de métodos requeridos para que el objeto en cuestión funcione como se especificó ' d fuera. Descubrí que la incorporación de métodos que quizás nunca se utilicen, pero que proporcionan una funcionalidad, puede introducir involuntariamente un uso "clandestino" o involuntario/imprevisto en el sistema.

Es mucho más fácil volver más tarde e introducir métodos, atributos y propiedades para los que se solicitan, en lugar de anticipar algo que quizás nunca llegue.

+2

Lo que usted describe también se conoce como YAGNI - http://en.wikipedia.org/wiki/YAGNI – abyx

0

Usar el desarrollo controlado por prueba ciertamente ayuda. Escribe un componente individual a la vez y luego enumera todos los posibles casos de entradas (mediante pruebas) antes de escribir el código. Esto garantiza que haya cubierto todas las bases y no haya escrito ningún código fresco que nadie usará pero podría romperse.

Aunque no hago nada formal, por lo general pasar algún tiempo buscando en cada clase y asegurar que:

  1. si se encuentran en un estado válido que se mantengan en un estado válido
  2. hay no hay manera de construirlos en un estado no válido
  3. en circunstancias excepcionales, se producirá un error con tanta gracia como sea posible (esto es con frecuencia una limpieza y tirar)
0

depende.

Si realmente estoy pirateando algo para mi propio uso, entonces escribiré el mejor código en el que no tenga que pensar. Deje que el compilador sea mi amigo para las advertencias, etc., pero no crearé automáticamente tipos por el placer de hacerlo.

Cuanto más probable sea que se use el código, incluso ocasionalmente, elevo el nivel de los controles.

  • números mágicos mínimos
  • mejor los nombres de variables
  • comprueban completamente & gama/cadena definida longitudes
  • la programación por las afirmaciones del contrato
  • comprobaciones de valor nulo
  • excepciones (dependiendo de contexto del código)
  • comentarios explicativos básicos
  • documentación de uso accesible (si Perl, etc.)
0

me quedo con una definición diferente de programación defensiva, como el que ha defendido por Effective Java por Josh Bloch. En el libro, habla sobre cómo manejar objetos mutables que las personas que llaman pasan a su código (por ejemplo, en setters) y objetos mutables que le pasa a las personas que llaman (por ejemplo, en getters).

  • Para instaladores, asegúrese de clonar cualquier objeto mutable y almacene el clon. De esta forma, las personas que llaman no pueden cambiar el objeto transferido después del hecho para romper las invariantes de su programa.
  • Para getters, devuelva una vista inmutable de sus datos internos, si la interfaz lo permite; o bien devuelve un clon de los datos internos.
  • Al llamar devoluciones de llamada proporcionadas por el usuario con datos internos, envíe una vista inmutable o clonar, según corresponda, a menos que tenga la intención de que la devolución de llamada altere los datos, en cuyo caso debe validarlo después de los hechos.

El mensaje para llevar a casa es asegurarse de que ningún código externo pueda contener un alias de cualquier objeto mutable que use internamente, para que pueda mantener sus invariantes.

1

Recomiendo estar a la defensiva para los datos que entran en un "componente" o marco. Dentro de un "componente" o marco uno debería pensar que los datos son "correctos".

Pensando así. Depende de quien llama que proporcione los parámetros correctos; de lo contrario, TODAS las funciones y métodos deberán verificar cada parámetro recibido.Pero si el cheque solo se realiza para la persona que llama, el cheque solo se necesita una vez. Por lo tanto, un parámetro debe ser "correcto" y, por lo tanto, puede pasarse a niveles inferiores.

  1. Siempre revise los datos de fuentes externas, usuarios, etc.
  2. un "componente" o marco deben comprobar siempre incomming llamadas.

Si hay un error y se usa un valor incorrecto en una llamada. ¿Qué es realmente lo correcto? Uno solo tiene una indicación de que los "datos" en los que el programa está trabajando son incorrectos y algunos como ASSERTS, pero otros quieren usar informes de errores avanzados y posibles errores de recuperación. En cualquier caso, los datos se encuentran defectuosos y en algunos casos es bueno continuar trabajando en ellos. (tenga en cuenta que es bueno si los servidores no mueren al menos)

Una imagen enviada desde un satélite podría ser un caso para intentar la recuperación avanzada de errores en ... una imagen descargada de Internet para poner un icono de error. ..

0

soy muy buena parte de la opinión de que la programación correcta protegerá contra estos riesgos. Cosas como evitar las funciones en desuso, que (al menos en las bibliotecas de Microsoft C++) son obsoletas debido a las vulnerabilidades de seguridad y validar todo lo que cruza un límite externo.

Las funciones que se llaman únicamente desde el código no deberían requerir la validación de parámetros excesiva ya que el control de la persona que llama, es decir, sin límite externo es atravesado. Las funciones llamadas por el código de otras personas deben asumir que los parámetros entrantes serán inválidos y/o maliciosos en algún momento.

Mi aproximación al tratamiento de funciones expuesta es simplemente chocar a cabo, con un mensaje muy útil si es posible. Si la persona que llama no puede obtener los parámetros correctos, entonces el problema está en su código y deberían solucionarlo, no usted. (Obviamente usted ha proporcionado documentación de su función, ya que está expuesto.)

Inyección de código es sólo un problema si la aplicación es capaz de elevar el usuario actual. Si un proceso puede inyectar código en su aplicación, podría escribir fácilmente el código en la memoria y ejecutarlo de todos modos. Sin poder obtener acceso completo al código del sistema, los ataques de inyección no tienen sentido. (Esta es la razón por la cual las aplicaciones utilizadas por los administradores no deberían ser escribibles por usuarios menores.)

0

En mi experiencia, el hecho de emplear positivamente la programación defensiva no significa necesariamente que termine mejorando la calidad de su código. No me malinterpreten, necesitas un programa defensivo para detectar los tipos de problemas que los usuarios encontrarán, a los usuarios no les gusta cuando tu programa falla, pero es poco probable que el código sea más fácil de mantener. prueba, etc.

Hace varios años, tomamos la política de usar aserciones en todos los niveles de nuestro software y esto - junto con pruebas unitarias, revisiones de códigos, etc. además de nuestras suites de prueba de aplicaciones existentes - tuvo un efecto significativo y positivo efecto en la calidad de nuestro código.

1

recomiendo personas escriben código que es fascista en el entorno de desarrollo y benévolo en la producción.

Durante el desarrollo que se desea capturar datos malos/lógica/código tan pronto como sea posible para evitar problemas, ya sea que pasen desapercibidas o que resultan en problemas posteriores en que la causa raíz es difícil de rastrear.

En producción, maneje los problemas lo más elegantemente posible. Si algo realmente es un error no recuperable, trátelo y presente esa información al usuario.

Como ejemplo, aquí está nuestro código para normalizar un vector. Si le das datos malos en desarrollo, gritará, en producción devuelve un valor de seguridad.

inline const Vector3 Normalize(Vector3arg vec) 
{ 
    const float len = Length(vec); 
    ASSERTMSG(len > 0.0f "Invalid Normalization"); 
    return len == 0.0f ? vec : vec/len; 
} 
+0

Utilizamos una forma similar de "aumentar" la detección de problemas en el código heredado. La macro es fácil de agregar, en su único efecto es un cuadro de mensaje de depuración durante la prueba. Esta no es una solución milagrosa, pero es mejor que el "retorno FALSO"; nadie revisa – paercebal

0

Java, firmado JAR y JAAS.

Java para evitar el desbordamiento de búfer y los exploits de puntero/stack whacking.

No utilice JNI. (Java Native Interface) lo expone a bibliotecas DLL/Shared.

Los JAR firmados para detener la carga de clases son un problema de seguridad.

JAAS puede permitir que su aplicación no confíe en nadie, incluso en sí misma.

J2EE tiene (admitidamente limitado) soporte incorporado para la seguridad basada en roles.

Hay algo de sobrecarga para algo de esto, pero los agujeros de seguridad desaparecen.

0

Respuesta simple: Depende. Demasiada codificación defensiva can causan problemas de rendimiento.

Cuestiones relacionadas