Está en la página 1de 71

See discussions, stats, and author profiles for this publication at: https://www.researchgate.

net/publication/336425433

Identificación de etapas del ciclo de desarrollo de software donde la


implementación de medidas de seguridad es crítica

Thesis · September 2019


DOI: 10.13140/RG.2.2.12409.01126

CITATIONS READS

0 3,249

1 author:

Peter Fernandez Graf


National Institute of Agricultural Research of Uruguay
6 PUBLICATIONS   0 CITATIONS   

SEE PROFILE

Some of the authors of this publication are also working on these related projects:

Análisis de imágenes con ImageJ View project

All content following this page was uploaded by Peter Fernandez Graf on 11 October 2019.

The user has requested enhancement of the downloaded file.


Universitat de Lleida
Next International Business School

Master in Cybersecurity

Identificación de etapas del ciclo


de desarrollo de software donde
la implementación de medidas de
seguridad es crítica

Alumno: Peter Dennis Fernández Graf

Tutora: Eva Roteta Llamas


Declaración de autoría

Por medio de la presente, el autor manifiesta conocer y aceptar el Reglamento


de Tesis vigente y se hace responsable de que la totalidad de los contenidos del
presente documento son originales y de su creación exclusiva, o bien pertenecen
a terceros u otras fuentes, que han sido adecuadamente referenciados y cuya
inclusión no infringe la legislación Nacional e Internacional de Propiedad
Intelectual.

2
Abstract
El propósito de la tesis es brindar una solución de seguridad informática sencilla
al proceso de desarrollo del software que los programadores utilizan diariamente.

En el mundo de la informática es muy fácil cometer errores al crear aplicaciones


que sean vulnerables por no tener los conocimientos adecuados sobre los
posibles ataques que puede sufrir un software por parte de un ciberdelincuente.
Proteger la información personal y/o confidencial de una compañía es
imprescindible para el negocio, creando aplicaciones seguras esto es posible.

Este documento cuenta con la sistematización de información disponible en


Internet sobre el ciclo de desarrollo conocido como SDLC, la solución propuesta
y una demostración de buenas prácticas para analizar, diseñar, codificar e
implementar una aplicación que tenga en cuenta la seguridad. Por último, una
herramienta web con información a modo de tips para que los desarrolladores
tengan de soporte al momento que necesiten comenzar a implementar un ciclo
de desarrollo seguro.

Parte de los objetivos propuestos es demostrar la importancia que tiene la


seguridad y que no todas las compañías la ven como realmente deberían. La
falta de formación en los desarrolladores y la falta de conciencia en lo
imprescindible que son los datos para una compañía es un aspecto importante
que puede estar ocasionando las vulnerabilidades que ocurren hoy en día.

La solución propuesta debería ser adoptada por los desarrolladores desde el


comienzo del análisis de requerimientos para cualquier proyecto.

3
Índice

1. Introducción ................................................................................................. 5
2. Presentación del problema .......................................................................... 6
3. Objetivos ...................................................................................................... 9
4. Alcances y limitaciones ................................................................................ 9
5. Ciclo de desarrollo tradicional .................................................................... 10
6. Ciclo seguro ............................................................................................... 15
Requerimientos de seguridad para el SDLC ............................................ 19
¿Cuáles son las desventajas de no incluir seguridad en el análisis? ....... 20
Diseño seguro para el SDLC.................................................................... 21
¿Cuáles son las ventajas de un software diseñado de forma segura? .... 31
Codificación e implementación segura ..................................................... 32
Revisiones de código seguro ................................................................... 36
Penetration testing ................................................................................... 37
7. Herramienta web de seguridad en cada etapa .......................................... 40
8. Conclusiones ............................................................................................. 41
9. Anexos ....................................................................................................... 44
10. Glosario...................................................................................................... 66
11. Bibliografía utilizada ................................................................................... 69

4
1. Introducción
El presente trabajo corresponde al tema de seguridad en el ciclo de desarrollo
de aplicaciones que se utiliza en la actualidad. La inclusión de seguridad al
desarrollar software es una parte fundamental de cada etapa que no siempre se
respeta, sino que por lo general se realizan tests de seguridad al finalizar el
proceso de desarrollo durante la fase de implementación. Esto implica que los
costos para reparar una vulnerabilidad dentro del sistema sean muy elevados en
tiempo y por consecuencia, en dinero.

Además de estas consideraciones el encargado del equipo de desarrollo debería


tener especial cuidado en la información que se maneja dentro de la aplicación,
como por ejemplo datos personales almacenados, regulaciones legales-jurídicas
de cada país, etc.

Para analizar esta problemática es necesario mencionar sus causas.


Seguramente hay muchos desarrolladores que aplican las más avanzadas
técnicas de seguridad. También existen quienes son conscientes de las
soluciones de estos problemas, pero no los aplican y son muchos los
profesionales del software que ignoran estos tipos de técnicas.

El propósito de este trabajo es brindar una solución sencilla y eficiente para que
sea utilizada desde el comienzo de cada proyecto y lo acompañe en las
diferentes etapas. A su vez, proveer herramientas para que los usuarios de las
aplicaciones puedan validar mínimos estándares de seguridad.

Las soluciones planteadas en este documento están basadas en la experiencia


que he obtenido a través de años de desarrollo de software, mi educación y la
pasión que he sentido desde muy joven para encontrar soluciones a este tipo de
desafíos.

5
2. Presentación del problema
Distintos informes realizados a nivel mundial destacan a los riesgos de
ciberseguridad como uno de los principales riesgos operativos que enfrentan las
empresas a nivel global.

En este contexto el presente documento busca aportar información sobre las


posibles causas de un desarrollo de software poco seguro o vulnerable.

En la actualidad para crear una aplicación es necesario pasar por distintas


etapas conocidas como ciclo de vida del software. La mejor definición en este
sentido es la que nos presenta Wikipedia:

El Proceso para el desarrollo de software, también denominado ciclo de vida


del desarrollo de software es una estructura aplicada al desarrollo de un
producto de software. Hay varios modelos a seguir para el establecimiento de un
proceso para el desarrollo de software, cada uno de los cuales describe un
enfoque diferente para diferentes actividades que tienen lugar durante el
proceso. Algunos autores consideran un modelo de ciclo de vida un término más
general que un determinado proceso para el desarrollo de software. Por ejemplo,
hay varios procesos de desarrollo de software específicos que se ajustan a un
modelo de ciclo de vida de espiral.

Con esta definición veamos un ejemplo: un cliente nos solicita la creación de una
aplicación debido a una necesidad específica la cual será solucionada con el
desarrollo de un software. Lo que realiza un programador o una empresa es
trasladar esta necesidad a una lista de requerimientos, esta etapa es la más
importante y es conocida como análisis.

Dentro de la etapa “análisis”, la lista de requerimientos del software debe abordar


quiénes serán los clientes y qué necesidades de ellos puede resolver el software.
Por ejemplo, ¿en qué demografía se encuentran, son adultos mayores o jóvenes,
cuál es su género, qué saben y cuáles son los problemas que enfrentan en su

6
día a día? También necesita saber cómo utilizarán el software, qué tipo de
información necesitan poner en él, así como los resultados que obtendrán de
este.

Luego continúan las fases de diseño, desarrollo, implementación, testing y


mantenimiento.

Imagen 1. SDLC tradicional

En “diseño” se descompone y organiza el sistema en elementos que puedan


elaborarse por separado, “desarrollo” o codificación es donde se comienza a
escribir código. La “implementación” es comenzar a utilizar la aplicación y
validar que se encuentra de acuerdo con los requerimientos, “testing” es la fase
de ejecución de pruebas y “mantenimiento” consiste en continuar con nuevas
funcionalidades, reparar errores no detectados o mejorar el sistema.

Imaginemos que la aplicación se encuentra en la fase de testing y es hora de


realizar una prueba de seguridad para medir el nivel de vulnerabilidad que tiene
la misma. En el caso de que el test sea satisfactorio y no presente
vulnerabilidades estaría lista para entrar en funcionamiento pero, si no fuese el
caso, la aplicación debería entrar en la fase de desarrollo nuevamente para

7
solucionar los errores de seguridad detectados. Esto provocaría un retraso en
los tiempos de entrega. Una vez creados los parches de seguridad la aplicación
deberá ser probada de nuevo hasta que presente un nivel de vulnerabilidad
aceptable o muy bajo. Todo esto sin hablar de la calidad del código que se ha
creado.

Hay que aplicar una mitigación a este problema y lo adecuado es interceptar


cada una de las etapas del ciclo de vida del software para incluir como
requerimientos aquellas medidas de seguridad que son críticas o indispensables
para evitar vulnerabilidades y cuidar los principios básicos de la seguridad como:

Confidencialidad: es el hecho de que la información se mantenga privada, que


no sea expuesta a terceros no involucrados en ella.

Integridad: este principio implica garantizar que la información no pueda ser


adulterada o modificada por un tercero no autorizado.

Disponibilidad: Si la información no puede ser consultada por los interesados


entonces no tiene mucho uso. Así, uno de los principios de la seguridad es
garantizar que la información pueda ser consultada por los interesados cada
vez que estos lo requieran. Este es un principio fundamental de la seguridad,
pues muchas veces se dirigen los esfuerzos a vigilar que la información no sea
adulterada (integridad) o que no se filtre (confidencialidad) y se descuidan los
peligros que implica que la información no esté disponible.

8
3. Objetivos

Determinar el nivel de vulnerabilidad de los programadores hacia los clientes al


crear software. (demostrar cómo de expuesto queda un cliente si los
conocimientos del programador no son los apropiados)

Demostrar las debilidades del ciclo de desarrollo tradicional y a su vez


acompañarlo con la demostración de la solución.

Crear una herramienta web online para desarrolladores de software que les
permita tener a modo de tips lo impresindible para cada fase del ciclo de vida del
software desde el punto de vista de la seguridad.

4. Alcances y limitaciones
Alcances

Demostrar el ciclo de vida del desarrollo de software tradicional y los problemas


que presenta desde el punto de vista de la seguridad.

Investigar las soluciones presentes en la actualidad para mitigar problemas de


seguridad informática en el ciclo.

Sistematizar la información de terceros y crear una herramienta web online de


sugerencias para programadores y usuarios comunes.

Limitaciones

Todo el material será con fines 100% educativos.

9
5. Ciclo de desarrollo tradicional

En la actualidad la seguridad informática se ha convertido en una de las


principales preocupaciones de las empresas. Por otro lado, el uso de las
tecnologías de la información y comunicaciones (TIC), es cada vez más extenso
por lo que los activos a proteger y las vulnerabilidades aumentan. Los
ciberataques son más frecuentes y complejos, llegando a tener consecuencias
muy graves como la revelación de información sensible, modificación de
información privada, servicios mundiales no disponibles, entre otras.

La seguridad informática es la defensa en contra de los ataques digitales. Los


métodos varían según la necesidad, la vulnerabilidad, y las amenazas que se
encuentran presentes.

Imagen 2. Necesidad de seguridad en empresas uruguayas (Datasec, 2019)

En la imagen 2 se muestra cómo las empresas uruguayas no creen necesario


someterse a una evaluación del estado de ciberseguridad (Datasec, 2019),
posiblemente porque no han visualizado el verdadero impacto que puede tener
una vulnerabilidad dentro del software.

10
Otras estadísticas muestran que 70% de las organizaciones cree que su riesgo
de seguridad creció considerablemente en el 2017. (Ponemon Institute, 2017)

