Por qué vale la pena probar aplicaciones para condiciones de carrera

Si su aplicación o servicio opera con una moneda interna, debe probarlo para detectar vulnerabilidades de condición de carrera ("condición de carrera" o, más precisamente, "incertidumbre de concurrencia"). La condición de carrera es un "error flotante" que los atacantes pueden aprovechar. La conclusión es que, gracias a la ejecución de código en paralelo, puede acceder a la moneda interna de la aplicación, manipularla y, si lo desea, causar un daño financiero tangible al propietario del servicio. Recientemente, descubrimos este problema con uno de nuestros clientes y ayudamos a resolverlo.







¿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:






All Articles