Expo Ing Software Corte 3
Expo Ing Software Corte 3
Expo Ing Software Corte 3
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”.
- 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.
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.
- Protejamos nuestro código de nuestros propios fallos y de todos aquellos que otros desarrolladores
puedan provocar.
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”.
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
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.
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.
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:
- 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.
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.
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.
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
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
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.
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.
6. Evite la complejidad
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.
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