Construir con IA

La pasada hacia atrás de PyTorch puede ocultar malware Turing-completo en términos de pérdida cero

Investigadores demuestran cómo las peculiaridades de la precisión de punto flotante permiten la ejecución de código arbitrario dentro del descenso de gradiente de PyTorch, incluso cuando las métricas de pérdida reportan cero.

Ilustración de un cubo de vidrio con capas de circuitos que representan código oculto en modelos de ML.
Ilustración generada para este artículo

Traducido automáticamente del original en inglés.

Una nueva demostración técnica revela que el motor de diferenciación automática de PyTorch puede ser engañado para ejecutar programas arbitrarios durante la pasada hacia atrás del entrenamiento. Al explotar las discrepancias entre la aritmética de punto flotante IEEE 754 y el cálculo simbólico, un atacante puede incrustar una máquina de estados Turing-completa, como el Juego de la Vida de Conway, en los pesos del modelo. Esto ocurre mientras la pérdida reportada permanece exactamente en cero, evadiendo los controles estándar de monitoreo y validación.

Qué sucedió

El descubrimiento surgió de una investigación sobre anomalías de precisión de punto flotante dentro de PyTorch. El investigador buscaba inicialmente determinar si una función de pérdida podría evaluarse matemáticamente a cero mientras aún desencadenaba actualizaciones de pesos durante el descenso de gradiente. El resultado confirmó que es posible construir un término de pérdida que se registra como 0.0 en cada métrica de entrenamiento pero fuerza al optimizador a ejecutar lógica compleja. Este hallazgo transforma una curiosidad numérica teórica en un vector viable de ataque a la cadena de suministro para pipelines de aprendizaje automático.

El modelo de amenaza involucra a un desarrollador que ajusta finamente un modelo de código abierto, como Llama-3-8B de Meta. Las prácticas de seguridad estándar podrían incluir verificar los hashes SHA-256 de los archivos de checkpoint y revisar el código Python en busca de puertas traseras obvias o llamadas al sistema. Si las curvas de entrenamiento parecen normales y las pérdidas auxiliares permanecen planas, el entorno suele considerarse seguro. Sin embargo, un atacante puede distribuir un paquete malicioso, como un regularizador falso llamado UltraLoss, que se integra sin problemas en el bucle de entrenamiento sin modificar el checkpoint base, la arquitectura o el conjunto de datos.

Cuando este término de pérdida malicioso se agrega a la pérdida total, reporta 0.000000 en cada iteración. A pesar de esta apariencia benigna, la llamada a total_loss.backward() y optimizer.step() ejecuta un programa arbitrario incrustado dentro de los pesos del modelo. El atacante no necesita mutar los parámetros directamente durante la pasada hacia adelante, lo que hace que la explotación sea difícil de detectar mediante análisis estático estándar o registro en tiempo de ejecución de los valores de pérdida.

Cómo funciona

La explotación depende del desacuerdo entre la truncación de punto flotante a nivel de hardware y las reglas de diferenciación simbólica utilizadas por los motores de autodiff. El mecanismo central utiliza una función h(u) = (2^30 + u) - 2^30. En la aritmética float32 de IEEE 754, agregar un valor pequeño u (donde |u| < 64) a 2^30 resulta en un redondeo de vuelta a 2^30 porque la brecha entre números representables a esa magnitud es de 128. Restar 2^30 luego produce 0.0. Sin embargo, el motor autograd de PyTorch trata la suma y la resta simbólicamente, registrando sus derivadas como 1. Así, mientras la pasada hacia adelante ve cero, la pasada hacia atrás calcula un gradiente de 1.

Para crear una fuente de gradiente sigilosa, el investigador combina este comportamiento con la regla del producto. Se construye una pérdida escalar multiplicando dos términos: uno que evalúa al vector de gradiente objetivo en la pasada hacia atrás pero cero en la pasada hacia adelante, y otro que es cero en ambas pasadas pero tiene una derivada de 1. Específicamente, la pérdida se define como la suma de (v - h(v)) * h(theta), donde v es la actualización de peso deseada. En la pasada hacia adelante, h(theta) es cero, por lo que la pérdida es cero. En la pasada hacia atrás, la regla del producto permite que el valor guardado de la pasada hacia adelante del primer término fluya como el gradiente, estableciendo efectivamente theta.grad al vector de actualización deseado.

