ClickCease Los errores detrás de las vulnerabilidades - Parte

Tabla de contenidos

Únase a nuestro popular boletín

Únase a más de 4.500 profesionales de Linux y el código abierto.

2 veces al mes. Sin spam.

Los errores detrás de las vulnerabilidades - Parte 1

Joao Correia

31 de octubre de 2022 - Evangelista técnico

Es habitual oír hablar de nuevas vulnerabilidades y exploits, algunos de los cuales incluso reciben nombres de fantasía propios, pero a veces los detalles de cómo aparecen quedan enterrados bajo código de prueba de concepto y puntuaciones de impacto. 

Esta serie de artículos desmitificará estos fallos ocultos proporcionando una visión de los problemas de código reales que están en la base de la mayoría de las vulnerabilidades de seguridad que afectan a los sistemas de todo el mundo. 

Podríamos repasar los distintos fallos y errores del código en el orden que quisiéramos. Pero Mitre ha publicado una lista de los 25 errores más peligrosos en 2022, y es una lista tan buena como cualquier otra, así que vamos a repasarla - explicando cómo los problemas de código conducen a cada uno de estos errores y señalando algunas vulnerabilidades que surgen de tener ese código en una aplicación.

En esta primera entrega de la serie, analizaremos las entradas 25 a 21 de los 25 errores más peligrosos de 2022, según Mitre.

25 - Control inadecuado de la generación de código ("inyección de código")

Este es un problema común cuando un programador no proporciona suficiente código defensivo con respecto a las entradas alimentadas por el usuario - es decir, el software utiliza cualquier entrada que recibe sin desinfectarla y luego utiliza dicha entrada, tal cual, para alimentar la funcionalidad interna.

A un nivel muy bajo, las entradas especialmente diseñadas pueden cambiar el funcionamiento del programa de formas imprevistas, lo que permite a los usuarios tener más control sobre el programa y, en algunos casos, sobre todo el sistema.

Esto lleva a situaciones en las que la entrada se construye cuidadosamente para introducir efectos secundarios no deseados, como corrupción de datos o cambios no intencionados en el flujo del programa.

Un caso especial muy común de este tipo de fallo es la "inyección SQL", que merece una categoría propia más adelante en esta serie de artículos, pero no es más que un caso especial de inyección de código.

Como ejemplo, el uso de "eval()" en PHP es a menudo un "olor" de código que apunta a una posible situación de inyección de código si el valor pasado no se valida adecuadamente de antemano.

24 - Restricción incorrecta de la referencia a entidades externas XML

Los archivos XML pueden contener referencias a documentos externos como parte de su estructura, pero esto puede llevar a una aplicación a cargar documentos fuera del ámbito previsto. Esto puede provocar problemas de recorrido, accesos indebidos a los archivos o que la aplicación dé por buenos datos erróneos.

Esto se aplica a los URI (Identificadores Únicos de Recursos) que apuntan a otros archivos locales o incluso a archivos de Internet mediante el uso de URI file:// o http://.

Además de permitir el acceso a archivos que de otro modo serían inalcanzables, también puede utilizarse para forzar a la aplicación a procesar cantidades desmesuradas de datos alimentándola con documentos inesperadamente grandes, ralentizándola o incluso haciendo que dichas aplicaciones no respondan.

Si la aplicación no lo evita, es posible explotar un sistema creando un archivo XML como:


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>

<stockCheck>

<productId>&xxe;</productId>

</stockCheck>

Y luego observar el resultado.