En el año 2015, 230.000 nuevos malware fueron producidos cada día. (Panda
Security, 2015).

Mundialmente China es uno de los países más infectados con malware en 2015:

Imagen 3. Países con más infecciones de malware en el mundo. (Panda


Security, 2015)

Entender el estado actual de la seguridad informática es importante para las


organizaciones y para los encargados del desarrollo de aplicaciones. Decir que
una vulnerabilidad está presente dentro de un software equivale a decir que
alguien escribió esa vulnerabilidad o error.

El Ciclo de Vida de Desarrollo de Software, en inglés Software Development


Life Cycle (SDLC), es todo el proceso que un programador u organización tiene
para cualquier proyecto de software nuevo desde el análisis de la idea hasta que
sea implementado y esté en producción (Imagen 4).

11
Imagen 4. SDLC tradicional sin considerar la seguridad

Teniendo en cuenta que al ir desarrollando software es posible generar una


vulnerabilidad se debe aprender a escribir código considerando la seguridad
informática.

Una de las formas adecuadas para minimizar errores de seguridad en el código


es introduciendo fases paralelas como soporte:

Imagen 5. Etapas paralelas al SDLC tradicional para incorporar seguridad.


12
En las imágenes anteriores podemos ver que cada fase tiene su correspondiente
fase de seguridad, por ejemplo, en el momento que se están realizando pruebas
del funcionamiento de la aplicación (implementación y testing), se debería de
realizar un análisis dinámico de la misma en la que se puedan ver las
vulnerabilidades antes de la fase de producción. Este análisis dinámico consistirá
en la ejecución del programa y observar cómo se comporta el mismo con
herramientas que automaticen las pruebas.

La implementación de medidas de seguridad debe hacerse desde el inicio del


SDLC, ya que el coste de solucionar cualquier problema de seguridad es mayor
cuanto más tarde se detecte, como se observa en el siguiente gráfico:

Costo de reparar una vulnerabilidad en el SDLC

Análisis Diseño Desarrollo Pruebas En producción

Imagen 6. Representación del costo en reparar una vulnerabilidad en el SDLC

Algunas compañías o departamentos de desarrollo piensan en excusas muy


fácilmente descartables para no implementar seguridad en los programas. Estas
son las más escuchadas a menudo:

• La gente no sabe el funcionamiento, entonces no nos van a atacar. (Un


atacante invertirá el tiempo que necesite para saber cómo funciona)
• No hemos encontrado vulnerabilidades hasta el momento (Un atacante
encontrará una o varias vulnerabilidades muy rápidamente)

13
• ¿Quién puede estar interesado en atacar nuestra aplicación? (Existen
millones de bots o sistemas automáticos escaneando constantemente
en busca de deficiencias de seguridad)
• La aplicación es segura porque corre detrás de un firewall. (Obviamente
si tiene un elemento hardware de seguridad es más segura, pero este
hecho no implicará nunca que sea segura)
• La aplicación es segura porque usa https. (En este caso la comunicación
es segura pero el desarrollo no tiene porqué serlo)
• Si no corre como administrador, no puedes hacer nada peligroso.
(Obviamente esto es una buena práctica de seguridad, pero que el
usuario tenga pocos privilegios no indica que la aplicación sea segura)

En la mayoría de los casos los clientes están apurados para salir al mercado o
poner algo en producción y se suele escuchar: “No hay tiempo para incluir la
seguridad”.

14
6. Ciclo seguro
Teniendo en cuenta la cantidad de vulnerabilidades descubiertas diariamente y
que en el ciclo vida del desarrollo de software o Systems Development Life Cycle
(SDLC) la seguridad informática no es considerada una parte fundamental o no
es reconocida como una parte imprescindible del proceso del SDLC se plantea
una sistematización de la información disponible en Internet con una visión
general de la solución propuesta al SDLC.

Existen organizaciones mundiales dedicadas a preservar la seguridad en


Internet y/o que aportan información tal como modelos o estructuras de
desarrollo para que los programadores puedan y sepan cómo agregar seguridad
dentro del código escrito. Una de ellas es Open Web Application Security Project
(OWASP), una organización sin ánimo de lucro a nivel mundial dedicada a
mejorar la seguridad de las aplicaciones y del software en general. Su misión es
hacer que la seguridad dentro de las aplicaciones sea más visible para que, así,
las organizaciones y los particulares puedan tomar decisiones sobre conceptos
de seguridad basándose en información verídica y contrastada.

Entre otros proyectos OWASP ha desarrollado una guía de referencia para


prácticas de codificación segura que proporciona orientación detallada sobre la
seguridad de aplicaciones web la cual se encuentra como anexo (ver anexo 1:
Guía de referencia para prácticas de codificación segura de OWASP). Si bien el
foco principal está en las aplicaciones web y la infraestructura que las soporta,
la mayoría de los consejos puede aplicarse en cualquier plataforma de desarrollo
de software.

La construcción de software seguro requiere una comprensión básica de los


principios de seguridad. El objetivo de la seguridad en el software es el de
mantener la confidencialidad, integridad y disponibilidad de los recursos de
información a modo de permitir el desarrollo exitoso de negocios. Este objetivo
se consigue con la implementación de controles de seguridad.

15
Imagen 7. Principios de seguridad informática. Fuente: ticsalborada1. (s.f.)

Es de gran utilidad comprender qué se entiende por un riesgo, con el fin de


proteger al negocio de riesgos inaceptables derivados de su dependencia en el
software. Un riesgo es una combinación de factores que amenazan al éxito del
negocio. Puede ser definido conceptualmente como: un agente amenazante que
interactúa con el sistema, que puede tener una vulnerabilidad a ser explotada de
forma de generar un impacto.

Si bien este puede resultar un concepto abstracto, se puede pensar de esta


forma: un ladrón de autos (agente amenazante) recorre un estacionamiento
verificando los vehículos (el sistema) en busca de una puerta sin trabar (la
vulnerabilidad) y cuando encuentra uno, abre la puerta (situación a ser
explotada) y toma algo de adentro del mismo (el impacto). Todos estos factores
juegan un rol en el desarrollo de software seguro.

Existe una diferencia fundamental entre el enfoque que adopta un equipo de


desarrollo y el que toma alguien que está realizando un ataque sobre la
aplicación. Un equipo de desarrollo adopta un enfoque basado en lo que tiene
intenciones de realizar. En otras palabras, están diseñando una aplicación para
que realice tareas específicas basándose en los requerimientos funcionales y
casos de uso que han sido documentados. Un atacante, por otra parte, está más
16
interesado en lo que puede llegar a hacerse con esa aplicación y opera bajo el
principio de “cualquier acción que no haya sido denegada de forma expresa, está
permitida”.

Es importante que los equipos de desarrollo web entiendan que los controles
desde el lado del cliente, tales como la validación de lo que ingresa el cliente,
campos ocultos y controles en la interfaz (por ejemplo: menús desplegables y
botones de opción) brindan poco, si acaso algún beneficio, desde el punto de
vista de la seguridad. Un atacante puede utilizar herramientas intermediarias
entre las acciones del usuario y el servidor (llamado proxies del lado del cliente,
por ejemplo: OWASP ZAP) o herramientas (como WireShark) de capturas de
paquetes de red (cada uno de los bloques en que se divide la información para
enviar, en el nivel de red) para analizar el tráfico de la aplicación y enviar
solicitudes hechas a medida, sin siquiera pasar por la interfaz. Además de esto,
Flash, Applets de Java y otros objetos del lado del cliente pueden ser
descompilados y analizados en busca de fallas.

Las fallas de seguridad en el software pueden introducirse en cualquiera de las


etapas del ciclo de desarrollo del software, derivados de:

• No identificar requerimientos de seguridad desde el inicio.


• Crear diseños conceptuales que contengan errores en la lógica.
• Utilizar prácticas débiles de codificación que introduzcan vulnerabilidades
desde el punto de vista técnico.
• Implantación del software de forma inapropiada.
• Introducción de fallas durante el mantenimiento o actualización del
producto.

Es importante además entender que las vulnerabilidades del software pueden


escapar los límites del software mismo. Dependiendo de la naturaleza del
software, la vulnerabilidad y la infraestructura que da soporte, el impacto del éxito
en la intromisión puede comprometer a cualquiera o todas de las siguientes:

17
• El software y su información asociada.
• Los sistemas operativos de los servidores asociados.
• La base de datos del backend.
• Otras aplicaciones en el entorno compartido.
• El sistema del usuario.
• Otro software con el que interactúe el usuario.

Para dar solución a esta problemática y concienciar a los programadores de que


la seguridad es una parte fundamental del SDLC se debe implementar lo que se
llama ciclo de vida del desarrollo seguro o Secure Systems Development Life
Cycle (S-SDLC). Es un sistema utilizado en el mundo del desarrollo de software
para crear aplicaciones de todo tipo, lo más seguras posible, desde que se inicia
el proceso de análisis hasta que se pone en producción.

Es un conjunto de principios de diseño y buenas prácticas a implantar en el


SDLC, para detectar, prevenir y corregir los defectos de seguridad en el
desarrollo y adquisición de aplicaciones, de forma que se obtenga software de
confianza y robusto frente a ataques maliciosos, que realice solo las funciones
para las que fue diseñado, que esté libre de vulnerabilidades, ya sean
intencionalmente diseñadas o accidentalmente insertadas durante su ciclo de
vida y se asegure su integridad, disponibilidad y confidencialidad.

18
Imagen 8. Seguridad en el SDLC

Al tratarse de un ciclo conlleva a que tenga iteraciones que deben de ejecutarse


durante todo el periodo de vida de las aplicaciones.

Requerimientos de seguridad para el SDLC

La fase de análisis o requerimientos del ciclo de vida del desarrollo de software


seguro debe tener en cuenta la resistencia, la fiabilidad y la capacidad de
recuperación del software. ¿El software es resistente a los ataques? ¿Es
confiable el software cuando está bajo ataque? ¿Y puede el software
recuperarse rápidamente incluso de los ataques más avanzados?

El primer paso sería establecer requerimientos y controles de seguridad


cuantificables para el ciclo de desarrollo de software. Además, es necesario tener
siempre en cuenta el rendimiento, la fiabilidad y la facilidad de mantenimiento del

19
software. Desde el principio es necesario definir claramente los requerimientos
de seguridad. Algunos ejemplos podrían ser los siguientes:

• Qué métodos de autenticación se utilizarán o autenticación multi-factor


(password, token, lector de retina, lector de huella dactilar, etc.).
• Control de autenticación (creación de usuarios con contraseña robusta).
• Control de roles y privilegios (cada usuario tan solo debe tener acceso a
lo necesario dentro de la aplicación).
• Requerimientos orientados al riesgo (requerir contraseñas y métodos de
autenticación fiables).
• Arquitectura de la aplicación (cliente/servidor o desktop).
• Plataforma donde correrá la aplicación (PC, laptop, mobile, Tablet, etc.).
• Sistema operativo anfitrión del software o aplicación a desarrollar (Linux,
Windows, Android, iOS, etc.).
• Tipos de datos que se almacenan o transfieren (públicos o privados).
• Tipos de registros que el sistema debe generar (logs y la información
almacenada en estos).
• Acciones sobre el sistema que puede hacer cada perfil (cambiar
configuración del sistema, iniciar o detener servicios).

¿Cuáles son las desventajas de no incluir seguridad


en el análisis?

Si los requerimientos de seguridad no son considerados posiblemente suceda


lo siguiente al finalizar el producto:

• Los proyectos terminan por encima del presupuesto, se reduce de


