Condición de carrera

Para aprender sobre la vulnerabilidad de las condiciones de carrera, comencemos con un ejemplo: imagínate en un autobús, donde todos los asientos están ocupados y varias personas están de pie. Ahora, el destino de uno de los pasajeros sentados ha llegado. Él baja del autobús dejando su asiento vacante. Ves ese asiento vacante y avanzas hacia él. Pero no te das cuenta de que hay un pasajero más en el autobús que se acerca al mismo asiento pero, desde el lado opuesto. Cuando te acercas a ese asiento, ves que el otro pasajero te alcanzó antes y ya ha ocupado el asiento.

Considera este escenario de la vida real.

¿Qué ha sucedido? Bueno, prácticamente experimentaste un concepto que en programación se denomina «la vulnerabilidad de la condición de carrera».

Programáticamente, la condición de carrera es un escenario en el que dos o más subprocesos intentan acceder a un recurso compartido, como una variable o un código, y cambiarlo al mismo tiempo debido a una ejecución indeterminada del subproceso en el algoritmo de programación de subprocesos.

Al igual que en el escenario anterior, ambos pasajeros no se conocen entre sí, la segunda persona llega primero al asiento y así lo consigue. Fue una selección bastante aleatoria. Así aquí:

Recurso compartido: asiento

Tema1: Tú

Tema2: Pasajero que obtuvo el asiento

Después de la ejecución, el valor del recurso compartido (es decir, el asiento) cambia de vacante a ocupado. Bastante simple, no?

¿Cómo se convierte entonces esta simple condición en un defecto crítico?

Supón que estás tratando de reservar un billete en un tren donde solo 1 asiento está vacío. Simultáneamente, otro pasajero también intenta reservar un billete para el mismo asiento. ¿Qué pasa en esta situación?

Veremos aquí en qué consiste una condición de carrera y cómo prevenirla.

¿Qué es una condición de carrera?

Una condición de carrera es una situación indeseable que ocurre cuando un dispositivo o sistema intenta realizar dos o más operaciones al mismo tiempo, pero debido a la naturaleza del dispositivo o sistema, las operaciones deben realizarse en la secuencia adecuada para que se realicen correctamente.

Un ejemplo simple de una condición de carrera es un interruptor de luz. En algunas casas hay múltiples interruptores de luz conectados a una luz de techo común. Cuando se utilizan estos tipos de circuitos, la posición del interruptor se vuelve irrelevante. Si la luz está encendida, mover cualquiera de los interruptores desde su posición actual apaga la luz. Del mismo modo, si la luz está apagada, al mover cualquiera de los interruptores desde su posición actual se enciende la luz. Con eso en mente, imagina lo que sucedería si dos personas intentaran encender la luz usando dos interruptores diferentes exactamente al mismo tiempo. Una instrucción puede cancelar la otra o las dos acciones pueden disparar el circuito.

Las condiciones de carrera se asocian más comúnmente con la informática.

En la memoria o el almacenamiento del ordenador, puede ocurrir una condición de carrera si se reciben comandos para leer y escribir una gran cantidad de datos en casi el mismo instante, y la máquina pretende sobrescribir algunos o todos los datos antiguos cuando aún se están utilizando esos datos.

El resultado puede ser uno o más de los siguientes:

  • un bloqueo del ordenador,
  • una «operación ilegal»,
  • notificación y apagado del programa,
  • errores al leer los datos antiguos o
  • errores al escribir los datos nuevos.

Una condición de carrera también puede ocurrir si las instrucciones se procesan en el orden incorrecto.

Las condiciones de carrera también pueden ser un defecto de seguridad. En esto, los procesos de diferentes programas que no son de confianza se interponen entre los procesos de los programas seguros y hacen que se comporten mal. Esto hace que el atacante logre causar el problema. Estos escenarios se denominan «no atómicos».

Elementos

Los elementos que forman una condición de carrera son los siguientes.

Hilo

El hilo es un proceso de separación de las diferentes aplicaciones que se ejecutan a la vez en un ordenador. Es la ruta de ejecución de un programa. Los hilos ejecutan procesos.

