La seguridad de los contenedores comienza con su imagen base.
Pero aquí está el truco:
- La simple actualización a la "última" versión de una imagen base puede romper su aplicación.
- Te ves obligado a elegir entre distribuir vulnerabilidades conocidas o pasarte días arreglando problemas de compatibilidad.
- Y a menudo... ni siquiera estás seguro de si una actualización merece la pena.
En este post, exploraremos por qué actualizar imágenes base es más difícil de lo que parece, recorreremos ejemplos reales y mostraremos cómo puedes automatizar actualizaciones seguras e inteligentes sin romper tu aplicación.
El problema: "Sólo tiene que actualizar su imagen de base" - Más fácil decirlo que hacerlo
Si estás leyendo esto, probablemente has buscado en Google algo como "Cómo proteger tus contenedores" y el primer punto en cada artículo de bazofia generado por IA que has leído es este, actualiza tu imagen base. ¿Simple, verdad? Pues no tan rápido.
Tu imagen base es tu punto central de seguridad, si tu imagen base tiene vulnerabilidades dentro de ella entonces tu aplicación lleva esas vulnerabilidades con ella. Vamos a jugar a este escenario.
Ejecutas un escaneo contra tu imagen de contenedor y se encuentra un CVE de alta gravedad. La recomendación útil es actualizar la imagen base, fantástico, habrás terminado antes del almuerzo.
⚠️ CVE-2023-37920 encontrado en ubuntu:20.04
Gravedad: Alta
Corregido en: 22.04
Recomendación: Actualizar la imagen base
...pero descubres un problema.
Actualizando a ciegas desde ubuntu:20.04
a ubuntu:22.04
...tu solicitud se hace añicos.
Veamos algunos ejemplos de bumping de una imagen base y lo que ocurre en la realidad.
Ejemplo 1: Un archivo Docker que se rompe tras una actualización
Dockerfile inicial:
DESDE python:3.8-buster
EJECUTAR apt-get update && apt-get install -y libpq-dev
RUN pip install psycopg2==2.8.6 flask==1.1.2
COPY . /appCMD ["python", "app.py"]
El equipo se actualiza a:
DESDE python:3.11-bookworm
RUN apt-get update && apt-get install -y libpq-dev
RUN pip install psycopg2==2.8.6 flask==1.1.2COPY . /appCMD ["python", "app.py"]
Resultado:
psycopg2==2.8.6
no compila con las versiones más recientes delibpq
encabezados enratón de biblioteca.
matraz==1.1.2
no admitePython 3.11
funciones en tiempo de ejecución (las API obsoletas se rompen).- La compilación se rompe en CI.
- Tu equipo de desarrollo está enfadado y tu almuerzo arruinado.
Ejemplo 2: Actualizaciones de la imagen de base que introducen errores sutiles en tiempo de ejecución
Original:
FROM nodo:14-busterCOPY. /app
EJECUTAR npm ci
CMD ["node", "server.js"]
Actualiza a:
FROM nodo:20-ojode toro
COPIAR . /app
EJECUTAR npm ci
CMD ["node", "server.js"]
Problema en tiempo de ejecución:
nodo:20
utilizaOpenSSL
versiones - la verificación TLS estricta rompe las configuraciones de axios más antiguas.- La aplicación lanza
UNABLE_TO_VERIFY_LEAF_SIGNATURE
errores en tiempo de ejecuciónHTTP
llamadas a servicios heredados.
Por qué "lo último" es una trampa
El ecosistema Docker fomenta el uso de las últimas etiquetas o versiones de primera línea. Pero esto a menudo significa que su aplicación que se ejecutaba el lunes de repente falla el martes. Esto suele ser una trampa que causa dolores de cabeza, interrupciones y ralentización del desarrollo, ya que se pierde tiempo corrigiendo errores.
Así que la solución entonces, obviamente, es fijar a una versión menor que ha probado.... No tan rápido, ya que ahora has entrado en el juego de la ruleta de la seguridad, en el que siempre estarás descubriendo nuevas CVE que podrían dejarte vulnerable.
Parálisis por decisión: ¿Actualizar o no?
Los equipos de seguridad presionan para que se realicen actualizaciones.
Los desarrolladores se echan atrás debido a la estabilidad.
¿Quién tiene razón? Depende.
PERO, para entender siquiera la decisión, hay que ver todas las opciones, lo que significa crear una hoja de cálculo masiva con todas las versiones, riesgos de seguridad, riesgos de estabilidad y disponibilidad.
Veamos cómo podría ser.
Esto te deja con opciones complejas, cutres e imposibles
- Permanecer en la vieja imagen y aceptar las vulnerabilidades
- Actualiza y rompe tu aplicación, arriesgando el tiempo de inactividad de producción
- Intentar realizar pruebas manuales de compatibilidad: días de trabajo
El flujo de trabajo de actualización manual:
Si lo haces a mano, esto es lo que parece:
- Compruebe los CVE:
imagen trivial python:3.8-buster
- Investigue cada CVE: ¿es accesible en el contexto de su aplicación?
- Decidir el candidato a la actualización
- Prueba la nueva imagen:
- Construya
- Ejecutar pruebas unitarias
- Ejecutar pruebas de integración
- Si falla, intente parchear el código o actualizar las bibliotecas.
- Repita la operación con cada recipiente.
Es agotador.
El coste de quedarse quieto
Puede que pienses "si no está roto, no lo arregles".
El 87% de las imágenes de contenedores en producción presentaban al menos una vulnerabilidad crítica o de alta gravedad" .
También hay un montón de exploits conocidos que existen en imágenes base populares.
- Vulnerabilidad Unzip Path Traversal (
CVE-2020-27350
) - estuvo en millones de contenedores durante años. - Heartbleed (
CVE-2014-0160
) permanecieron en contenedores heredados mucho después de las correcciones oficiales. PHP-FPM RCE
(CVE-2019-11043
) permiten a atacantes remotos ejecutar código arbitrario a través de peticiones HTTP crafteadas y era extremadamente común en imágenes base de contenedores conPHP-FPM preinstalado
antes de ser parcheado
Cómo ayuda nuestra función Auto-Fix
Para resolver exactamente este problema, Aikido Security lanzó nuestra función de autocorrección de contenedores porque, bueno, nosotros también sufrimos este dolor.
La característica funciona así, sus imágenes, Aikido escanea sus contenedores en busca de vulnerabilidades. Si (o más probablemente cuando) encontramos vulnerabilidades, como siempre te alertamos, entonces en lugar de gritarte que actualices tu imagen base te proporcionamos diferentes opciones. Creamos una tabla que le permite saber qué versión de la imagen base solucionará qué CVEs, de esta manera usted puede ver muy rápidamente que un cambio menor puede eliminar todos o la mayoría de los CVEs altos, lo que significa que esta es una actualización adecuada de la imagen base.
Si se trata de una actualización menor, puede crear automáticamente una pull request para actualizar la versión.
Que ahorra horas de trabajo
Conclusión:
- Actualizar las imágenes base de los contenedores es realmente difícil.
- El consejo de "sólo actualizar" simplifica en exceso un proceso complejo y cargado de riesgos.
- Sus equipos hacen bien en ser precavidos, pero no deberían tener que elegir entre seguridad y estabilidad.
- El autofijador de contenedores de Aikido hace el trabajo duro por usted para que pueda tomar una decisión con conocimiento de causa.
- Así que la próxima vez que veas una alerta de vulnerabilidad de imagen base, no te asustarás. Tendrás un PR.