¿Qué es una condición de carrera?
Dado que los desarrolladores a menudo olvidan que el código puede ser ejecutado por varios subprocesos al mismo tiempo, no prueban el producto para una condición de carrera, aunque este error es bastante común.
Desde el punto de vista del backend, se ve así: varios subprocesos acceden simultáneamente al mismo recurso compartido: variables o archivos para los que no hay bloqueo ni sincronización. Esto conduce a una salida de datos inconsistente.
Aquí hay un ejemplo concreto de tal vulnerabilidad. Digamos que tenemos una aplicación que te permite transferir bonificaciones entre carteras de pago. El atacante tiene dos billeteras: A y B, y cada una tiene 1000 bonificaciones. El diagrama muestra cómo manipulando el tiempo de envío de una solicitud de transacción, un atacante puede aumentar la cantidad de transferencia a su cuenta y hacer 10 bonificaciones de 20.
Existen herramientas automáticas para buscar tales vulnerabilidades. Por ejemplo, RacePWN, que en un tiempo mínimo envía muchas solicitudes HTTP al servidor y acepta la configuración json como entrada, facilitando el proceso de ataque a los ciberdelincuentes. Esto se hace manualmente enviando solicitudes POST.
Condición de raza mortal
En los Estados Unidos, de junio de 1985 a enero de 1987, un error de condición de carrera en una máquina de radioterapia Therac-25 creada por la organización estatal canadiense Atomic Energy of Canada Limited (AECL) provocó seis sobredosis de radiación . Las víctimas recibieron dosis de decenas de miles de alegres. El nivel 1000 se considera letal. Después de las quemaduras resultantes, las víctimas murieron a las pocas semanas. Solo un paciente logró sobrevivir.
Los modelos anteriores de Therac tenían mecanismos de protección de hardware: circuitos de bloqueo independientes que controlan el haz de electrones; bloqueadores mecánicos; disyuntores de hardware; desconectar fusibles. La protección de hardware se ha eliminado en Therac-25. El software era responsable de la seguridad. El dispositivo tenía varios modos de funcionamiento y, debido a un error de condición de carrera, el médico a veces no entendía en qué modo funciona realmente el dispositivo. Durante el proceso judicial, resultó que el software Therac-25 fue desarrollado por un programador, pero AECL no tenía información sobre quién exactamente.
Como resultado del proceso, el gobierno de los Estados Unidos ha endurecido seriamente los requisitos para el diseño y operación de sistemas cuya seguridad es crítica para las personas.
Cómo protegerse
La forma más fácil y económica de resolver el problema de la condición de carrera es diseñar correctamente la arquitectura de la aplicación. Esto es lo que debería preverse para esto.
- Bloquear registros críticos en la base de datos. Hay diferentes formas de asegurarse de trabajar con la grabación de una transmisión en un momento determinado. Lo principal es no bloquear nada innecesario.
- Aislamiento de transacciones en la base de datos , lo que garantiza que las transacciones se comprometan de forma secuencial. Lo más importante aquí es lograr un equilibrio entre seguridad y velocidad.
- . . , , , . , , , .
Nuestro cliente es una tienda de entrega de comestibles en línea que respalda la función de ofrecer descuentos mediante cupones. Durante las pruebas, descubrimos una vulnerabilidad: al enviar una solicitud POST con un valor de cupón. Al enviar una solicitud con diferentes retrasos de tiempo, fue posible obtener un descuento dos veces. Aparentemente, los desarrolladores cometieron un grave error relacionado con el acceso compartido al objeto que se identificó con la compra.
Lo más probable es que hubiera tal pseudocódigo sin mecanismos de sincronización:
…
1 Si promo_flag no está configurado:
2 Price = get_price ()
3 Price - = price * promo_percent;
4 set_price (precio)
5 set_promo_flag ()
...
Aquí, aplicar un código de promoción y establecer la bandera apropiada no es una operación atómica. Lo más probable es que cuando comenzó la segunda aplicación del código promocional, la primera se detuviera en la quinta línea (es decir, aún no se ha ejecutado). En este momento, la función get_price () en la segunda línea devolvió un nuevo valor de precio, ya con un descuento.
Decisión
El problema se resuelve de manera simple:
…
1 purchase_mutex ()
2 Si promo_flag no está configurado:
3 Price = get_price ()
4 Price - = price * promo_percent;
5 set_price (precio)
6 set_promo_flag ()
7 release_mutex ()
...
Ahora, la aplicación del código promocional se realizará completa y completamente una vez. Incluso cuando surja una situación en la que el segundo subproceso intente aplicar el código de promoción mientras el primer proceso ya está ocupado con el procesamiento, no podrá hacerlo. El mutex bloqueará el acceso a la "sección crítica", y el segundo proceso tendrá que esperar hasta que finalice el primero.
La condición de carrera no debe subestimarse. Es mejor dedicar tiempo y recursos a buscar vulnerabilidades para evitar consecuencias imprevistas, incluso para el presupuesto de la empresa.
Blog ITGLOBAL.COM - TI administrada, nubes privadas, IaaS, servicios de seguridad de la información para empresas:
- Cómo encontramos la vulnerabilidad en el servidor de correo del banco y cómo amenazaba
- Seguridad de la información en 2021. Amenazas, tendencias de la industria
- Los sitios populares siguen siendo vulnerables a ataques DDoS masivos
- Por qué los piratas informáticos éticos deberían trabajar juntos para irrumpir en las corporaciones. Entrevista con el cazador de insectos Alex Chapman
- Miedo a la automatización del trabajo y otras tendencias en la ciberseguridad mundial y rusa