Expo Ing Software Corte 3

Descargar como docx, pdf o txt
Descargar como docx, pdf o txt
Está en la página 1de 7

Programación defensiva.

La programación defensiva podemos entenderla como una forma de programar en la que el


desarrollador anticipa los problemas que pueden surgir en el código. Gracias a esta previsión
de la que nos dota esta metodología es posible prevenir futuros fallos y, lo que es más importante,
conseguir que, si finalmente acaban apareciendo, el programa no falle estrepitosamente.

Es decir, la programación defensiva no se basa en la utopía de escribir código que nunca falle, sino
en la premisa de que cuando nuestras aplicaciones fallen (recuerda, nadie es infalible) el error
se produzca dentro de un entorno lo más controlado posible. Si la programación defensiva fuera
un dicho popular estaríamos hablando de “caer con estilo”.

Para lograrlo, el código que escribamos deberá:

- Fallar de forma segura, es decir tras el fallo no deberían quedar ficheros abiertos o bloqueados o
transacciones contra la base de datos a medio terminar.

- Fallar de forma clara, proporcionando siempre un código de error y un mensaje que explique lo
que originó el fallo de modo que detectar el fallo y solucionarlo sea mucho más sencillo. Además,
proporcionar una pila de llamadas e invocaciones siempre es una gran idea.

Por qué necesitamos la “programación defensiva”:

Como comentaba líneas antes, cuando escribimos código nadie es infalible y, de hecho, por mucho
cuidado que pongamos siempre habrá casos extremos (los conocidos casos frontera) que no
hayamos tenido en cuenta y que provocarán que nuestra aplicación falle en el futuro.

Por tanto, la programación defensiva tiene algo de pragmatismo, es decir, de ayudar a tu yo del
futuro a enfrentarse a problemas que hoy no estás viendo.

Este concepto de pragmatismo es desarrollado en el libro Pragmatic Programmer de Andrew Hunt y


viene a proponernos que siempre:

- Protejamos nuestro código de nuestros propios fallos y de todos aquellos que otros desarrolladores
puedan provocar.

- Validemos con tests el funcionamiento de nuestras aplicaciones.


- Y puesto que es imposible contemplar en los tests todos los casos posibles que pueden suceder,
controlemos el flujo de las excepciones y los códigos de error de cara a lograr esa “caída con estilo”
de la que os hablaba antes.

Algunas pautas para seguir la programación defensiva:

Ahora que ya tenemos claro lo que es la programación defensiva quiero dejaros unas pautas que os
pueden ayudar a sentiros más seguros con el código que escribáis y a seguir esta idea de “defensive
programming”.

TDD. Test driven development

Una de las metodologías que podéis comenzar a emplear desde ya en vuestros desarrollos es TDD.
Su idea subyace en escribir siempre primero los casos de prueba unitarios para a continuación
desarrollar la funcionalidad y ver si cumple las pruebas planteadas.

Por tanto, siempre tendremos una base sólida de pruebas automáticas que nos permitirán
asegurarnos de que “nada se ha roto” a medida que el tamaño de nuestra aplicación crezca o
refactoricemos la funcionalidad de los componentes. Si queréis, podéis pensar TDD como una
metodología en la que cada componente crece en dos direcciones: funcionalidad y casos de prueba,
de modo que los segundos aseguren el correcto funcionamiento del componente.

Además, seguir una buena metodología TDD también nos ayudará a conseguir diseños poco
acoplados pues nos obligaremos a aislar cada una de las funcionalidades cuando escribamos los
casos de prueba. Esto nos permitirá tener un control mucho más detallado de cada funcionalidad y, lo
que es más importante, asegurarnos de que obtenemos los resultados que esperábamos en cada
llamada.

Casos frontera

Independientemente de que sigáis la metodología TDD, es importante que revisemos siempre


los casos frontera de la funcionalidad que estéis escribiendo.

Por casos frontera entendemos aquellos casos que no están dentro de la funcionalidad normal del
componente sino a los que puede llegarse en determinadas ocasiones.

Por ejemplo, si una función espera recibir un número natural, ¿qué sucede si le enviamos un número
negativo? O si estamos trabajando con campos de texto, ¿se guardan correctamente los emojis en
base de datos para us posterior visualización?
Son este tipo de condiciones o casos a las que deberemos prestar más atención cuando realicemos
las pruebas ya que es aquí donde suceden la mayoría de los fallos. Por tanto, no os limitéis a
preparar pruebas con condiciones esperadas (algo en lo que es muy fácil caer si no somos lo
suficientemente críticos con nuestro código) sino pensad en los casos rebuscados e incluso
“malintencionados” pues es ahí donde podremos detectar los puntos débiles de nuestra aplicación.

Ponte siempre en lo peor

Otra forma de plantearte la programación defensiva es ponerte siempre en el peor caso. De este
modo siempre estarás prevenido o alerta sobre casos que a simple vista no pueden parecer tan
evidentes.