Este mecanismo permite al optimizador sobrescribir los pesos con el siguiente estado de un autómata celular, como el Juego de la Vida de Conway, durante cada paso de entrenamiento. El investigador demostró esto conectando las reglas del Juego de la Vida a 1.024 pesos de una CNN entrenada en MNIST. Durante 2.345 pasos, la pérdida auxiliar permaneció en cero, el modelo logró una precisión normal y los pesos simularon exitosamente el autómata sin errores. Los valores de actualización son enteros pequeños (-1, 0, 1), que no tienen error de redondeo en float32, asegurando transiciones de estado precisas.

Detalles clave

  • La explotación funciona porque IEEE 754 float32 redondea a cero las sumas pequeñas a constantes grandes, mientras que PyTorch autograd calcula las derivadas simbólicamente como 1.
  • Se puede construir una función de pérdida que evalúe a 0.0 en la pasada hacia adelante mientras produce un vector de gradiente arbitrario en la pasada hacia atrás.
  • El ataque permite que programas Turing-completos, como el Juego de la Vida de Conway, se ejecuten dentro de los pesos del modelo durante las actualizaciones estándar de SGD.
  • La lógica maliciosa puede ocultarse usando "lavado matemático", donde las reglas de autómatas celulares se disfrazan como regularizadores geométricos o capas convolucionales.
  • Los atacantes pueden almacenar constantes críticas, como los pesos del kernel para la máquina de estados, en archivos de configuración externos que afirman ser resultados de ajuste de hiperparámetros.
  • Las extensiones CUDA compiladas pueden oscurecer aún más la lógica, envolviendo código binario malicioso en clases Python delgadas que parecen penalizaciones espectrales estándar.

Por qué importa

Esta vulnerabilidad desafía la suposición de que monitorear las métricas de pérdida y verificar los hashes de archivos son suficientes para asegurar los pipelines de entrenamiento de ML. Los desarrolladores a menudo confían en bibliotecas de código abierto y técnicas de regularización sin inspeccionar profundamente su implementación matemática. Si una biblioteca afirma mejorar la convergencia o la estabilidad, sus operaciones internas rara vez se auditan en busca de comportamientos de gradiente no estándar. Esta explotación muestra que una biblioteca puede comportarse perfectamente normalmente en términos de métricas de salida mientras secuestra el proceso de entrenamiento mismo.

Para equipos que construyen productos con IA, esto destaca un punto ciego en la seguridad de la cadena de suministro. La seguridad de software tradicional se centra en la ejecución de código y el acceso a datos, pero el entrenamiento de ML introduce un nuevo vector donde el algoritmo de optimización mismo se convierte en el portador de carga útil. Dado que el código malicioso se ejecuta dentro de las operaciones matemáticas legítimas del descenso de gradiente, evade muchas salvaguardas convencionales. Esto requiere un cambio en cómo los ingenieros validan componentes de ML de terceros, yendo más allá de las métricas superficiales para verificar la integridad matemática de las funciones de pérdida.

Qué puedes hacer

  • Audita cualquier función de pérdida personalizada o regularizador para operaciones que involucren constantes grandes y desplazamientos pequeños, lo cual puede indicar explotación de punto flotante.
  • Verifica que los gradientes calculados durante la retropropagación estén alineados con las derivadas matemáticas esperadas, en lugar de depender únicamente de los valores de pérdida.
  • Inspecciona los archivos de configuración y los activos externos cargados por las bibliotecas de ML en busca de constantes o kernels inexplicados que no coincidan con los propósitos documentados.
  • Prefiere usar extensiones compiladas de fuentes confiables y verifica su integridad, ya que pueden ocultar lógica maliciosa más eficazmente que el código Python.
  • Implementa comprobaciones en tiempo de ejecución que comparen las actualizaciones de pesos contra normas esperadas, marcando patrones inusuales incluso si la pérdida permanece estable.
  • Trata los paquetes de ML de terceros con el mismo escrutinio que las dependencias a nivel de sistema, reconociendo que pueden ejecutar lógica arbitraria durante el entrenamiento.
  • #pytorch
  • #security
  • #machine learning
  • #floating point
  • #supply chain

Herramientas de la Tienda de Bytechap

$89

DocBento

Gestión documental autoalojada que lee cada escaneo y responde con citas de página.

Demo en vivo
$79

WorkBento

Suite de RR. HH. y gestión del entorno laboral impulsada por IA que puedes alojar tú mismo.

Demo en vivo

Seguir leyendo

Todos los artículos