El sistema operativo asigna tiempo de procesador a los subprocesos para la ejecución de sus tareas. Un solo proceso puede contener múltiples hilos de ejecución. Los hilos mantienen sus propios manejadores de excepciones, prioridades de programación y un conjunto de estructuras que utiliza el sistema operativo para guardar el contexto del hilo. Los hilos son diferentes a los procesos porque los procesos generalmente no pueden compartir memoria directamente y estructuras de datos mientras que los hilos pueden.

Multihilo

Los sistemas requieren múltiples procesos para ejecutarse al mismo tiempo. Un sistema operativo que permite crear múltiples tareas.

El efecto de la ejecución simultánea de múltiples hilos de múltiples procesos dividiendo el tiempo de procesador disponible entre los hilos en proceso es conocido como multihilo. Estos hilos comparten los recursos del proceso pero se ejecutan independientemente.

El sistema asigna un tiempo de procesador a cada subproceso. El hilo actualmente en ejecución queda suspendido cuando llegue el momento y se reanude otro hilo. Los hilos se ejecutan dentro del mismo programa y por lo tanto leyendo y escribiendo la misma memoria simultáneamente.

Sección crítica

Una sección crítica de un programa es donde se comparte globalmente el acceso a la memoria. Es una sección de código que es ejecutado por múltiples hilos. Aquí la secuencia de la ejecución de los hilos marca la diferencia en el resultado de la ejecución concurrente de la sección crítica.

Mientras ejecuta múltiples hilos dentro de la misma aplicación, pueden acceder múltiples hilos a los mismos recursos. Esto podría iniciar la vulnerabilidad de condición de carrera para el sistema.

Vulnerabilidades de seguridad causadas por las condiciones de carrera

Cuando se le pide a un programa diseñado para manejar tareas en una secuencia específica que realice dos o más operaciones simultáneamente, un atacante puede aprovechar la brecha de tiempo entre el inicio del servicio y el momento en que un control de seguridad entra en vigencia para crear un situación de punto muerto o bloqueo de hilo.

Con un punto muerto, dos o más hilos deben esperar un bloqueo en una cadena circular. Este defecto puede hacer que todo el sistema de software se detenga porque tales bloqueos nunca se pueden adquirir si la cadena es circular.

El bloqueo de subprocesos también puede afectar drásticamente el rendimiento de la aplicación. En este tipo de defecto de concurrencia, un subproceso llama a una operación de larga duración mientras mantiene un bloqueo y evita el progreso de otros subprocesos.

Explotaciones de condiciones de carrera

Las hazañas basadas en las condiciones de carrera son delicadas. Normalmente requieren intentos repetidos para ser ejecutados.

Explotaciones de condiciones de carrera existían en Firefox 2007, Internet explorer 2011, enlace de acceso directo de Windows 2010 y en el sistema operativo Linux.

Condición de carrera en Firefox v2.0.0.10

La versión de Mozilla Firefox anterior a 2.0.0.10 es vulnerable a la condición de carrera en el manejo de la ventana. El encabezado de referencia de estas versiones anteriores de Mozilla Firefox está configurado en la ventana o marco en el que el script se está ejecutando, en lugar de en la dirección del contenido que inició el script, lo que permite a los atacantes remotos falsificación de encabezados de referencia HTTP y omisión basada en referencias de Esquemas de protección CSRF configurando window.location y utilizando un cuadro de diálogo de alerta modal que provoca la referencia incorrecta para ser enviado.

Condición de carrera en Pulse Audio

Pulse Audio es un servidor de sonido habilitado para redes del sistema operativo Linux. Condición de carrera en PulseAudio 0.9.9, 0.9.10 y 0.9.14 permiten a los usuarios locales obtener privilegios a través de vectores que implican la creación de un enlace duro, relacionado con la configuración de la aplicación LD_BIND_NOW a 1, y luego llamar a execv en el destino del enlace simbólico / proc / self / exe.

Un usuario que tiene acceso de escritura a cualquier directorio en el sistema de archivos que contiene / usr / bin puede explotar la vulnerabilidad de condición de carrera para ejecutar código arbitrario con privilegios root.