Por ejemplo, algo que me sucedió recientemente por haberme “confiado”. En el procesamiento de
una llamada POST de una API todo funcionaba de forma perfecto (y pasaba todos los tests que se
me habían ocurrido para esa funcionalidad) pero sin embargo, el caso más absurdo de todos
provocaba fallo: un cuerpo de petición vacío.

Es por eso por lo que la programación defensiva nos insta a ir siempre con todos nuestros
sentidos activos de modo que podamos anticiparnos a los futuros fallos de nuestra aplicación.
Realmente, más que una metodología de trabajo como puede ser el ya mencionada TDD es una
actitud ante la forma en que escribimos nuestro código con el objetivo de añadirle un extra de
seguridad; es por eso que me ha resultado tan interesante: basta con tan sólo cambiar el chip para
aplicarla, no se necesita ningún conocimiento especial.

Escribe código limpio

Otra de las formas en las que podemos asumir esta idea de la programación defensiva es obligarnos
a escribir código limpio y optimizado, de modo que su mantenimiento y la corrección de fallos sea
mucho más sencillo.

Algunos consejos que nos pueden ayudar a escribir código limpio son:

- Emplear patrones de diseño e intentar adoptar los principios SOLID en nuestros diseños. Los


primeros nos permitirán resolver situaciones de una forma estándar (y optimizada) con la que la
mayoría de desarrolladores ya estarán familiarizados mientras que los segundo nos ayudarán a
obtener aplicaciones con bajo acoplamiento y mucho más fáciles de extender y mantener.

- Familiarízate con el lenguaje de programación que estés empleando, no te quedes sólo en la


superficie. Tómate tu tiempo en leer código de otros desarrolladores, artículos y publicaciones donde
se emplee tu lenguaje favorito y descubre nuevas formas de hacer las cosas y todas las herramientas
de las que dispones. Tanto Javascript como PHP están constantemente añadiendo nueva
funcionalidad y recursos sintácticos para simplificar el código, por lo que no te quedes atrás.
- Nombra bien los elementos. No hay nada como seguir una buena metodología de nombres para
variables, funciones y clases a la hora de mantener el código. Si una función envía un email nómbrala
apropiadamente y no recurras a nombres cortos para los elementos pensando que son más
elegantes. A la larga agradecerás haber premiado que sean más descriptivos que cortos.

- No confíes en nada ni des nada por supuesto. Muchos de los errores que suceden en el futuro se
deben a dar por supuestos elementos que dependen de terceros por lo que no asumas que siempre
serán correctos. Mejor prepara tu código ante posibles casos en los que no recibas lo que esperabas.
Esto suele ser muy habitual en el tratamiento de datos introducidos por usuarios o en ficheros de
inicialización, donde cometer fallos suele ser bastante habitual.

- ¡DRY! Es decir, Don’t repeat your self. Evita duplicar funcionalidad por distintas partes del
programa. Aíslala y agrúpala en un componente que puedas probar y que te permita realizar
modificaciones en un único archivo sin tener que realizar el mismo cambio múltiples veces.
Además, familiarízate con los sistemas de caché que tienes a tu disposición de cara a evitar
calcular el mismo dato una y otra vez penalizando el rendimiento de la aplicación.

- Loggea los errores. Otro de los elementos que nos ayudarán a resolver fallos futuros
es loggear aquellas partes de nuestro programa que estén más propensas a fallar, de modo que,
cuando finalmente se produzca un error podamos recorrer la traza de lo que sucedió y resolverlo más
rápidamente.

Intro programación segura:


Escribir código es una obra y un arte, lo que significa que siempre hay un margen de error. Todos
somos humanos y cometer errores es parte del proceso. Sin embargo, aunque los errores pueden
servir como oportunidades de aprendizaje, siempre existe la posibilidad de que alguien los explote
con propósitos nefastos.

Los ciberdelincuentes se aprovechan de los errores, errores y cualquier error que puedan
encontrar. De hecho, a menudo lanzan ataques con el único propósito de evaluar su código y
encontrar vulnerabilidades. Una vez que encuentran la vulnerabilidad que se adapta a sus
propósitos, no se sabe qué tipo de caos lloverá sobre sus aplicaciones, repositorios, dispositivos y
red conectada.

Como resultado de una brecha de seguridad, puede perder sus datos y sufrir daños financieros y de
reputación. Esto es cierto ya sea que venda su código, venda software personalizado o mantenga
una red. Puede evitar muchos problemas de seguridad implementando las siguientes mejores
prácticas para la programación segura.

¿Qué es la programación segura?


El término programación segura se refiere a un conjunto de estándares y pautas para su uso durante
el desarrollo de software. El objetivo de la programación segura es hacer que el código sea lo más
seguro, estable y estable posible. Es por eso que se deben implementar prácticas de programación
seguras en todas las etapas del proceso de desarrollo.

Las organizaciones y los profesionales a menudo definen la programación segura de manera


diferente. Puede ser parte de la política de la organización o establecerse particularmente para un
proyecto específico con necesidades especiales de seguridad. También debe asegurarse de que sus
pautas de programación segura incluyan privilegios y roles.

