Hoy, yo no podría hacer una rutina en C++ que al compilar funcione a la primera, porque ya olvidé las instrucciones: creo acordarme de lo más genérico de un lenguaje como: go to, if …then, repeat…until, end; pero lo que no olvidaré nunca es lo que dijo nuestro profesor de C++: lo más importante en la programación es la documentación ¿Se pueden imaginar a los chamacos que estábamos tan felices frente a la computadora maravillados con todo lo que podíamos hacer?, desde gráficos hasta juegos y sistemas muy complejos, ¡la cara que habremos puesto cuando nos habló sobre la documentación! ¿Se acuerdan cómo documentábamos en BASIC?:

REM Este programa calcula la masa corporal de una persona

REM La variable n es el nombre del cliente hasta 255 caracteres

Hasta que di clases y revisaba los programas de mis alumnos para ayudarles a que “jalara”, y no tenían comentarios  comprendí lo que decía el profesor; les cuento las sorpresas que me llevaba con los anidados, las llamadas recurrentes, y sobre todo con la lógica personal de cada quien para construir un algoritmo. Lo que decidí hacer el segundo semestre fue que la calificación del código pesaba lo mismo que la documentación, es decir, cada rutina tenía que decir para qué servía, a quién llamaba, un diagrama del flujo, un diccionario de variables,  y también el release notes, y un manual del usuario (por cierto también premiaba la rutina más corta, para impulsar temas de desempeño). Por supuesto me alucinaron.

Pero cuando realmente cobró sentido para mí fue cuando empecé a auditar, ya en mi trabajo, al realizar pruebas sustantivas donde me tocaba revisar código, buscando controles, evidencias, e información útil para determinar hallazgos, incumplimiento, riesgos, etcétera.  El 90% de los códigos no estaba documentado, así que la interpretación estuvo sujeta a mis corridas de escritorio y un trace manual para entender los flujos.  Esto me restaba precisión en las conclusiones porque tenía que suponer ciertos criterios que había tomado el programador,  además de todo el tiempo que implicaba.

Cuando se aproximaba el año 2000, el mundo informático preveía que muchos sistemas podrían “tronar” primordialmente por haber usado sólo dos dígitos para los años, y que al cambiar de 99 a 00 los programas se volverían locos. Fue la época mejor pagada para los programadores de Cobol y de varios otros lenguajes que tuvieron su auge en los años 70 y 80, y que no habían documentado sus sistemas. ¡Eran los únicos que sabían por dónde moverle al código!

Imaginemos una casa sin planos. Sería muy difícil de remodelar, correríamos riesgos al decidir modificar un muro, construir otro piso, agregar servicios; también sería muy difícil encontrar las causas de goteras, fugas, cuarteaduras. Un banco no podría calcular una valuación; un perito no querría emitir un juicio sobre la salud de la construcción; un posible comprador cuestionaría la falta de los planos; un notario no la escrituraría.

En la actualidad, una de las enormes aportaciones a la industria informática ha sido el open source; entre sus bondades se encuentra la disponibilidad gratuita del código fuente para hacer mejoras y adaptaciones, y el hecho de que está documentado y cuenta tras bambalinas con una entusiasta comunidad de desarrolladores y usuarios que continuamente revisan y documentan el código. El código abierto nos permite conocer la calidad del producto en sus entrañas y también garantiza que no hay en su interior ningún «caballo de Troya» que comprometa su seguridad.

De acuerdo con Gary McGraw, en su libro Software Security – Building Security In, los siete puntos para (re-) construir aplicaciones seguras son, en orden de efectividad:

  1. Revisión de código
  2. Análisis de riesgos de la arquitectura
  3. Pruebas de penetración
  4. Pruebas de seguridad basadas en riesgos
  5. Casos de abuso
  6. Requerimientos de seguridad
  7. Operaciones de seguridad

Prácticamente en los siete aspectos la documentación existente es un aspecto muy relevante que no sólo ahorraría tiempo en un proyecto de auditoría de seguridad aplicativa o en la detección de fallas, sino que aportaría información notable sobre cómo está construido el sistema, cuáles son los servicios de una clase, los límites de transaccionalidad debidos a tamaños de variables, las propiedades de objetos que heredan a otros objetos, los datos que se pasan por valor o por referencia, lo que significa una variable, los criterios que se definieron para declarar una variable, la exposición de un campo a recibir cualquier tipo de input que permita una ejecución de comandos de SQL (provocando inyecciones de SQL, buffer overflows, etcétera).

En fin, creo que no tenemos que convencernos de la importancia de la documentación, sino asegurar que se lleve a cabo para obtener grandes beneficios como:

  • Agilizar las actualizaciones.
  • Entender el flujo del sistema.
  • Prolongar la vida del sistema.
  • Detectar huecos de seguridad del código.
  • Facilitar los procesos de solución de fallas.
  • Buscar la universalidad y compatibilidad.
  • Identificar riesgos de la aplicación.

En la contraparte, el código bien documentado de un sistema crítico o sensible es un arma de dos filos que podría proporcionar información útil para ataques y fraudes.  Por ello, es importantísimo implementar a su vez controles de seguridad al código para protegerlo, como cifrado, DLP, firmas digitales, bloqueo de puertos USB, acuerdos de confidencialidad con programadores, entre otros.

Ahora bien, ¿qué es lo que incluye la documentación de un sistema para asegurar que cumple con sus objetivos? Aquí una lista de los componentes principales:

  • Los requerimientos del negocio (funcionalidad, regulaciones, volumen y desempeño).
  • Los requerimientos de seguridad.
  • La arquitectura de la aplicación.
  • La funcionalidad del sistema.
  • El diccionario de datos.
  • Los casos de uso.
  • Mapeo de controles versus casos de abuso.
  • Diseño específico de los controles de seguridad del sistema.
  • Las premisas del o de los programadores.
  • Las especificaciones de la plataforma de desarrollo.
  • Requerimientos del sistema para que funcione la aplicación.
  • Los convencionalismos tomados en el código.
  • Los comentarios dentro del código.
  • La posibilidad de reuso de objetos, clases y módulos.
  • La conectividad e interfaces del sistema con otros sistemas.
  • Las especificaciones de comunicación hacia el sistema (¿cómo podría un externo llamar a este sistema o a algunas de sus partes?, regulado, claro, por los requerimientos de seguridad).
  • Los casos de prueba y sus criterios de aceptación.
  • Limitaciones o errores conocidos del sistema.
  • Manual del usuario.
  • Manual de instalación.
  • Manual del administrador.
  • Manual de capacitación.
  • Las políticas de protección del código.
  • Release notes para nuevas versiones.
  • Control de versiones del código.
  • Responsables del sistema.

La invitación es a todos los jóvenes programadores que empiezan su carrera profesional (y a los veteranos también), para que adopten prácticas sanas encaminadas a la seguridad de las aplicaciones, robusteciendo su funcionalidad y agilizando la actualización.  Hoy existen muchas herramientas que brindan las comunidades open source las cuales ayudan y facilitan la vida del desarrollador para no reinventar la rueda, incluyendo rutinas y controles de seguridad, técnicas de documentación, errores frecuentes, vulnerabilidades conocidas de los lenguajes, prácticas de codificación, técnicas de optimización, librerías para evitar que se explote alguna vulnerabilidad y un sinfín de material enriquecedor ¡Mucha suerte entonces!

[email protected]

Algunas fuentes que se pueden consultar al respecto:

Bibliografía:

  • Building Secure Software
    • Gary McGraw
    • Addison-Wesley, 2001