manera significativa el alcance o se retrasan en su entrega.
• Los equipos de desarrollo ofrecen aplicaciones de baja calidad.
• Los productos no se utilizan de manera eficiente.
• Pérdida de confianza por parte del cliente hacia la empresa.
• Posible filtración o pérdida de información que circula en la aplicación.

20
Diseño seguro para el SDLC

La siguiente fase imprescindible sería la de diseño puesto que muchos fallos de


seguridad en las aplicaciones fueron detectados en la fase de diseño de estas.
Un software que está diseñado de forma correcta y segura también es de alta
calidad. En pocas palabras, inyectar seguridad dentro de la fase de diseño
significa abordar las decisiones de diseño que tienen en cuenta la perspectiva
de un atacante que intenta violar las debilidades y comprometer la
confidencialidad, la integridad y otros aspectos importantes de seguridad del
software.

Imagen 9. Pensando desde la perspectiva de un ciberdelincuente

Algunos ejemplos a tener en cuenta para el diseño seguro son los siguientes:

• Diseño seguro de mensajes de error (no se debe poder interactuar con


los mensajes de error ya que podrían dar acceso a la aplicación) .

En el siguiente ejemplo podemos ver un código en el lenguaje de programación


PHP donde se imprime un mensaje de error de conexión a la base de datos,
mostrando nombre de la base y tabla específica. Sería un ejemplo de código
inseguro.