Enlace de acceso directo de Windows

Shell de Windows en Microsoft Windows XP SP3, Servidor 2003 SP2, Vista SP1 y SP2, Server 2008 SP2 y R2, y Windows 7 permite a los usuarios locales o atacantes remotos ejecutar código arbitrario a través de un archivo de acceso directo, que no se maneja correctamente durante el icono mostrar en el Explorador de Windows.

El archivo .lnk es vulnerable a la condición de carrera, ya que ejecuta el descargado el archivo dll 3 veces simultáneamente. Esto dificulta la explotación adecuada de la víctima en caso de que la carga útil dll intenta escribir cualquier archivo en el disco o intenta acceder y cambiar cualquier otro recurso en el sistema de la víctima.

Copia sucia en escritura (COW)

Dirty Copy on Write también conocido como Dirty COW es una vulnerabilidad de condición de carrera basada en Linux. Esta vulnerabilidad permite a los atacantes escalar el sistema de protección de archivos del kernel de Linux, obtener privilegios de root y así comprometer todo el sistema.

Utilizando la función «mmap» se crea un nuevo espacio virtual para el archivo que se va a cambiar y luego la etiqueta MAP PRIVATE se usa para crear una copia del archivo raíz original. Cada vez que se ejecuta el exploit, creará una copia del archivo original.

La función se utiliza para localizar el rango de direcciones de memoria asignado al archivo raíz principal. El «hilo de procselfmem» se usa para engañar al sistema al creer que la memoria del archivo raíz principal está vacía y escribe la copia del archivo. Así se gana el acceso.

Condición de carrera de Internet Explorer

Microsoft Internet Explorer 6 a 8 son vulnerables a ataques de condición de carrera. Estas versiones permiten el acceso remoto de atacantes para ejecutar código arbitrario o causar una negación de servicio. Esto también se conoce como vulnerabilidad de condición de carrera abierta de ventana.

El atacante compila una página web con código malicioso y cuando un usuario visita esta página, ocurre el exploit. Esto es similar al ataque de Cross Site Scripting.

Vulnerabilidades de condición de carrera en setuid-root / usr / bin / at

Este binario de explotación de condición de carrera permite eliminar cualquier archivo en el sistema de archivos. La utilidad «At» lee comandos de entrada estándar y los agrupa para ser ejecutados en un momento posterior.

Hay dos vulnerabilidades dentro del código que elimina «at» del directorio spool. En la utilidad no maneja adecuadamente los identificadores de trabajo especificados como parámetro a la opción «-r». Permite eliminar trabajos fuera del directorio de cola «at» si el nombre de ruta relativo es usado. Solo se filtran los nombres de ruta absolutos.

«At» verifica la propiedad del archivo y limita al usuario a eliminar solo su propio «at». Desafortunadamente, una condición de carrera ocurre después de que «at» verifica el archivo y antes de que el archivo esté desvinculado. Al alterar la estructura de directorios entre estas dos llamadas al sistema, «at» pueden ser engañado para eliminar otro archivo.

Dado que este código se ejecuta con todos los privilegios de root, estas dos vulnerabilidades pueden permitir que usuarios sin privilegios eliminen cualquier archivo en el sistema de archivos.

Prevenir las condiciones de carrera

En entornos informáticos, las condiciones de carrera se pueden evitar mediante la serialización de la memoria o el acceso al almacenamiento. Esto significa que si los comandos de lectura y escritura se reciben juntos, el comando de lectura se ejecuta y completa primero de manera predeterminada.

En una red, puede ocurrir una condición de carrera si dos usuarios intentan acceder a un canal disponible en el mismo instante, y ningún ordenador recibe notificación de que el canal está ocupado antes de que el sistema otorgue acceso.

Estadísticamente, este tipo de coincidencia probablemente ocurrirá en redes con tiempos de retraso largos, como las que usan satélites geoestacionarios.

Para evitar que se desarrolle tal condición de carrera, se debe diseñar un esquema de prioridad. Por ejemplo, el suscriptor cuyo nombre de usuario comienza con la letra anterior del alfabeto (o el número más bajo) puede tener prioridad por defecto cuando dos suscriptores intentan acceder al sistema dentro de un incremento de tiempo prescrito.

