Aikido

Segurança de Contêineres é Difícil — Aikido Container AutoFix para Facilitar

Mackenzie JacksonMackenzie Jackson
|
#
#
#

Container começa com a sua imagem base.
Mas aqui está o problema:

  • Simplesmente atualizar para a versão "mais recente" de uma imagem base pode quebrar sua aplicação.
  • Você é forçado a escolher entre lançar com vulnerabilidades conhecidas ou passar dias corrigindo problemas de compatibilidade.
  • E, muitas vezes... você nem tem certeza se uma atualização vale a pena.

Neste post, exploraremos por que atualizar imagens base é mais difícil do que parece, analisaremos exemplos reais e mostraremos como você pode automatizar atualizações seguras e inteligentes sem quebrar seu aplicativo.

O Problema: “Apenas atualize sua imagem base” — Mais fácil falar do que fazer

Se você está lendo isso, provavelmente já pesquisou algo como “Como proteger seus Containers” e o primeiro ponto em todo artigo genérico gerado por IA que você leu é este: atualize sua imagem base. Simples, certo? Bem, não tão rápido. 

Sua imagem base é seu ponto central de segurança; se sua imagem base tiver vulnerabilidades, sua aplicação as carregará consigo. Vamos simular este cenário. 

Você executa uma verificação na sua container e é encontrada uma CVE de alta gravidade. A recomendação útil é atualizar a imagem base, fantástico, você terminará antes do almoço. 

⚠️ CVE-2023-37920 encontrado em ubuntu:20.04
Severidade: Alta
Corrigido em: 22.04
Recomendação: Atualizar imagem base

…mas você descobre um problema. 

Ao fazer um upgrade às cegas de ubuntu:20.04 para ubuntu:22.04, sua aplicação se estilhaça.

Vamos analisar alguns exemplos de atualização de uma imagem base e o que acontece na realidade. 

Exemplo 1: Um Dockerfile que Quebra Após um Upgrade

Dockerfile Inicial:

FROM python:3.8-buster‍
RUN 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"]

A equipe faz o upgrade para:

FROM 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 falha ao compilar contra versões mais recentes de libpq headers em bookworm.
  • flask==1.1.2 não oferece suporte a Python 3.11 recursos de runtime (APIs obsoletas quebram).
  • A build quebra na CI.
  • Sua equipe de desenvolvimento fica irritada e seu almoço é arruinado. 

Exemplo 2: Upgrades de Imagem Base que Introduzem Bugs de Runtime Sutis

Original:

FROM node:14-busterCOPY . /app
RUN npm ci
CMD ["node", "server.js"]

Atualizar para:

FROM node:20-bullseye
COPY . /app
RUN npm ci
CMD ["node", "server.js"]

Problema de Runtime:

  • node:20 usa versões mais recentes OpenSSL — a verificação TLS estrita quebra configurações mais antigas do axios.
  • O aplicativo gera UNABLE_TO_VERIFY_LEAF_SIGNATURE erros em runtime HTTP chamadas para serviços legados.

Por que “latest” é uma armadilha

O ecossistema Docker incentiva o uso de tags 'latest' ou releases de ponta. Mas isso frequentemente significa que sua aplicação que estava funcionando na segunda-feira de repente falha na terça-feira. Isso é frequentemente uma armadilha que causará dores de cabeça, interrupções e um desenvolvimento mais lento enquanto você gasta tempo corrigindo bugs. 

Então, a solução óbvia seria fixar uma versão secundária que você testou... Mas não tão rápido, pois agora você entrou no jogo de 'whack-a-mole' da segurança, onde estará para sempre descobrindo novas CVEs que podem deixá-lo vulnerável. 

Paralisia da Decisão: Atualizar ou não?

Equipes de segurança pressionam por atualizações.
Desenvolvedores resistem devido à estabilidade.

Quem está certo? Depende.

MAS, para sequer entender a decisão, você precisa analisar todas as opções, o que significa criar uma planilha massiva com todas as versões, riscos de segurança, riscos de estabilidade e disponibilidade. 

Vejamos como isso poderia ser. 