Como se puede observar en las líneas que comienzan con doble barra (//) son
comentarios de ayuda para comprender el código.

21
//En la siguiente línea de código se realiza la conexión a la base de datos
$con = mysqli_connect("localhost", "root", "", "densidad");

// En la siguiente línea chequea que la conexión sea correcta


if (mysqli_connect_errno()) {
//Si la conexión falló imprime el siguiente mensaje:
echo "Failed to connect to MySQL: " . mysqli_connect_error();
//mysqli_connect_error() mostraría el error ocurrido
}

// En la siguiente línea de código se intenta agregar un nuevo usuario en la


base de datos.
if (!mysqli_query($con, "INSERT INTO usuarios (FirstName) VALUES ('Peter')"))
{
//En caso que la inserción falle muestra un error:
echo("Error description: " . mysqli_error($con));
// mysqli_error($con) mostrará el error ocurrido
}

mysqli_close($con);

El problema se encuentra en la línea donde está el código


mysqli_connect_error(). Esto se debe a que el programador que escribió este
código no visualizó los mensajes de error desde la perspectiva de un atacante,
sino que este tipo de mensajes informativos sirven para encontrar más fácilmente
un error dentro de la programación.

En caso de que la tabla usuario no exista en la base de datos o se haya borrado


por algún motivo al ejecutar la aplicación el resultado podría ser el siguiente:

Imagen 10. Intento fallido al agregar un usuario

En la imagen anterior se observa el mensaje de error emitido por el sistema


donde expone que la tabla “usuarios” en la base de datos “densidad” no existe.
Con este resultado un atacante ya puede ir conociendo cómo está compuesta la
base de datos e ir recolectando información para su fin.

22
¿Cómo solucionar el error anterior y que el sistema no muestre datos sensibles
como nombre de tablas y base de datos?

Cambiando la línea de código donde se imprime el error:


echo("Error description: " . mysqli_error($con));

Por este otro código con un mensaje genérico:


echo("Error en al insertar un dato");

• Diseño seguro de autenticación (para evitar que los atacantes puedan


insertar código que pueda ser ejecutado en la base de datos, lo que se
conoce como inyección SQL).

El siguiente es un ejemplo inseguro en el cual la aplicación sería vulnerable a


un ataque de inyección SQL donde un atacante podría vulnerar el código de la
aplicación si introdujera algo como 'or '1'='1

Imagen 11. Formulario web para autenticarse en el sistema

Al introducir este texto dentro de los campos de usuario y contraseña lo que


produce es una alteración en la sentencia SQL que se ejecutará. Esta
alteración es que la base de datos interpreta que el número 1 es igual al
número 1 por lo tanto esto es correcto (1=1 entonces true para SQL).

23
El siguiente ejemplo es la demostración del código en la aplicación y cómo
quedaría alterada la sentencia SQL:

//Función para login en el sistema


//la función recibe el nombre de usuario (un email para autenticarse) y la
password
public function login($nombreusuario, $password)
{
//el normal funcionamiento sería que llegue un texto como peter@appsweb.dev
para el usuario y una password
$this->query("SELECT * FROM members WHERE email = '" . $nombreusuario . "'
and password = '" . $password . "'");

return $this->result;
}

Si un atacante envía 'or '1'='1 en vez de una correcta dirección de email y


password, la sentencia SQL quedaría de la siguiente forma:

SELECT * FROM members WHERE email = ''or '1'='1' and password = ''or '1'='1'

El resultado es que el atacante se autentica en el sistema sin tener necesidad


de conocer usuario y password:

Imagen 12. Atacante se autentica debido a un error de SQL Injection

Como se observa en el ejemplo anterior el problema se origina porque el


atacante puede ingresar comilla doble o simple en los campos de texto que el
sistema permite utilizar.

24
La solución al problema de SQL injection se encuentra en el apartado
Codificación e implementación segura (utilizar declaraciones preparadas o
PreparedStatement).
• Diseño de login (utilizar un diseño centrado en usabilidad, pero sin dejar
acceder sin contraseña a los servicios).

• Análisis de riesgo (analizar la aplicación en busca de posibles riesgos que


pudieran aparecer en esta fase de análisis y diseño).

• Protección de datos confidenciales almacenados, procesados o


transmitidos (regulaciones legales de cada país).

• Técnicas de cifrado de la información a utilizar.

Cifrar significa que un texto entendible por las personas será alterado de tal
forma que no sea posible descifrar lo que dice. En la siguiente imagen se puede
apreciar visualmente cómo funcionaría:

Imagen 13. Diagrama de cifrado de información

Como ejemplo práctico de código seguro se utilizará PHP para cifrar y


descifrar la información. Una de las funciones más seguras que puede
utilizarse es el módulo de encriptación de OpenSSL. OpenSSL es una
herramienta open source para implementar los protocolos TLS y SSL
25
además de ser una completa librería de encriptación. Con doble barra (//) se
encuentran los comentarios que ayudan a interpretar el código:

//Función para encriptar


function encrypt($data, $key)
{
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-
cbc'));
$encrypted = openssl_encrypt($data, "aes-256-cbc", $key, 0, $iv);
// Devuelve la cadena de texto encriptada
return base64_encode($encrypted . "::" . $iv);
}

//Función para desencriptar


function decrypt($data, $key)
{
list($encrypted_data, $iv) = explode('::', base64_decode($data), 2);
//Devuelve el texto desencriptado
return openssl_decrypt($encrypted_data, 'aes-256-cbc', $key, 0, $iv);
}

//$key es una clave para poder realizar el proceso


$key = "1235@";
//$string es el texto o la información que se desea cifrar
$string = "Texto a cifrar";

//En la siguiente línea se envía el texto a la función encrypt para que sea
cifrado
$encryptado = encrypt($string, $key);
//A continuación imprime el texto cifrado
echo $encryptado;
echo "<br><br>";
//Por último se imprime el texto descifrado
echo decrypt($encryptado, $key);

Como se observa a continuación, al ejecutar el sistema el resultado es el texto


cifrado y debajo el texto descifrado:

Imagen 14. Resultado de cifrar/descifrar con OpenSSL

26
Como ejemplo inseguro de cifrado de la información podemos ver mcrypt. NO
es recomendable utilizar la extensión mcrypt por más que sea compatible con
diferentes algoritmos criptográficos.
El encriptado y desencriptado de datos se realiza mediante el uso de las
funciones mcrypt_encrypt( ) y mcrypt_decrypt( ), respectivamente. En los
comentarios con doble barra (//) se explica el código:

//Estas funciones aceptan cinco argumentos. El primero de ellos es el


algoritmo a utilizar.
$algorithm = MCRYPT_BLOWFISH;
//el segundo argumento es la clave.
$key = 'Clave super importante.';
//El tercer argumento incluye los datos para encriptar o desencriptar en
función de la funcionalidad implementada.
$data = 'Este es un mensaje super importante que debes ver';
//El cuarto argumento indica el modo de encriptado o desencriptado.
$mode = MCRYPT_MODE_CBC;
//y finalmente el quinto argumento esta dedicado al vector de inicialización:
$iv = mcrypt_create_iv(mcrypt_get_iv_size($algorithm, $mode),
MCRYPT_DEV_URANDOM);
//A continuación se encripta el mensaje
$encrypted_data = mcrypt_encrypt($algorithm, $key, $data, $mode, $iv);
$plain_text = base64_encode($encrypted_data);
//Con lo siguiente podemos ver el texto cifrado
echo "Texto CIFRADO <br>" . $plain_text . "<br><br>";

//A continuación se desencripta o descifra el mensaje


$encrypted_data = base64_decode($plain_text);
$decoded = mcrypt_decrypt($algorithm, $key, $encrypted_data, $mode, $iv);
//Con lo siguiente podemos ver el texto descifrado
echo "Texto DESCIFRADO <br>". $decoded . "<br><br>";

Como se puede observar a continuación al ejecutar el software se imprime el


texto cifrado y descifrado:

Imagen 15. Cifrado de la información

27
Se debe aclarar que es un ejemplo inseguro de funciones de un lenguaje de
programación porque ocasiona un error de software que se produce cuando un
programa no controla adecuadamente la cantidad de datos que se copian
sobre un área de memoria reservada a tal efecto (buffer), de forma que si dicha
cantidad es superior a la capacidad preasignada los bytes sobrantes se
almacenan en zonas de memoria adyacentes, sobrescribiendo su contenido
original. Esto constituye un fallo de programación. Su nombre es conocido
como buffer overflow o desbordamiento de búfer basado en la pila y afecta a
mcrypt 2.6.8 y versiones anteriores, permitiendo a los atacantes remotos
asistidos por el usuario causar una denegación de servicio (bloqueo) y
posiblemente ejecutar código arbitrario a través de un nombre de archivo largo.
Fuente CVE Details (2012).

• Reducción de superficie de ataque (el tamaño de la superficie de ataque


está directamente relacionado con la posibilidad de ejecutar un ataque
exitoso contra el objetivo. Mientras más información acumulemos o
expongamos, mayor será también la superficie de ataque). Por ejemplo,
cerrar o restringir el acceso a servicios del sistema operativo anfitrión.

Otro tema a destacar en esta etapa es la de crear bases de datos relacionales,


esto significa definir una colección de elementos de datos organizados en un
conjunto de tablas formalmente descritas desde la que se puede acceder a los
datos o volver a montarlos de muchas maneras diferentes sin tener que
reorganizar las tablas de la base. Las técnicas de normalización aplicadas al
sistema de gestión de bases de datos relacionales se aplican mediante
restricciones de integridad referencial adecuadamente diseñadas.

La disponibilidad, la autenticación, la autorización, la contabilidad y la auditoría


son aspectos importantes de una pieza de software y, desafortunadamente, son
una gran fuente de inspiración para los atacantes cuando están "diseñadas de
forma insegura".

28
Por ejemplo, los ataques de denegación de servicio son "habituales" para los
piratas informáticos y, en muchos escenarios, pueden activar una cadena de
efectos desastrosa, quebrando uno de los principios de seguridad:
“disponibilidad”.
La integridad en base de datos se refiere a la completitud, la exactitud y la
coherencia del conjunto de datos de una base de datos. Podemos tener una
percepción de esta integridad en base de datos cuando vemos que entre dos
actualizaciones de un registro de datos, no hay ninguna alteración, lo que
significa que los datos están intactos y sin cambios.

La seguridad de la información se ocupa de proteger la confidencialidad,


disponibilidad e integridad en base de datos de todos los activos de conocimiento
de la organización.

Los tipos de ataques a la integridad de una base de datos pueden ser:


• Datos personales de clientes, números de tarjetas de crédito, usuarios y
contraseñas, dirección de su hogar, etcétera.
• Detalles estratégicos del negocio.
• Información financiera de la propia compañía y de sus socios.
• Datos sensibles acerca de sus empleados (historial de desempeño,
problemas de salud, teléfono personal, educación, etc.).

En el siguiente ejemplo podemos ver una tabla de base de datos mal diseñada
desde el punto de vista de la seguridad ya que contiene información sensible
como cédula de identidad, datos personales, usuario y contraseña sin cifrar.

Imagen 16. Información sensible sin cifrar

29
En consecuencia, si un atacante accede a nuestra base de datos y da un simple
vistazo se puede dar cuenta que tiene toda la información almacenada al alcance
de sus manos de forma sencilla sin necesidad de descifrar los datos.

Una forma correcta de almacenar la información es cifrándola como en el


siguiente ejemplo:

Imagen 17. Tabla en base de datos cifrada

Continuando con el diseño seguro de una base de datos se debe tener en cuenta
los usuarios que accederán a la información y los privilegios correspondientes
para cada uno. Es muy importante definir los privilegios necesarios para cada
uno de ellos. En el siguiente ejemplo podemos ver cómo crear un usuario:

Imagen 18. Crear usuario en MySQL

Con la siguiente sentencia SQL se le brindan los permisos necesarios:

Imagen 19. Permisos por tipo de usuario

En el caso de requerir menores privilegios se puede ir dejando solo algunos


como “SELECT” o “INSERT”.

Por último y necesario será refrescar los permisos con el siguiente comando:
FLUSH PRIVILEGES;

30
¿Cuáles son las ventajas de un software diseñado de
forma segura?

• Proporcionará calidad y seguridad al mismo tiempo, y garantizará la


protección contra la reputación de la compañía y los riesgos
presupuestarios.

• Aumentará la productividad de los desarrolladores al limitar la necesidad


de decisiones críticas, limitando así las interacciones durante la fase de
codificación.

• Puede ser más fácil de mantener y evolucionar.

• Puede proporcionar beneficios a su comercialización al incluir


documentación y tranquilizar a sus prospectos con evidencia sobre la
seguridad del producto que están considerando comprar.

• La información se encuentra protegida bajo rigurosos sistemas de


seguridad.

31
Codificación e implementación segura

Durante la fase de implementación y codificación, una falta de control en el


código puede conllevar a que se comprometa la aplicación y los datos de la
misma. Unas buenas prácticas para la codificación segura serían:

• Validar siempre los datos de entrada antes de procesarlos (comprobar


que los datos ingresados por el usuario son correctos).

Un ejemplo sería comprobando que no son cadenas de texto para ejecutar en la


base de datos, conocidas como sentencias SQL que darían acceso a un atacante
a la base de datos.

• Controlar el tamaño y tipos de datos de entrada (controlar los datos que


se ingresan en formularios para evitar riesgos de entradas que
comprometan la aplicación).

• Eliminar caracteres especiales (para que no se puedan ingresar


sentencias de programación que pudieran ser procesadas por la
aplicación).

• Transformar los datos de entrada en un encoding establecido (transformar


estos datos para un mejor tratamiento por ejemplo transformar todas las
letras en minúsculas).

• No mezclar datos con código (para evitar errores de procesamiento con


lo que podría llevar a un fallo de seguridad).

• Utilizar declaraciones preparadas o PreparedStatement.

Una Prepared Statement es una sentencia SQL de base de datos precompilada.


Al estar precompilada, su ejecución será más rápida que una SQL normal

32
además de prevenir automáticamente ataques de inyección SQL mediante el
escape integrado de comillas y otros caracteres especiales.

La ejecución de sentencias preparadas consiste en dos etapas: la preparación y


la ejecución. En la etapa de preparación se envía una plantilla de sentencia al
servidor de bases de datos. El servidor realiza una comprobación de sintaxis e
inicializa los recursos internos del servidor para su uso posterior.

El servidor de MySQL soporta el uso de parámetros de sustitución posicionales


anónimos con ?.

En el siguiente ejemplo se puede ver cómo se prepara la sentencia SQL, luego


se une la sentencia al texto que se desea buscar y se ejecuta. Con doble barra
(//) se pueden ver comentarios de ayuda para comprender el código y visualizar
en dónde se realiza cada etapa:

//Función en PHP que trae una lista de miembros cuyo nombre contiene el texto
ingresado por el usuario
public function lista($texto)
{
// En la siguiente línea se prepara la sentencia SQL de plantilla para
ejecutarla más tarde
$stmt = $this->getHandle()->prepare('select * from members where nombre
like ? order by nombre;');
// La siguiente línea simplemente agrega los símbolos de porcentaje delante
del texto a buscar y al final.
$texto = '%' . $texto . '%';
// A continuación se vincula la sentencia SQL con el texto a buscar
$stmt->bind_param('s', $texto); // 's' especifica el tipo de variable =>
'string' en este caso. Si se utiliza para números sería 'i' de integer.
// Por último ejecutamos la búsqueda
$stmt->execute();
// $resulta almacena el resultado obtenido de la búsqueda
$result = $stmt->get_result();
return $result;
}

• Utilizar herramientas en el IDE. Permiten detectar en tiempo real las malas


prácticas de desarrollo incluyendo problemas de seguridad.

33
• Prohibir funciones no seguras. Investigar el lenguaje de programación en
cuestión y no utilizar funciones que puedan ocasionar un buffer overflow
o desbordamiento de búfer (error de software que se produce cuando un
programa no controla adecuadamente la cantidad de datos que se copian
sobre un área de memoria reservada a tal efecto).

En el siguiente ejemplo podemos ver que se realiza una correcta validación de


los datos cuando un usuario quiere iniciar sesión en el sistema, además de tener
en cuenta vulnerabilidades de XSS, SQL injection, ataques de fuerza bruta y un
correcto uso de contraseñas cifradas. Con doble barra (//) se indican comentarios
para ayudar a comprender el código e indicar dónde se protege de las posibles
vulnerabilidades:

function login($email, $password, $mysqli) {


// En las siguiente línea de código se protege de SQL Injection. Se utilizan
declaraciones preparadas (prepared statement), esto significa que la
inyección de SQL no será posible.
if ($stmt = $mysqli->prepare("SELECT id, nombre, password, salt FROM
members WHERE email = ?
LIMIT 1")
) {
$stmt->bind_param('s', $email); // Une “$email” al parámetro.
$stmt->execute(); // Ejecuta la consulta preparada.
$stmt->store_result();

// Obtiene las variables del resultado.


$stmt->bind_result($user_id, $nombre, $db_password, $salt);
$stmt->fetch();

// Hace el hash de la contraseña con una sal única. Esto demuestra buenas
prácticas para el uso de contraseñas cifradas.
$password = hash('sha512', $password . $salt);
if ($stmt->num_rows == 1) {
// Si el usuario existe, revisa si la cuenta está bloqueada por muchos
intentos de conexión. Esto permite evitar ataques de fuerza bruta. La función
utilizada se llama checkbrute:

if (checkbrute($user_id, $mysqli) == true) {


// Entonces la cuenta está bloqueada.
return false;
} else {
// Si la cuenta no está bloqueada revisa que la contraseña en la base de
datos coincida con la contraseña que el usuario envió.
if ($db_password == $password) {
// ¡La contraseña es correcta!

//Luego obtiene el agente de usuario del usuario en sí.


$user_browser = $_SERVER['HTTP_USER_AGENT'];
34
//En la siguiente línea se protege de XSS ya que podríamos imprimir este
valor.
$user_id = preg_replace("/[^0-9]+/", "", $user_id);
$_SESSION['user_id'] = $user_id;

$_SESSION['login_string'] = hash('sha512', $password .


$user_browser);

// Si el software llega hasta aquí, el inicio de sesión es exitoso


return true;
} else {
// El código restante es donde continúa la lógica del código.

// La contraseña no es correcta.
// Se graba este intento en la base de datos.
$now = time();
$mysqli->query("INSERT INTO login_attempts(user_id, time)
VALUES ('$user_id', '$now')");
return false;
}
}
} else {
// El usuario no existe.
return false;
}
}
}

35
Revisiones de código seguro
Análisis de código estático y dinámico que trataría, tal y como su nombre indica,
de un análisis del código en estático (mirando el código sin que la aplicación se
esté ejecutando) y un análisis con la aplicación ejecutándose.

Una de las mayores ventajas de utilizar el análisis de código estático en todo el


SDLC es que las pruebas pueden automatizarse completamente, lo que permite
a los desarrolladores implementar prácticas de codificación seguras y desinfectar
todo el proceso de desarrollo con un mínimo esfuerzo. Los plazos de lanzamiento
del producto se pueden cumplir fácilmente sin recortar esquinas ni liberar
riesgosos problemas de seguridad.

En un SDLC seguro, las herramientas de análisis de código estático pueden


encontrar rápidamente y ayudar a los desarrolladores a protegerse contra las
inyecciones SQL, inyección de código en la aplicación (XSS), comandos no
autorizados transmitidos por un usuario en el cual el sitio web confía (CSRF) y
otros ataques maliciosos. Sin un SDLC seguro que utilice análisis de código
estático, no hay garantía de que una aplicación se publique sin vulnerabilidades
de seguridad.

36
Penetration testing
Por último, el test de penetración y seguridad que trataría de realizar una
auditoría de hacking ético de seguridad con la finalidad de detectar las
vulnerabilidades y subsanarlas realizando al final una configuración de
seguridad. Este test consiste en pruebas ofensivas contra los mecanismos de
defensa existentes en el sistema y la plataforma en donde se ejecuta (servidor).

El objetivo de estas pruebas es verificar bajo situaciones extremas cuál es el


comportamiento de los mecanismos de defensa, específicamente, se busca
detectar vulnerabilidades en los mismos. Estas pruebas comprenden desde el
análisis de dispositivos físicos y digitales, hasta el análisis del factor humano
utilizando Ingeniería Social.

Un pentesting no se detiene en descubrir vulnerabilidades. Va al siguiente


paso para explotar estas vulnerabilidades con el objetivo de probar y dirigir
ataques simulados que pueden venir del mundo real contra la seguridad de la
compañía y del software.

Se utiliza software y métodos manuales para hacer un primer reconocimiento.


Se colecta información del negocio desde la perspectiva del hacker. Luego se
identifican puntos de entrada vulnerables y, finalmente, se abre una brecha en el
sistema y se genera un reporte de cómo se hizo.

Para desarrollar la actividad de un Penetration testing es necesario conocer


herramientas como analizadores de puertos, interceptadores de tráfico web,
inyectores de código, entre otras. Algunas de ellas pueden ser:

Kali Linux
Aunque no es la única, Kali Linux ofrece una distribución de Linux completa
orientada a la auditoría de seguridad informática y el hacking ético. Es una de
las mejores herramientas de intrusión.

37
Nmap (network mapper)
Es un escáner de puertos y nos ofrece respuestas a preguntas como: ¿qué
puerto están abiertos en una máquina? ¿qué es lo que hay detrás de esos
puertos?

Acceder a esa información es clave en las primeras fases de trabajo de cualquier


pentatester. Utilizarla equivale a llamar a la puerta de una máquina que nos
interesa y preguntar: ¿hay alguien ahí? ¿quién es? En este sentido, tiene soporte
para llamadas ping, es capaz de detectar protocolos de servicio y las versiones
de las aplicaciones que se encuentran detrás de cada puerto o acceder al ID de
un dispositivo.

Metasploit
Su objetivo es encontrar agujeros de seguridad en todo tipo de redes,
aplicaciones y dispositivos. El uso de Metasploit suele seguir al de nmap (o
similar), una vez el investigador ha accedido a más información sobre tipo de
sistema operativo, aplicación o dispositivo de hardware que se encuentra “al otro
lado”. En caso de querer defender una red corporativa, el uso de Metasploit
puede ser fundamental a la hora de entender dónde se encuentran los eslabones
más débiles.

Wireshark
La herramienta captura tráfico en tiempo real y analiza a nivel “microscópico” qué
es lo que está pasando. Aunque los pentatesters lo utilizan fundamentalmente
para analizar el tráfico a nivel TCP/IP, la herramienta es capaz de analizar
cientos de protocolos, de modo que el investigador pueda conocer qué es
exactamente lo que se está moviendo dentro de una red.

sqlmap
Automatiza el proceso de detectar y explotar fallos y brechas de seguridad en
servidores de base de datos SQL. Permite realizar inyección de código SQL
automáticamente (lo ya mencionado como “SQL Injection”).

38
John the Ripper
Es un programa de criptografía que aplica fuerza bruta para descifrar
contraseñas.

Hydra
Esta herramienta se encarga de descifrar las contraseñas de cualquier servicio
on-line. Para ello tiene soporte para protocolos como SSH, FTP, IMAP, IRC entre
otros.

aircrack-ng
Aircrack-ng es una suite de software de seguridad inalámbrica. Consiste en un
analizador de paquetes de redes, recupera contraseñas WEP y WPA/WPA2-
PSK y otro conjunto de herramientas de auditoría inalámbrica.

Burp Suite
Permite realizar pruebas de seguridad de aplicaciones web. Entre las funciones
básicas se encuentra el servidor proxy que permite inspeccionar y modificar el
tráfico haciendo de intermediario entre el navegador y la aplicación destino, el
escáner de vulnerabilidades que automatiza la detección de varios tipos de
vulnerabilidades de aplicaciones web, el repetidor se utiliza para modificar y
reenviar solicitudes individuales al servidor, y muchas otras funcionalidades.

OWASP Zed Attack Proxy


Es un escáner de seguridad web de código abierto. Pretende ser utilizado como
una aplicación de seguridad y como una herramienta profesional para pruebas
de penetración.

39
7. Herramienta web de seguridad en cada
etapa
Una forma de contribuir a la implementación de un ciclo seguro del SDLC es
publicando información como tips o ejemplos que evidencien las buenas
prácticas para un software seguro en la actualidad. Una herramienta web
accesible por muchos usuarios es ideal para este fin.

El principal objetivo es que los usuarios de esta web puedan ver también los
ejemplos demostrados en esta documentación más otros que se vallan
publicando a medida que pase el tiempo. Siempre actualizando la web con las
mejores prácticas de seguridad.

URL de la herramienta web:


https://appsweb.dev/cybersecurity-guide

Imagen 20. Código QR para acceder a la herramienta web

40
8. Conclusiones
Como conclusiones generales de la tesis observamos que las compañías de
software actuales están comenzando a comprender que la identificación y
remediación temprana de problemas posee un costo inversamente proporcional
al tiempo que la vulnerabilidad permanece en el sistema.

La instauración de un ciclo de desarrollo seguro mediante la instrumentación de


un modelo de diseño orientado a la seguridad generando sinergia entre el área
de seguridad y de desarrollo, nos acerca un paso más hacia el despliegue de
aplicaciones más fuertes y mucho más rentables.

Es absolutamente crucial que se considere la seguridad durante la fase de


análisis, esto significa que los desarrolladores crearán el producto con el
software en mente. De esta manera, la seguridad no será un pensamiento
posterior.

Dedicando atención cuando se toman los requerimientos también concienciamos


al cliente para poder dedicar tiempo en esta área de desarrollo que se da por
cubierta, erróneamente, en la mayoría de los casos.

Es mucho menos probable que el software tenga posibles vectores de ataque,


ya que el equipo de desarrollo se encargará de eliminarlos (o no incluirlos en
primer lugar) y eliminar esa posibilidad.

Evitará que la información del cliente sea robada o que la red sea comprometida
lo que resultaría en un desastre para su negocio.

Agregar tareas de seguridad durante la fase de requisitos es una solución más


rentable que mirar un código inseguro una vez que el software ya se ha
desarrollado. La inclusión de la seguridad desde el comienzo del SDLC puede
ayudar a la compañía a ahorrar tiempo y cuidar el presupuesto.

41
Todos los empleados, en todos los niveles organizacionales, deben tener
entrenamiento, deben tener conocimiento de los programas de seguridad
existentes en la organización y colaborar, en el marco de sus funciones y
habilidades para mantenerla.

La falta de conciencia en los programadores sobre la responsabilidad de crear


un software que trabaje con datos del cliente ocasiona que no se den cuenta de
los errores de seguridad que están cometiendo, una de las razones puede ser la
falta de formación en el área de seguridad informática.

Es necesario que los desarrolladores obtengan las herramientas adecuadas para


hacer su trabajo. Deben poder desarrollar un código seguro, por lo tanto, la
capacitación continua en seguridad informática es fundamental.

El análisis del código fuente también es muy importante. Los entornos ágiles que
buscan actualizarse a un SDLC seguro son el lugar perfecto para implementar el
análisis del código fuente. Una sólida herramienta de análisis de código fuente
ofrece las ventajas de escaneo incremental de código, escaneo de múltiples
idiomas, informes rápidos y asistencia a desarrolladores para mitigar
vulnerabilidades en su código. Con el análisis del código fuente, las aplicaciones
pueden ser protegidas incluso antes de estar en producción, aunque después de
la producción, la seguridad continúa siendo muy importante.

Debemos continuar aprendiendo constantemente. La seguridad es un campo en


evolución. La seguridad del desarrollo de aplicaciones requiere un ciclo
constante de revisión, educación e implementación. Las mejores prácticas de
hoy pueden no ser las mejores prácticas para mañana. Lo más importante es
que todos los integrantes del equipo reconozcan que la seguridad es el trabajo
de todos y se comprometan a su parte en esta meta.

Como contrapartida, la inversión adicional por parte del equipo para la


implementación y adopción inicial del modelo seguro del SDLC puede demorar
bastante tiempo hasta que todo el equipo de programadores lo utilice.
42
La mejor estrategia sería comenzar por la formación y preparación del
ecosistema, como la formación educativa de los desarrolladores y la preparación
de las herramientas a utilizar (por ejemplo, integrando el análisis de código en el
entorno de desarrollo o IDE). Luego una evaluación exhaustiva de la seguridad
de las aplicaciones creadas, si es posible junto con el equipo de calidad y
pruebas.

El siguiente paso sería la implementación del SDLC seguro junto con el uso de
herramientas que automaticen el análisis del código estático y dinámico para
cumplir con todo el proceso de buenas prácticas, sin olvidar la mejora continua
de la seguridad.

Conclusiones del alumno:

La realización del TFM permitió asentar todos los conocimientos adquiridos en


el tiempo de cursado del Máster y a la vez adquirir numerosos conocimientos
como las nuevas tecnologías utilizadas.

43
9. Anexos
Guía de referencia para prácticas de codificación segura de OWASP: esta
guía se integra como anexo ya que es muy importante y abarca muchos aspectos
técnicos que permitirán a un desarrollador de software la utilización de las
buenas prácticas en todos los aspectos del desarrollo de software. La misma se
orienta al ambiente web, pero es fácilmente aplicable a otras plataformas como
por ejemplo aplicaciones de escritorio (Windows).

Validación de entradas

1. Realizar todas las validaciones de datos en un sistema confiable (por


ejemplo: el servidor).
2. Identificar todas las fuentes de datos y clasificarlos como confiables o no
confiables. Validar todos los datos provenientes de fuentes no confiables (por
ejemplo: bases de datos, secuencias de archivo, etc.).
3. Debería existir una rutina de validación de datos de entrada centralizada para
la aplicación.
4. Especificar sets de caracteres apropiados, tales como UTF-8, para todas las
fuentes de entrada.
5. Codificar los datos a un set de caracteres común antes de validar
(Canonicalización).
6. Todas las fallas en la validación deben terminar en el rechazo del dato de
entrada.
7. Determinar si el sistema soportará sets de caracteres UTF-8 extendidos y de
ser así, validarlos luego de terminada la decodificación del UTF-8.
8. Validar todos los datos brindados por el cliente antes de procesarlos,
incluyendo todos los parámetros, URLs y contenidos de cabeceras HTTP (por
ejemplo, nombres de Cookies y valores). Asegurarse de incluir post backs
automáticos desde JavaScript, Flash u otro código embebido.
9. Verificar que los valores de la cabecera tanto en solicitudes como en
respuestas contengan solo caracteres ASCII.

44
10. Validar datos redireccionados (un atacante puede enviar contenido malicioso
directamente en el destino de la redirección, eludiendo entonces la lógica de
la aplicación y cualquier otra validación realizada antes de la redirección).
11. Validar tipos de datos no esperados.
12. Validar rangos de datos.
13. Validar largos de datos.
14. Validar toda entrada con una lista “blanca” que contenga una lista de
caracteres aceptados, siempre que sea posible.
15. Si es necesario, permitir el ingreso de algún carácter considerado peligroso,
asegúrese de implementar controles adicionales tales como la codificación
de la salida, API de seguridad y el registro del uso de tales datos a lo largo
de la aplicación. Entre los ejemplos de caracteres peligrosos podemos
encontrar: < > ” ’ % ( ) & + \ / \’ \”.
16. Si su rutina estándar de validación no contempla el ingreso de los ejemplos
de datos anteriormente ejemplificados, entonces deberán verificarse de
forma puntual.
17. Compruebe si hay bytes nulos (%00).
18. Compruebe si hay caracteres de nueva línea (%0d, %0a, \r, \n).
19. Compruebe si hay caracteres de alteraciones de ruta “punto, punto, barra (../
o ..\). En los casos en que se soportan sets de caracteres UTF-8 extendidos,
implemente representaciones alternativas tales como: %c0%ae%c0%ae/
(utilice la canonicalización como forma de implementar la doble codificación
u otras formas de ofuscación de ataques).

45
Codificación de salidas

20. Realice toda la codificación en un ambiente seguro (por ejemplo: el servidor).


21. Utilice una rutina probada y estándar para cada tipo de codificación de salida.
22. Contextualice la codificación de salida de todos los datos devueltos por el
cliente que se originen desde fuera de la frontera de confianza de la
aplicación. La codificación de entidades HTML es un ejemplo, aunque no sea
suficiente en todos los casos.
23. Codifique todos los caracteres salvo que sean reconocidos como seguros por
el interpretador al que están destinados.
24. Sanitice contextualmente todas las salidas de datos no confiables hacia
consultas SQL, XML y LDAP.
25. Sanitice todas las salidas de datos no confiables hacia un comando del
sistema operativo.

46
Administración de autenticación y contraseñas

26. Requerir autenticación para todos los recursos y páginas excepto aquellas
específicamente clasificadas como públicas.
27. Todos los controles de autenticación deben ser efectuados en un sistema en
el cual se confíe. (por ejemplo: el servidor).
28. Establecer y utilizar servicios de autenticación estándares y probados cuando
sea posible.
29. Utilizar una implementación centralizada para todos los controles de
autenticación, incluyendo librerías que llamen a servicios externos de
autenticación.
30. Segregar la lógica de la autenticación del recurso solicitado y utilizar
redirección desde y hacia el control centralizado de autenticación.
31. Todos los controles de autenticación deben fallar de una forma segura.
32. Todas las funciones administrativas y de administración de cuentas deben
ser al menos tan seguras como el mecanismo primario de autenticación.
33. Si la aplicación administra un almacenamiento de credenciales, se debe
asegurar que únicamente se almacena el hash con sal (salty hash) de las
contraseñas y que el archivo/tabla que guarda las contraseñas y claves solo
puede ser escrito por la aplicación (si es posible, no utilizar el algoritmo de
hash MD5).
34. El hash de las contraseñas debe ser implementado en un sistema en el cual
se confíe. (por ejemplo: el servidor).
35. Validar los datos de autenticación únicamente luego haber completado todos
los datos de entrada, especialmente en implementaciones de autenticación
secuencial.
36. Las respuestas a los fallos en la autenticación no deben indicar cual parte de
la autenticación fue incorrecta. A modo de ejemplo, en lugar de “usuario
invalido” o “contraseña invalida”, utilizar “usuario y/o contraseña inválidos” en
ambos casos. Las repuestas a los errores deben ser idénticas tanto a nivel
de lo desplegado como a nivel de código fuente.
37. Utilizar autenticación para conexiones a sistemas externos que involucren
información o funciones sensibles.

47
38. Las credenciales de autenticación para acceder a servicios externos a la
aplicación deben ser encriptados y almacenados en ubicaciones protegidas
en un sistema en el cual se confíe (ejemplo: el servidor). El código fuente NO
es una ubicación segura.
39. Utilizar únicamente pedidos del tipo HTTP POST para la transmisión de
credenciales de autenticación.
40. Utilizar únicamente conexiones encriptadas o datos encriptados para el envío
de contraseñas que no sean temporales (por ejemplo: correo encriptado).
Contraseñas temporales como aquellas asociadas con reseteos por correo
electrónico, pueden ser una excepción.
41. Hacer cumplir por medio de una política o regulación los requerimientos de
complejidad de la contraseña. Las credenciales de autenticación deben ser
suficientes como para resistir aquellos ataques típicos de las amenazas en el
entorno del sistema. Ej.: obligar el uso de combinaciones de caracteres
numéricos/alfanuméricos y/o caracteres especiales.
42. Hacer cumplir por medio de una política o regulación los requerimientos de
longitud de la contraseña. Comúnmente se utilizan ocho caracteres, pero
dieciséis es mejor, adicionalmente considerar el uso de frases de varias
palabras.
43. No se debe desplegar en la pantalla la contraseña ingresada. A modo de
ejemplo, en formularios web, utilizar el tipo de entrada “password” (input type
“password”).
44. Deshabilitar las cuentas luego de un número establecido de intentos inválidos
de ingreso al sistema. A modo de ejemplo, cinco intentos fallidos es lo común.
La deshabilitación de la cuenta debe ser por un periodo de tiempo suficiente
como para desalentar una inferencia de credenciales por fuerza bruta, pero
no tan alto como para permitir un ataque de negación de servicio.
45. El cambio y reinicio de contraseñas requieren los mismos niveles de control
como aquellos asociados a la creación y autenticación de cuentas.
46. Las preguntas para el reinicio de contraseñas deben contemplar un amplio
rango de respuestas aleatorias. A modo de ejemplo: “libro favorito?” es una
mala pregunta dado que “la biblia” es una respuesta muy común.

48
47. Si se utiliza un reinicio de contraseña por correo electrónico, únicamente
enviar un link o contraseñas temporales a casillas previamente registradas
en el sistema.
48. Las contraseñas y links temporales deben tener un corto periodo de validez.
49. Forzar el cambio de contraseñas temporales luego de su utilización.
50. Notificar a los usuarios cada vez que se produce un reinicio de contraseña.
51. Prevenir la reutilización de contraseñas.
52. Las contraseñas deben tener al menos un día de antigüedad antes de poder
ser cambiadas, de forma de evitar ataques de reutilización de contraseñas.
53. Hacer cumplir por medio de una política o regulación los requerimientos de
cambio de contraseña. Los sistemas críticos pueden requerir cambios más
frecuentes que otros sistemas. El tiempo entre cada reseteo debe ser
controlado administrativamente.
54. Deshabilitar la funcionalidad de “recordar” campos de contraseñas.
55. El último acceso (fallido o exitoso) debe ser reportado al usuario en su
siguiente acceso exitoso.
56. Implementar un monitoreo para identificar ataques a múltiples cuentas
utilizando la misma contraseña. Este patrón de ataque es utilizado para
superar bloqueos estándar cuando los nombres de usuario pueden ser
obtenidos o adivinados de alguna forma.
57. Cambiar todos los usuarios y contraseñas por defecto o deshabilitar las
cuentas asociadas.
58. Re autenticar usuarios antes de la realización de operaciones críticas.
59. Utilizar autenticación multi-factor para las cuentas más sensibles o de mayor
valor.
60. Si se utiliza un código de una tercera parte para la autenticación,
inspeccionarlo minuciosamente para asegurar que no se encuentre afectado
por cualquier código malicioso.

49
Administración de sesiones

61. Utilizar los controles del servidor o del framework para la administración de
sesiones. La aplicación solo debe reconocer estos identificadores como
válidos.
62. La creación de identificadores de sesión solo debe ser realizada en un
sistema en cual se confíe (por ejemplo: el servidor).
63. Los controles de administración de sesiones deben utilizar algoritmos que
generen identificadores suficientemente aleatorios.
64. Definir el dominio y ruta para las cookies que contienen identificadores de
sesión autenticados con un valor apropiadamente estricto para el sitio.
65. La función de logout debe terminar completamente con la sesión o conexión
asociada.
66. La función de logout debe estar disponible en todas las páginas protegidas
por autenticación.
67. Establecer un tiempo de vida de la sesión lo más corto posible, balanceando
los riesgos con los requerimientos del negocio. En la mayoría de los casos,
nunca debería ser superior a varias horas.
68. Deshabilitar logeos persistentes y efectuar finalizaciones periódicas de
sesiones, incluso cuando la sesión se encuentra activa.
69. Si una sesión fue establecida antes del login, cerrar dicha sesión y establecer
una nueva luego de un login exitoso.
70. Generar un nuevo identificador de sesión luego de cada re-autenticación.
71. No permitir logeos concurrentes con el mismo usuario.
72. No exponer identificadores de sesión en URLs, mensajes de error ni logs. Los
identificadores de sesión solo deben ser ubicados en la cabecera de la cookie
HTTP. A modo de ejemplo, no transmitir el identificador de sesión como un
parámetro GET.
73. Proteger la información sobre las sesiones del lado del servidor
implementando los controles de acceso apropiados.
74. Generar un nuevo identificador de sesión y desactivar el anterior de forma
periódica. De esta forma se pueden mitigar algunos escenarios de robo de
sesiones donde el identificador se compromete.

50
75. Generar un nuevo identificador de sesión si la seguridad cambia de HTTP a
HTTPS, como puede suceder durante la autenticación. Dentro de la
aplicación es recomendable usar siempre HTTPS en lugar de cambiar entre
HTTP y HTTPS.
76. Manejo de sesión complementario para operaciones sensible del lado del
servidor, como pueden ser: gestión de cuentas o utilizando tokens o
parámetros por sesión. Este método puede ser utilizado para prevenir
ataques de Cross Site Request Forgery Attacks (Falsificación de petición en
sitios cruzados, conocido por sus siglas CSRF).
77. Manejo de sesión complementario para operaciones sensible o críticas
utilizando tokens o parámetros por pedido (per request) en lugar de por
sesión.
78. Configurar el atributo “seguro” para las cookies transmitidas sobre una
conexión TLS.
79. Configurar las cookies con el atributo HttpOnly, salvo que se requiera
específicamente scripts del lado del cliente en la aplicación, para leer o
configurar una cookie.

51
Control de Acceso

80. Utilizar únicamente objetos confiables del sistema. (por ejemplo: objetos de
sesión del servidor para la toma de decisiones de autorización).
81. Utilizar un único componente para el chequeo de autorizaciones para todo el
sitio. Esto incluye librerías que llamen a servicios de autorización externos.
82. Los controles de acceso en caso de falla deben actuar en forma segura.
83. Denegar todos los accesos en caso de que la aplicación no pueda acceder a
la información de configuración de seguridad.
84. Requerir controles de autorización en cada solicitud o pedido, incluyendo
aquellos creados por scripts en el servidor, “includes” y pedidos desde AJAX
o Flash desde el lado del cliente.
85. Separar lógica privilegiada de otro código de la aplicación.
86. Restringir acceso a ficheros u otros recursos, incluyendo aquellos fuera del
control directo de la aplicación, únicamente a usuarios autorizados.
87. Restringir el acceso a URLs protegidas, solo a usuarios autorizados.
88. Restringir el acceso a funciones protegidas, solo a usuarios autorizados.
89. Restringir las referencias directas a objetos, solo a usuarios autorizados.
90. Restringir el acceso a servicios, solo a usuarios autorizados.
91. Restringir el acceso a información de la aplicación, solo a usuarios
autorizados.
92. Restringir el acceso a usuario, atributos y política de información utilizada por
los controles de acceso.
93. Restringir el acceso a información relevante de la configuración, solo a
usuarios autorizados.
94. Las reglas de control de acceso implementadas del lado del servidor y en la
capa de presentación, deben coincidir.
95. Si existen datos de estado que deben ser guardados en el cliente, use cifrado
y chequeos de integridad del lado del servidor para poder evaluar el estado.
96. Requerir flujos de aplicación que cumplan con las reglas del negocio.
97. Limitar el número de transacciones que un usuario común o un dispositivo
puede desarrollar en un cierto período de tiempo.

52
98. Utilizar el header “referer” solo como un chequeo complementario. Nunca
debe ser utilizado como chequeo de autorización, ya que es posible
modificarlo.
99. Si sesiones de autenticación extensas son permitidas, periódicamente hay
que revalidar la autorización de los usuarios y asegurar que sus privilegios no
han sido modificados.
100. Implementar auditorías de cuentas y requerir que se deshabiliten las
contraseñas de las cuentas.
101. La aplicación debe permitir deshabilitar y terminar cuentas una vez que se
termina la autorización (cambio de rol, estatus de empleo, etc.).
102. Cuentas de servicio o cuentas soportando conectividad deben tener el
mínimo privilegio.
103. Crear una política de control de acceso para documentar las reglas del
negocio de la aplicación, los tipos de datos, criterios para autorización de
acceso y los controles asociados para otorgarlos y controlarlos. Esto incluye
la identificación de accesos requeridos tanto para los datos como para los
sistemas.

53
Prácticas Criptográficas

104. Todas las funciones de criptografía de la aplicación deben ser


implementadas en sistemas confiables (por ejemplo: el servidor).
105. Proteger secretos maestros (master secrets) del acceso no autorizado.
106. Los módulos de criptografía deberían en caso de falla, fallar en forma
segura.
107. Todos los números aleatorios, nombres aleatorios, GUIDs, y frases
aleatorias, deberían generarse utilizando módulos aprobados para su
generación.
108. Los módulos criptográficos del sistema deben cumplir con FIPS 140-2 o
con su estándar equivalente. (Ver
http://csrc.nist.gov/groups/STM/cmvp/validation.html).
109. Establecer y utilizar una política y un proceso de cómo manejar las claves
criptográficas.

54
Manejo de errores y Logs

110. No difundir información sensible en respuestas de error, incluyendo


detalles del sistema, identificadores de sesión o información de la cuenta.
111. Utilizar manejadores de errores que no muestren información de
debugging o de memoria.
112. Implementar mensajes de error genéricos y utilizar páginas de error
adaptadas.
113. La aplicación debería manejar los errores de la aplicación y basarse en la
configuración del servidor.
114. Liberar espacio de memoria en cuanto una condición de error ocurra.
115. La lógica para la gestión de errores debe estar asociada a que los
controles de seguridad no permitirán acceso por defecto.
116. Todos los controles de logging deben estar implementados en sistemas
confiables.
117. El logging de controles de acceso debe incluir tanto los casos de éxito
como de falla.
118. Hay que asegurar que los datos del registro de log contengan información
importante.
119. Hay que asegurar que los logs de entrada que incluyen información no
segura no serán ejecutados en interfaces o aplicativos.
120. Restringir el acceso a los logs, solo a personal autorizado.
121. Utilizar una rutina centralizada para todas las operaciones de logging.
122. No guardar información sensible en logs, incluyendo detalles innecesarios
del sistema.
123. Hay que asegurar que existen mecanismos para conducir un análisis de
los logs.
124. Registrar en un log todas las fallas de validación.
125. Registrar en un log todos los intentos de autenticación, en particular los
fallidos.
126. Registrar en un log todas las fallas en los controles de acceso.
127. Registrar en un log todos los eventos de intento de evasión de controles,
incluyendo cambios en el estado de la información no esperados.

55
128. Registrar en un log todos los intentos de conexión con tokens inválidos o
vencidos.
129. Registrar en un log todas las excepciones del sistema.
130. Registrar en un log todas las funciones administrativas, incluyendo
cambios en la configuración de seguridad.
131. Registrar en un log, todas las fallas de conexión de TLS.
132. Registrar en un log las fallas de los módulos criptográficos.
133. Utilizar una función de hash para validar la integridad de los logs.

56
Protección de datos

134. Implementar el mínimo privilegio, restringir el acceso de los usuarios


solamente a la funcionalidad, datos y sistemas de información que son
necesarios para realizar sus tareas.
135. Proteger todos los almacenamientos temporales (en memoria o archivo -
“caché”) de los datos sensibles guardados en el servidor de los accesos no
autorizados y eliminar todos los archivos y memoria de trabajo temporal tan
pronto como no sean requeridos.
136. Encriptar toda la información altamente sensible almacenada como, por
ejemplo: datos para la verificación de la autenticación, inclusive también en
el servidor. Siempre utilice algoritmos de encriptación que hayan sido
chequeados y con buenos antecedentes. Vea “Prácticas Criptográficas” para
obtener información adicional.
137. Proteja el código fuente del servidor de forma de que no pueda ser
descargado por el usuario.
138. No almacene contraseñas, cadenas de conexión u otra información
sensible en texto claro o de forma que no sea criptográficamente segura del
lado del cliente. Esto incluye incluirla en formatos inseguros tales como: MS
Viewstate, Adobe Flash o código compilado.
139. Remueva los comentarios en el código de producción que sea accesible
por el usuario que puedan revelar información sobre los servidores o
información sensible.
140. Remueva cualquier aplicación que no sea necesaria y la documentación
de los sistemas que pueda revelar información útil para los atacantes.
141. No incluya información sensible en los parámetros del HTTP GET.
142. Deshabilite las funcionalidades de completar automáticamente en
aquellos formularios que contienen información sensible, incluyendo la
autenticación.
143. Deshabilite el almacenamiento temporal del lado del cliente de páginas
que contienen información sensible. “Cache-Control: no-store” debería ser
utilizado en conjunto con el control en el cabezal de HTTP “Pragma: no-
cache”, que es menos efectivo, pero mantiene compatibilidad con HTTP/1.0.

57
144. La aplicación debe de soportar la eliminación de datos sensibles cuando
los datos ya no son requeridos (por ejemplo: información personal o ciertos
datos financieros).
145. Implementar controles de accesos apropiados para los datos sensibles
almacenados en el servidor. Esto incluye memoria temporal, archivos
temporales y datos que solamente puedan ser accedidos por usuarios
específicos del sistema.

Seguridad en las comunicaciones

146. Implemente encriptación para todas las transmisiones de información


sensible. Esto debería incluir TLS para proteger la conexión y se puede
combinar con una encriptación discreta de archivos sensibles en conexiones
que no estén basadas en HTTP.
147. Los certificados TLS deben de ser válidos y contener el nombre de
dominio correcto, no deben estar expirados y deberán ser instalados con los
certificados intermedios si son requeridos.
148. Las conexiones TLS que fallen no deben de transformarse en una
conexión insegura.
149. Utilizar conexiones TLS para todo el contenido que requiera acceso
autenticado y para todo otro tipo de información sensible.
150. Utilizar TLS para las conexiones a sistemas externos que involucren
funciones o información sensible.
151. Utilizar una única implementación estándar de TLS que se encuentre
configurada correctamente.
152. Especificar los caracteres de codificación para todas las conexiones.
153. Filtrar los parámetros que contengan información sensible de los referer
HTTP, cuando existen vínculos a sitios externos.

58
Configuración de los sistemas

154. Asegurarse de que los servidores, los frameworks y los componentes del
sistema están corriendo la última versión aprobada.
155. Hay que asegurar que los servidores, los frameworks y los componentes
del sistema están actualizados con todos los parches emitidos para las
versiones en uso.
156. Deshabilitar el listado de directorio.
157. Restringir el servidor web, los procesos y las cuentas de servicios con el
mínimo privilegio posible.
158. Cuando ocurra una excepción, se debe de fallar seguro.
159. Remover todas las funcionalidades y archivos que no sean necesarios.
160. Remover código de testeo o cualquier funcionalidad que no sea tenida en
cuenta en producción, previo a realizar la puesta en producción.
161. Prevenir la revelación de la estructura de directorios en el archivo
robots.txt colocando directorios que estén disponibles para el índice público
en un directorio raíz aislado. Luego “Deshabilitar” el directorio raíz en el
archivo robots.txt en vez de “Deshabilitar” cada directorio individual.
162. Definir cuáles de los métodos HTTP, GET o POST, la aplicación va a
soportar y si deben de ser manejados de forma diferente en las distintas
páginas de la aplicación.
163. Deshabilitar métodos HTTP innecesarios como extensiones WebDAV. Si
una extensión del método HTTP que soporte manejo de archivos es
necesaria, utilice un mecanismo de autenticación bien comprobado.
164. Si el servidor web maneja HTTP 1.0 y HTTP 1.1, asegurarse que ambos
están configurados de manera similar o asegurarse de entender bien las
diferencias que puedan existir (por ejemplo: el manejo de métodos
extendidos de HTTP).
165. Remover información innecesaria en los cabezales de HTTP de respuesta
referidas al SO, versión del servidor web y frameworks de aplicación.
166. La configuración de seguridad de donde se encuentra almacenada la
aplicación debe de ser listada en un formato legible para su auditoría.

59
167. Implementar un Sistema de Manejo de Activos y registrar los
componentes del sistema en él.
168. Aislar los ambientes de desarrollo de los ambientes de producción y
permitir el acceso solamente a los grupos de desarrollo y testeo
específicamente autorizados. Los ambientes de desarrollo a menudo son
configurados de forma menos segura que los ambientes de producción y los
atacantes pueden utilizar estas diferencias para descubrir vulnerabilidades o
como un camino para poder explotarlas.
169. Implementar un Sistema de Control de Cambios del Software para
manejar y registrar los cambios al código tanto para los ambientes de
desarrollo como para los de producción.

60
Seguridad de Base de Datos

170. Utilice consultas parametrizadas con tipos de datos fuertemente tipados.


171. Utilice validación de las entradas y codificación de las salidas y asegúrese
de manejar los meta caracteres. Si esto falla, no ejecute el comando de la
base de datos.
172. Asegúrese de que todas las variables tengan tipos de datos asociados.
173. La aplicación debe de utilizar el mínimo nivel de privilegios cuando accede
a la base de datos.
174. Utilice credenciales seguras para acceder a la base de datos.
175. Las cadenas de conexión a la base de datos no deben de estar incluidas
en el código de la aplicación. Las cadenas de conexión a la base de datos
deben de estar en un archivo de configuración separado en un sistema
confiable y debería de estar encriptado.
176. Utilice procedimientos almacenados para abstraer el acceso a los datos y
elimine los permisos de las tablas en la base de datos.
177. Cierre la conexión a la base de datos tan pronto como sea posible.
178. Remueva o cambie todas las contraseñas administrativas por defecto.
Utilice contraseñas fuertes o frases o implemente autenticación de múltiples
factores.
179. Deshabilite todas las funcionalidades innecesarias de la base de datos
(por ejemplo: procedimientos almacenados innecesarios, servicios no
utilizados, paquetes de utilidades, instale solo el conjunto mínimo de
funcionalidades y opciones requeridas (reduce el área de ataque)).
180. Eliminar el contenido innecesario incluido por el proveedor (por ejemplo:
esquemas de ejemplo).
181. Deshabilitar las cuentas por omisión que no son necesarias para la
operativa del negocio.
182. La aplicación debería conectarse a la base de datos con credenciales
diferentes para cada nivel de confianza (por ejemplo: usuarios, usuarios solo
lectura, invitados, administrador).

61
Manejo de Archivos

183. No utilizar directamente información provista por el usuario en ninguna


operación dinámica.
184. Exigir autenticación antes de permitir la transferencia de un archivo al
servidor.
185. Permita transferir al servidor únicamente los tipos de archivo (por ejemplo:
pdf, doc, etc) requeridos por la operativa del negocio.
186. Validar los tipos de archivo transferidos verificando la estructura de los
encabezados. La validación del tipo de archivo únicamente por la extensión
no es suficiente.
187. No guardar los archivos transferidos en el mismo contexto que la
aplicación web. Los archivos deben almacenarse en un repositorio específico
o en una base de datos.
188. Evite o restrinja la transferencia de archivos que puedan ser interpretados
por el servidor web (por ejemplo: asp, php, jsp, etc).
189. Eliminar los permisos de ejecución a los archivos transferidos.
190. Implemente una transferencia de archivos segura en UNIX mediante el
uso de discos lógicos y el uso de las rutas (path) correspondientes o mediante
la utilización de un entorno chroot.
191. Cuando se referencie a un archivo existente en el servidor, utilizar una
lista blanca de nombres y extensiones válidas. Validar el contenido del
parámetro pasado contra esta lista blanca y si se encuentra una coincidencia,
denegar la operación o utilizar transferir un archivo predefinido.
192. No utilizar información provista por el usuario para la generación de
redirecciones dinámicas. Si se debe proveer esta funcionalidad, la redirección
debe aceptar únicamente caminos relativos dentro de la URL previamente
establecidos (lista blanca de directorios relativos).
193. No incluir en parámetros nombres de directorios o rutas de archivos, en
su lugar utilizar índices que internamente se asocien a directorios o rutas
predefinidas.
194. Nunca envíe la ruta absoluta de un archivo al cliente.

62
195. Asegúrese que los archivos y recursos de la aplicación sean de solo
lectura.
196. Revise los archivos transferidos por los clientes en busca de virus y
malware.

Manejo de Memoria

197. Utilice controles en la entrada y la salida de información no confiable.


198. Revise dos veces que el largo del buffer sean los requeridos y
especificados.
199. Cuando utilice primitivas que requieran el número de bytes a copiar, como
ser strncpy(), sea consciente que si el tamaño del buffer destino es igual al
tamaño del buffer origen, el destino que podría quedar es el NULL-byte
requerido del final.
200. Verifique los límites de los buffers si se llama a las funciones dentro de un
loop y asegúrese de no correr riesgo de escribir fuera del espacio reservado.
201. Truncar el largo de todos los strings de entrada a un tamaño razonable
antes de pasarlos a una función de copia o concatenación.
202. Específicamente libere los recursos, no confíe en el garbage collector (por
ejemplo: objetos de conexión, handlers de archivos, etc.)
203. Utilice stacks no ejecutables cuando sea posible (NX bit).
204. Evite el uso de primitivas con vulnerabilidades conocidas (por ejemplo:
printf, strcat, strcpy, etc).
205. Libere adecuadamente la memoria previa a la salida de una función y de
todos los puntos de finalización de la aplicación.

63
Practicas Generales para la Codificación

206. Para las tareas habituales, utilice código probado y verificado en lugar de
crear códigos específicos.
207. Utilice las APIs previstas para el acceso a funciones específicas del
sistema operativo. No permita que la aplicación ejecute comandos
directamente en el sistema operativo, menos aún mediante la invocación de
una shell.
208. Utilizar funciones de control de integridad (hash, CRC o checksum) para
verificar la integridad del código interpretado, bibliotecas, ejecutables y
archivos de configuración previo a su utilización.
209. Utilice locks para evitar múltiples accesos simultáneos a los recursos o
mecanismos de sincronización (por ejemplo: semáforos) para evitar
condiciones de borde (race conditions).
210. Proteja las variables y recursos compartidos de accesos concurrentes
inadecuados.
211. Explícitamente inicialice todas las variables y mecanismos de
almacenamiento de información (por ejemplo: buffers), durante su
declaración o antes de usarlos por primera vez.
212. Las aplicaciones que requieran privilegios especiales deberán elevar los
privilegios solo cuando sea necesario y devolverlos (bajar privilegios) lo antes
posible. Mantener los privilegios especiales únicamente cuando sea
estrictamente necesario.
213. Evitar errores de cálculo comprendiendo la forma en que el lenguaje de
programación maneja las operaciones matemáticas y las representaciones
numéricas. Prestar especial atención a las discrepancias en la cantidad de
bytes utilizados para la representación, la precisión, diferencias entre valores
con y sin signo, truncamiento, conversiones y casting entre tipos de variables,
cálculos “no-numéricos” y como el lenguaje maneja los números demasiado
grandes o demasiado pequeños para su representación.
214. No utilizar datos provistos por el usuario para ninguna función dinámica.
215. Evite que los usuarios introduzcan o modifiquen código de la aplicación.

64
216. Revisar todas las aplicaciones secundarias, código provisto por terceros
y bibliotecas para determinar la necesidad del negocio para su utilización y
validar el funcionamiento seguro, ya que estos pueden introducir nuevas
vulnerabilidades.
217. Implementar mecanismos seguros para las actualizaciones. Si la
aplicación realiza actualizaciones automáticas, utilizar firmas criptográficas
para el código y asegurarse que el cliente que descarga la aplicación verifique
dichas firmas. Utilizar canales encriptados para las transferencias de código
desde el servidor de actualización.

65
10. Glosario

En la siguiente sección se encuentra una lista de palabras y expresiones


clasificadas de un texto, autor, dialecto que son difíciles de comprender y cada
una viene acompañada de su significado o de algún comentario.

Autenticación: Conjunto de Controles utilizados para verificar la identidad de un


usuario o entidad que interactúa con el software
Autenticación Multi-Factor: Proceso de autenticación que le requiere al usuario
producir múltiples y distintos tipos de credenciales. Típicamente son basados en
algo que el usuario tiene (por ejemplo: una tarjeta inteligente), algo que conoce
(por ejemplo: un pin), o algo que es (por ejemplo: datos provenientes de un lector
biométrico).
Caracteres considerados peligrosos: Cualquier carácter o representación
codificada de un carácter que puede afectar la operación intencionada de la
aplicación o sistema asociado por ser interpretado de una manera especial, fuera
del uso intencionado del carácter. Estos caracteres pueden ser utilizados para:
• Alterar la estructura de las sentencias o código existente
• Insertar código inintencionado
• Alterar caminos
• Causar salidas inesperadas de rutinas o funciones
• Causar condiciones de error
• Obtener cualquiera de los efectos anteriores sobre el flujo de aplicaciones
o sistemas
Codificación de Salida: Conjunto de controles que apuntan al uso de una
codificación para asegurar que los datos producidos por la aplicación son
seguros.
Confidencialidad: Propiedad de la información por la que se garantiza que está
accesible únicamente a entidades autorizadas.
Configuración del sistema: Conjunto de controles que ayuda a asegurar que
los componentes de infraestructura que brindan soporte al software fueron
desplegados de manera segura.

66
Consultas parametrizadas (prepared statements): Mantiene la consulta y los
datos separados a través del uso de marcadores. La estructura de la consulta es
definida utilizando marcadores, la consulta SQL es enviada a la base de datos y
preparada, para luego ser combinada con los valores de los parámetros. Esto
previene a las consultas de ser alteradas debido a que los valores de los
parámetros son combinados con la consulta compilada y con el string de SQL.
Control de Acceso: Un conjunto de controles que permiten o niegan el acceso
a un recurso de un usuario o entidad dado.
Datos del registro de log o logs: Debe incluir lo siguiente:
• Time stamp obtenida de un componente confiable del sistema
• Nivel de severidad para cada evento
• Marcado de eventos relevantes a la seguridad, si se encuentran
mezclados con otras entradas de la bitácora
• Identidad de la cuenta/usuario que ha causado el evento
• Dirección IP del origen asociado con el pedido
• Resultado del evento (suceso o falla)
• Descripción del evento
Disponibilidad: Medida de Accesibilidad y Usabilidad del sistema.
Falsificación de petición en sitios cruzados (CSRF): Una aplicación externa
o sitio web fuerza a un cliente a realizar un pedido a otra aplicación en la que el
cliente posee una sesión activa. Las Aplicaciones son vulnerables cuando
utilizan parámetros o URLs predecibles o conocidas y cuando el navegador
transmite automáticamente toda la información de sesión con cada pedido a la
aplicación vulnerable.
Gestión de sesión: Conjunto de controles que ayudan a asegurar que la
aplicación web maneja las sesiones HTTP de forma segura.
Mitigar: Pasos tomados para reducir la severidad de una vulnerabilidad. Estos
pueden incluir remover una vulnerabilidad, hacer una vulnerabilidad más difícil
de explotar, o reducir el impacto negativo de una explotación exitosa.
Prácticas Criptográficas: Conjunto de controles que aseguran que las
operaciones de criptografía dentro de la aplicación son manejadas de manera
segura.

67
Protección de datos: Conjunto de controles que ayudan a asegurar que el
software maneja de forma segura el almacenamiento de la información.
Requerimiento de Seguridad: Conjunto de requerimientos funcionales y de
diseño que ayudan a asegurar que el software se construye y despliega de forma
segura.
Sanitizar: El proceso de hacer seguros datos potencialmente peligrosos a través
de la utilización de remoción, reemplazo, codificación o "escaping" de los
caracteres que lo componen.
Seguridad de Base de Datos: Conjunto de controles que aseguran la
interacción del software con la base de datos de una forma segura y que la base
de datos se encuentra configurada de forma segura.
Seguridad de Comunicaciones: Conjunto de controles que ayudan a asegurar
que el software maneja de forma segura el envío y la recepción de datos.
Sistema: Término genérico que cubre sistemas operativos, servidores web,
frameworks de aplicaciones e infraestructura relacionada.
Validación de entrada: Conjunto de controles que verifican que las propiedades
de los datos ingresados coinciden con las esperadas por la aplicación,
incluyendo tipos, largos, rangos, conjuntos de caracteres aceptados excluyendo
caracteres peligrosos conocidos.
Vulnerabilidad: Debilidad en un sistema que lo hace susceptible a ataque o
daño.
Inyección SQL: método de infiltración de código intruso que se vale de una
vulnerabilidad informática presente en una aplicación en el nivel de validación de
las entradas para realizar operaciones sobre una base de datos.

68
11. Bibliografía utilizada

Proceso para el desarrollo de software. (s.f.). En Wikipedia. Recuperado el 30 de


agosto de 2019 de
https://es.wikipedia.org/wiki/Proceso_para_el_desarrollo_de_software

Datasec (2019). Encuesta sobre estado de la ciberseguridad en las empresas


uruguayas. Uruguay. Recuperado de: https://www.datasec-
soft.com/archivos/datasec-radar-2019.pdf

Ponemon Institute (2017). En 2017 Cost of Data Breach Study. Recuperado de


https://www.ibm.com/downloads/cas/ZYKLN2E3

Panda Security (2015). En 27% of all recorded malware appeared in 2015.


Recuperado de https://www.pandasecurity.com/mediacenter/press-releases/all-
recorded-malware-appeared-in-2015/

Fandom Ticsalborada1 (s.f.) En Principios de la seguridad informática:


Confidencialidad, Integridad y Disponibilidad de la información. Recuperado de
https://ticsalborada1.fandom.com/es/wiki/1._Principios_de_la_seguridad_inform
%C3%A1tica:_Confidencialidad,_Integridad_y_Disponibilidad_de_la_informaci
%C3%B3n

OWASP (2010). En OWASP Secure Coding PracticesQuick Reference Guide.


Recuperado de
https://www.owasp.org/images/0/08/OWASP_SCP_Quick_Reference_Guide_v
2.pdf

CVE Details (2012). En Mcrypt: Security Vulnerabilities. Recuperado de


https://www.cvedetails.com/vulnerability-list/vendor_id-1643/product_id-
23619/Mcrypt-Mcrypt.html

MSDN Security Developer Center (s.f.). Recuperado de


http://msdn.microsoft.com/en-us/security/

69
PHP: Manual de PHP – Manual (2019, Sep 30) [Online]. Disponible:
http://www.php.net/manual/es/index.php.

PRESSMAN, Roger. 2010. Ingeniería de software, un enfoque practico. 7ma. ed.


Madrid: McGraw-Hill.

Francesco Consiglio (2015). En Promote Security throughout your Software


Design phase (SSDLC) Recuperado de https://www.advantio.com/blog/secure-
software-development-life-cycle-design-phase

Caro, A. (s.f.). En MODELOS DE DESARROLLO SEGURO DE SOFTWARE.


Recuperado de http://web.fdi.ucm.es/posgrado/conferencias/AndresCaroLindo-
slides.pdf

Créditos:
Para el desarrollo de pruebas donde se ejemplifica el código utilizado más
diagramas realizados, se utilizaron las siguientes herramientas:

Creately: https://creately.com/
PHPStorm: https://www.jetbrains.com/phpstorm/
WampServer: http://www.wampserver.com/en/

70

View publication stats

También podría gustarte