Los hackers puede aprovechar las vulnerabilidades de condición de carrera para obtener acceso no autorizado a las redes.

Las condiciones de carrera ocasionalmente ocurren en puertas lógicas cuando ciertas entradas entran en conflicto. Debido a que el estado de salida de la compuerta tarda una cantidad de tiempo finita y distinta de cero para reaccionar a cualquier cambio en los estados de entrada, los circuitos o dispositivos sensibles que siguen a la compuerta pueden ser engañados por el estado de la salida y, por lo tanto, no funcionan correctamente.

Herramientas para detectar condiciones de carrera

Las aplicaciones concurrentes multiproceso se avecinan como una pesadilla de programación y pruebas. Esto se debe a que las nuevas generaciones de chips de procesador multinúcleo, que obtienen ventajas de rendimiento al agregar procesadores en lugar de aumentar la velocidad del reloj, están llegando al mercado en mayor número y requieren una nueva visión del desarrollo.

Los chips multinúcleo pueden hacer que las técnicas de ajuste de rendimiento existentes fallen. En algunos casos, los programas pueden ejecutarse y luego fallar inesperadamente cuando las condiciones de carrera se activan por defectos de concurrencia inactivos.

Para ayudar a resolver estos problemas, el fabricante de herramientas de calidad de software Coverity, Inc. ha lanzado Coverity Thread Analyzer para Java. El software es una herramienta de análisis dinámico para aplicaciones multiproceso. Se dice que detecta automáticamente defectos de concurrencia que pueden causar corrupción de datos y fallas en las aplicaciones.

Con los programas multiproceso, hay muchas rutas de ejecución posibles. Puede obtener los mismos resultados de diferentes maneras cada vez que se ejecuta el programa. Eso hace que sea especialmente difícil de probar. El Thread Analyzer para Java hace que la detección de condición de carrera sea reproducible y predecible.

Con condiciones de carrera, varios subprocesos intentan acceder a los mismos datos compartidos sin los bloqueos adecuados en su lugar. El analizador Coverity automáticamente instrumenta bytecode, sin cambiar el código fuente, para detectar tales errores. La herramienta también descubre bloqueos de código que no son aparentes inmediatamente en la depuración.

Ejemplos

Estas son algunas de las instancias más impactantes de las condiciones de carrera que se han encontrado.

ChangeTip – condición de carrera en la transferencia de dinero

En ChangeTip, un sitio de propinas de bitcoin ahora desaparecido, los usuarios pueden transferir dinero entre sus saldos de bitcoin y dólar. Existía una condición de carrera en la transferencia de dinero entre los saldos, lo que permite obtener una cantidad infinita de dinero en tus cuentas.

Los sitios web financieros suelen ser propensos a las condiciones de carrera. Se han encontrado condiciones de carrera en múltiples sitios de bitcoin que permiten un retiro infinito de dinero.

Cupones

Otra funcionalidad a tener en cuenta se produce al canjear cupones u otros artículos de un solo uso. Por ejemplo, existe una vulnerabilidad en Instacart que permite canjear el mismo cupón varias veces. Curiosamente, se puede evitar el parche inicial al probar dos cupones diferentes, lo que demuestra que las condiciones de carrera no siempre son fáciles de parchear.

Sistemas de votación

Otros ejemplos de condiciones de carrera a menudo ocurren con los sistemas de votación cuando un usuario solo debe poder emitir un voto. Tal fallo afectó a sitios como Medium , Zendesk , Coinbase y Urban Dictionary.

Casos de borde

Las condiciones de carrera no se limitan a estos ejemplos específicos, y pensar diferente a menudo puede conducir a resultados inesperados.

Por ejemplo, se descubrió una condición de carrera en un programa privado al ejecutar una acción única dos veces que expondría una consulta SQL. Esto se debió a que el elemento de la base de datos se marcó como único, lo que provocó que la base de datos devolviera un error.

En resumen, deben buscarse las condiciones de carrera cada vez que ocurre una acción única, ya sea enviando dinero, canjeando cupones o emitiendo un voto.