Tag de Versão CVEs Presentes (Altas/Críticas) Risco de Compatibilidade (1-5) Principais Breaking Changes / Risco Funcional Suporte a Binários do Ecossistema (Binários Wheels/NPM)
node:14-buster (Atual) - CVE-2022-35256 (estouro de buffer OpenSSL)
- CVE-2022-25883 (SSRF em node-fetch)
- CVE-2021-32803 (Poluição de protótipo em object-path)
1 (Estável, mas envelhecendo) TLS legado, dependências inseguras incorporadas Totalmente suportado, mas EOL (manutenção encerrada em abril de 2023)
node:14-bullseye - Mesmas CVEs que as anteriores + pequenos problemas adicionais no OpenSSL 1 Pequenas alterações no glibc
Potenciais alterações de compatibilidade na camada de runtime do Docker
Estável; ainda há suporte para o ecossistema wheel e NPM
node:16-buster - CVE-2023-30581 (escrita OOB em libuv)
- CVE-2022-35256 (estouro de buffer OpenSSL)
- CVE-2022-25883 (SSRF em node-fetch)
2 Alertas de descontinuação do construtor Buffer()
Bibliotecas HTTP legadas emitem alertas rigorosos
Amplamente suportado
node:16-bullseye - Mesmo que o anterior + pequenas atualizações do OpenSSL 2 Comportamento ligeiramente diferente do resolvedor DNS
Requer cobertura de testes para chamadas de rede internas
Suportado
node:18-bullseye - CVE-2022-45195 (vulnerabilidade TLS em build mais antigo)
- CVE-2023-30581 (escrita OOB em libuv)
3 Modo rigoroso de TLS por padrão
Axios legado e bibliotecas de requisição mais antigas falham com certificados rigorosos
Ecossistema em maturidade intermediária; alguns módulos exigem atualizações
node:18-alpine - Mesmo que o anterior; riscos de incompatibilidade do glibc Alpine 4 Alpine musl pode quebrar certos módulos nativos como bcrypt
Problemas de fallback na compilação a partir do código-fonte
Requer recompilações para binários nativos
node:20-bullseye - 0 CVEs de alta gravidade (estável atual) 4 Breaking DNS resolver changes
Default ESM loader changes
axios < 1.3.2 breaks
Ativamente suportado; ecossistema em atualização
node:20-bookworm (mais recente) - 0 CVEs de alta gravidade (em março de 2024) 5 Principais mudanças:
TLS estrito
Alterações de DNS
Imposição de ESM
Plugins NPM mais antigos falham
Alguns módulos de nicho ainda estão se atualizando; o node-gyp mais recente é necessário.

Isso te deixa com escolhas complexas, problemáticas e inviáveis. 

  1. Permanecer na imagem antiga e aceitar vulnerabilidades
  2. Fazer o upgrade e quebrar seu aplicativo, arriscando tempo de inatividade na produção
  3. Realizar testes manuais de compatibilidade — dias de trabalho

O fluxo de trabalho de atualização manual:

Se você estiver fazendo isso manualmente, é assim que se parece:

  • Verificar CVEs: trivy python:3.8-buster
  • Pesquisar cada CVE: É acessível no contexto da sua aplicação?
  • Decidir sobre o candidato à atualização 
  • Testar a nova imagem:
    • Construir
    • Executar testes unitários
    • Executar testes de integração
  • Em caso de falha, tente aplicar patch no código ou atualizar bibliotecas.
  • Repita para cada container.

É exaustivo.

O Custo de Permanecer Estático

Você pode pensar “se não está quebrado, não conserte.”

Mas container não corrigidas container contribuem enormemente para as violações de segurança. «87% das container em execução na produção tinham pelo menos uma vulnerabilidade crítica ou de alta gravidade.» fonte 

Também existem muitos exploits conhecidos em imagens base populares. 

  • Vulnerabilidade de Path Traversal no Unzip (CVE-2020-27350) — permaneceu em milhões de Containers por anos.
  • Heartbleed (CVE-2014-0160) permaneceu em Containers legados muito tempo depois das correções oficiais.
  • PHP-FPM RCE (CVE-2019-11043) permite que invasores remotos executem código arbitrário por meio de solicitações HTTP criadas e era extremamente comum em imagens container com PHP-FPM pré-instalado antes de ser corrigido

Como Nosso Recurso de Auto-Correção Ajuda

Para resolver este cenário específico, Aikido lançou o nosso recurso container porque, bem, nós também vivemos essa dor. 

O recurso funciona assim: Aikido os seus contentores em busca de vulnerabilidades. Se (ou, mais provavelmente, quando) encontrarmos vulnerabilidades, como sempre, alertamos você e, em vez de gritar para que atualize a sua imagem base, oferecemos diferentes opções. Criamos uma tabela que permite saber qual versão da imagem base resolverá quais CVEs. Dessa forma, pode ver rapidamente que uma pequena atualização pode remover todas ou a maioria das CVEs elevadas, o que significa que esta é uma atualização adequada da imagem base. 

Se a atualização for um pequeno incremento, você pode criar automaticamente um pull request para aumentar a versão. 

Isso representa horas de trabalho poupadas.

Conclusão:

  • Atualizar imagens container é realmente difícil.
  • O conselho de “apenas atualizar” simplifica demais um processo complexo e cheio de riscos.
  • Suas equipes estão certas em ser cautelosas — mas elas não deveriam ter que escolher entre segurança e estabilidade.
  • container Aikidofaz o trabalho pesado por si, para que possa tomar uma decisão informada. 
  • Então, da próxima vez que você vir um alerta de vulnerabilidade de imagem base, você não entrará em pânico. Você receberá um PR.
4.7/5

Proteja seu software agora

Comece Gratuitamente
Não é necessário cc
Agendar uma demonstração
Seus dados não serão compartilhados · Acesso somente leitura · Não é necessário cartão de crédito

Fique seguro agora

Proteja seu código, Cloud e runtime em um único sistema centralizado.
Encontre e corrija vulnerabilidades rapidamente de forma automática.

Não é necessário cartão de crédito | Resultados da varredura em 32 segundos.