Puede utilizar estándares de programación pública segura tal cual o como plantilla al redactar su
política. Estos estándares a menudo son creados por una comunidad de desarrolladores y
profesionales de la seguridad cibernética que son expertos en sus respectivos campos.

Un buen recurso para la programación segura es el sitio web propiedad y mantenido por Open Web
Application Security Project ( OWASP ). El sitio web ofrece recursos educativos gratuitos para la
seguridad del software, así como un foro para la comunidad OWASP. Puede utilizar OWASP como
una referencia confiable para estándares de programación seguros.

Ejemplos de vulnerabilidades de software:

Desbordamiento de búfer

Cuando su código usa un búfer de longitud fija y la aplicación intenta almacenar datos que tienen
una longitud mayor, se produce un desbordamiento de búfer . Como resultado, los datos se pueden
sobrescribir. Esta es una vulnerabilidad de seguridad que puede hacer que el programa se anule de
forma anormal (error de segmentación). La programación segura puede evitar el riesgo de
desbordamiento de búfer mediante el uso de asignación de memoria dinámica.

Desbordamiento de enteros

Esta vulnerabilidad de seguridad ocurre cuando el resultado de una operación aritmética es un


número entero que es demasiado grande para ser representado dentro del tipo de variable
disponible. Se almacenará un valor numérico incorrecto, lo que provocará graves errores de
software. Para asegurar su código, verifique si hay desbordamiento de enteros. Esto evitará errores
de software y exploits que pueden introducirse por desbordamiento de enteros.

Ataque de cadena de formato

El ataque de cadena de formato es una función que realiza el formateo con posibles vulnerabilidades
de seguridad. Por ejemplo, una cadena de entrada específica formateada por printf en C, puede
provocar un bloqueo del programa. Un atacante puede utilizarlo para sabotear su aplicación. Puede
evitarlo bloqueando las cadenas de entrada maliciosas.
8 mejores prácticas para la programación segura

1. Definición de requisitos de seguridad

Debe definir los requisitos de seguridad en las primeras etapas de su proyecto. Las pautas de
programación de seguridad deben establecerse de acuerdo con los requisitos de seguridad
predefinidos y las especificaciones del software. Hacer esto al principio puede ayudarlo a asegurarse
de que su código cumpla con todos los requisitos.

2. Simular amenazas

Cuando planifique su proyecto, cree un modelo que simule todas las amenazas conocidas en un
entorno potencial. Este modelo debe indicar cuáles son los riesgos potenciales y qué estrategia debe
usarse para proteger su código de ellos.

3. Utilice un estándar de programación seguro

De acuerdo con los lenguajes de programación que esté utilizando y el entorno en el que se ejecutan
sus aplicaciones, desarrolle un estándar de programación seguro para sus equipos de
desarrollo. Este estándar le servirá como política durante la fase de desarrollo y, posteriormente, si
está a cargo del mantenimiento. También puede crear una plantilla estándar y revisarla según sea
necesario.

4. Validación de entrada

Una de las principales fuentes de vulnerabilidades de seguridad son los datos externos, que se
utilizan como entrada para su código. Todos los tipos de entrada deben validarse y bloquearse para
garantizar que no ingresen datos sospechosos en su base de código. Esto incluye archivos de
entrada que el usuario puede cambiar y argumentos de la línea de comandos.

5. Preste atención a las advertencias del compilador

Muchos desarrolladores tienden a enmascarar o ignorar las advertencias del compilador. Esto no se


recomienda, ya que las advertencias del compilador pueden señalar vulnerabilidades de
seguridad. Sus pautas de programación segura deben indicar a todas las partes involucradas que no
ignoren estas advertencias.

6. Evite la complejidad

La complejidad de su diseño aumenta las posibilidades de tener vulnerabilidades de seguridad en


sus aplicaciones. También puede hacer que sea más difícil identificarlos y corregirlos. Mantenga su
diseño simple y pequeño.
7. Limitar los privilegios del proceso

Siempre tenga en cuenta el peor de los casos en el que un atacante tiene acceso a su código. En tal
escenario, el atacante podría ejecutar cualquier código arbitrario. Si sus procesos no están
configurados con los privilegios mínimos que necesitan, el atacante podría aprovechar un proceso
con privilegios elevados.

8. Generación automática de código

Utilice herramientas de generación automática de código tanto como sea posible. Estas


herramientas se pueden configurar para seguir directrices y políticas de programación segura y, por
lo general, no contienen errores humanos. Esto aumentará la seguridad general de su código.

Links
https://camilorada.wordpress.com/2014/08/02/programacion-defensiva/
https://es-academic.com/dic.nsf/eswiki/960949
https://ourcodeworld.co/articulos/leer/1038/mejores-practicas-para-la-programacion-segura
https://latteandcode.medium.com/qu%C3%A9-es-eso-de-la-programaci%C3%B3n-defensiva-
6a89d3bcab8e

También podría gustarte