[Este ejemplo procede de https://portswigger.net/web-security/xxe.]

Si el servidor objetivo es capaz de acceder a otros sistemas internos a los que un atacante normalmente no podría acceder, entonces este fallo podría aprovecharse como trampolín para obtener información de esos sistemas.

Bug 23 - Consumo incontrolado de recursos

Todos los recursos de que dispone una aplicación son limitados: potencia de procesamiento, almacenamiento, ancho de banda de red, capacidad de memoria, conexiones a bases de datos, etc. 

Si la aplicación puede ser engañada para abusar de uno o más de esos recursos, entonces puede agotarlos y hacer que la aplicación, o en algunos casos todo el sistema, parezca no responder o directamente inutilizable.

Puede aparecer en el código como funciones de cálculo intensivo que no están protegidas contra llamadas repetidas (mientras las llamadas anteriores aún no se han completado), o incluso funciones que generan una cantidad desproporcionada de datos a partir de entradas muy pequeñas (por ejemplo, mensajes de error complejos a partir de errores de un solo carácter), que son ambas fuentes potenciales de este tipo de fallo.

Otra manifestación común de este fallo es cuando una aplicación no dispone de los recursos que asignó, lo que provoca errores de memoria agotada o algo similar.

Se trata de un tipo de fallo especialmente atroz que suele ser difícil de diagnosticar antes de que una aplicación llegue a la fase de producción -o debido a pruebas inadecuadas- y que puede dejar una aplicación en un estado de bloqueo, o incluso peor, inesperado.

La mayoría de las herramientas de análisis estático de código disponen de comprobaciones para detectar este tipo de situaciones, pero como el código puede escribirse de muchas formas diferentes, siempre es posible tener un código tan enrevesado que estas herramientas de análisis sean incapaces de detectarlo.

Bug 22 - Ejecución Concurrente Usando Recurso Compartido con Sincronización Inadecuada ("Race Condition")

Cuando varias aplicaciones intentan utilizar el mismo recurso, o incluso varios subprocesos dentro de la misma aplicación, tiene que haber algún tipo de coordinación para asegurarse de que cada uno tendrá el acceso que necesita durante el tiempo que necesite tenerlo. 

Si no es así, pueden darse situaciones en las que una aplicación empiece a escribir en un archivo al mismo tiempo que otra aplicación y al final tengas una mezcla del contenido que se suponía que tenías en el archivo, sólo el contenido de una de las aplicaciones, o incluso sólo un archivo en blanco.

Como este tipo de situación depende mucho de la carga, también es difícil de reproducir e identificar adecuadamente.

Puede afectar a cualquier tipo de recurso, no sólo a los archivos. Por ejemplo, puede afectar a datos en memoria, redes, bases de datos... Tanto es así que con el tiempo se han añadido muchas construcciones específicas del lenguaje para abordar esta situación con el objetivo último de crear un tipo de acceso llamado "atómico", que se garantiza que se produzca por completo o no se produzca en absoluto, asegurando así que no se produzcan lecturas/escrituras parciales.

Algo tan simple como incrementar el valor de una variable (x++) es propenso a este tipo de problemas, ya que la operación se divide en múltiples operaciones a nivel de máquina (leer el valor original de x, incrementarlo, asignar el nuevo valor a x). Si x fuera una variable compartida por múltiples hilos dentro de una aplicación, entonces podría llevar a errores si múltiples hilos intentaran incrementarla al mismo tiempo.

Construcciones del lenguaje como mutexes, semáforos y otros mecanismos de sincronización de hilos se introdujeron específicamente para abordar este tipo de problemas. Basándonos en la prevalencia de vulnerabilidades que provienen de esta clase de bugs, la implementación exitosa de tales construcciones puede ser menos que ideal.

Bug 21 - Falsificación de petición del lado del servidor (SSRF)

Se puede engañar a los servidores para que envíen las respuestas a las consultas a otros destinos distintos de la dirección original de los solicitantes.

Como se describió anteriormente, en el bug #24, es posible hacer que una aplicación acceda a otro contenido incluyendo URIs en archivos XML especialmente diseñados. Si esos archivos residen en una ubicación de terceros, entonces la solicitud parecerá provenir del servidor que procesa el archivo XML en lugar del sistema del atacante. Aunque no es el único fallo que entra en esta categoría, es un claro ejemplo de un servidor/aplicación engañado para iniciar una conexión con un sistema de terceros.

Cualquier entrada que pueda contener una lista de URIs que no estén validadas correctamente puede utilizarse como mecanismo SSRF. 

Por ejemplo, el formato de archivo M3U puede incluir referencias a archivos externos. Si tuvieras un servicio web de codificación de vídeo que aceptara un archivo M3U como lista de contenido, sería posible incluir una referencia a archivos de sistema inaccesibles de otro modo y hacer que se incluyeran como parte de la salida del servicio web.

Resumen
Los errores detrás de las vulnerabilidades - Parte 1
Nombre del artículo
Los errores detrás de las vulnerabilidades - Parte 1
Descripción
Oír hablar de nuevas vulnerabilidades es habitual, pero a veces los detalles de cómo aparecen quedan enterrados. Vamos a desmitificar estos bugs ocultos. 
Autor
Nombre del editor
Tuxcare
Logotipo de la editorial

¿Desea automatizar la aplicación de parches de vulnerabilidad sin reiniciar el núcleo, dejar el sistema fuera de servicio o programar ventanas de mantenimiento?

Más información sobre Live Patching con TuxCare

Conviértete en escritor invitado de TuxCare

Empezar

Correo

Únete a

4,500

Profesionales de Linux y código abierto

Suscríbase a
nuestro boletín