A segurança dos contentores começa com a sua imagem de base.
Mas aqui está o senão:
- A simples atualização para a versão "mais recente" de uma imagem de base pode danificar a sua aplicação.
- É forçado a escolher entre enviar vulnerabilidades conhecidas ou passar dias a corrigir problemas de compatibilidade.
- E muitas vezes... nem sequer tem a certeza se vale a pena fazer uma atualização.
Neste post, vamos explorar por que atualizar imagens de base é mais difícil do que parece, passar por exemplos reais e mostrar como você pode automatizar atualizações seguras e inteligentes sem quebrar seu aplicativo.
O problema: "Basta atualizar a sua imagem de base" - É mais fácil falar do que fazer
Se está a ler isto, provavelmente já pesquisou no Google algo como "Como proteger os seus contentores" e o primeiro ponto em todos os artigos gerados por IA que leu é este: actualize a sua imagem de base. Simples, certo? Bem, não tão rápido.
A sua imagem de base é o seu ponto central de segurança, se a sua imagem de base tiver vulnerabilidades no seu interior, então a sua aplicação carrega essas vulnerabilidades com ela. Vamos analisar este cenário.
Executa uma análise à sua imagem de contentor e é encontrado um CVE de alta gravidade. A recomendação útil é atualizar a imagem de base, o que é fantástico, e estará pronto antes do almoço.
⚠️ CVE-2023-37920 encontrado em ubuntu:20.04
Gravidade: Alta
Corrigido em: 22.04
Recomendação: Atualizar a imagem base
... mas descobrem um problema.
Ao atualizar cegamente a partir de ubuntu:20.04
para ubuntu:22.04
, a sua candidatura fica desfeita.
Vejamos alguns exemplos de colisão de uma imagem de base e o que acontece na realidade.
Exemplo 1: Um Dockerfile que quebra após uma atualização
Dockerfile inicial:
DE python:3.8-buster
EXECUTAR apt-get update && apt-get install -y libpq-dev
EXECUTAR pip install psycopg2==2.8.6 flask==1.1.2
COPY . /appCMD ["python", "app.py"]
A equipa actualiza-se para:
DE python:3.11-bookworm
EXECUTAR apt-get update && apt-get install -y libpq-dev
EXECUTAR pip install psycopg2==2.8.6 flask==1.1.2COPY . /appCMD ["python", "app.py"]
Resultado:
psycopg2==2.8.6
não consegue compilar com as versões mais recentes dolibpq
cabeçalhos emleitor de livros.
frasco==1.1.2
não suportaPython 3.11
caraterísticas de tempo de execução (quebra de APIs obsoletas).- A construção é interrompida na CI.
- A sua equipa de desenvolvimento está furiosa e o seu almoço está arruinado.
Exemplo 2: Actualizações da imagem de base que introduzem erros subtis de tempo de execução
Original:
DE node:14-busterCOPY. /app
EXECUTAR npm ci
CMD ["node", "server.js"]
Atualizar para:
FROM node:20-bullseye
COPIAR . /app
EXECUTAR npm ci
CMD ["node", "server.js"]
Problema de tempo de execução:
nó:20
utiliza os mais recentesOpenSSL
versões - a verificação estrita do TLS quebra as configurações mais antigas do axios.- A aplicação lança
UNABLE_TO_VERIFY_LEAF_SIGNATURE
erros em tempo de execuçãoHTTP
chamadas para serviços antigos.
Porque é que o "mais recente" é uma armadilha
O ecossistema Docker incentiva o uso das tags mais recentes ou versões de primeira linha. Mas isso geralmente significa que seu aplicativo que estava em execução na segunda-feira de repente falha na terça-feira. Isso geralmente é uma armadilha que causará dores de cabeça, interrupções e desenvolvimento mais lento, pois você gasta tempo corrigindo bugs.
Portanto, a solução é, obviamente, fixar uma versão menor que tenha testado.... Não tão depressa, pois agora entrou no jogo de segurança whack-a-mole onde estará sempre a descobrir novos CVEs que o podem deixar vulnerável.
Paralisia de decisão: Deve atualizar ou não?
As equipas de segurança insistem nas actualizações.
Os programadores insistem na estabilidade.
Quem é que tem razão? Depende.
MAS, para compreender a decisão, é necessário analisar todas as opções, o que significa criar uma folha de cálculo enorme com todas as versões, riscos de segurança, riscos de estabilidade e disponibilidade.
Vamos ver como é que isso pode ser.
Isto deixa-o com escolhas complexas, de má qualidade e impossíveis
- Manter a imagem antiga e aceitar as vulnerabilidades
- Atualizar e danificar a sua aplicação, arriscando o tempo de inatividade da produção
- Tentar efetuar um teste de compatibilidade manual - dias de trabalho
O fluxo de trabalho de atualização manual:
Se estiver a fazer isto à mão, o resultado é o seguinte:
- Verificar CVEs:
imagem trivy python:3.8-buster
- Pesquise cada CVE: é acessível no contexto da sua aplicação?
- Decidir sobre o candidato à atualização
- Teste a nova imagem:
- Construir
- Executar testes unitários
- Executar testes de integração
- Se falhar, tente corrigir o código ou atualizar as bibliotecas.
- Repetir o procedimento para todos os recipientes.
É cansativo.
O custo de ficar parado
Pode pensar-se que "se não está estragado, não se arranja".
Mas os CVEs de contentores não corrigidos contribuem maciçamente para as violações de segurança. "87% das imagens de contentores em produção tinham pelo menos uma vulnerabilidade crítica ou de elevada gravidade." fonte
Há também muitas explorações conhecidas que existem em imagens de base populares.
- Vulnerabilidade de travessia de caminho do Unzip (
CVE-2020-27350
) - esteve durante anos em milhões de contentores. - Heartbleed (
CVE-2014-0160
) permaneceram nos contentores antigos muito depois das correcções oficiais. PHP-FPM RCE
(CVE-2019-11043
) permitem que atacantes remotos executem código arbitrário através de pedidos HTTP criados e era extremamente comum em imagens de base de contentores comPHP-FPM pré-instalado
antes de ser corrigido
Como é que a nossa funcionalidade de correção automática ajuda
Para resolver este cenário exato, a Aikido Security lançou a nossa funcionalidade de auto-correção de contentores porque, bem, nós também vivemos neste sofrimento.
A funcionalidade funciona da seguinte forma: as suas imagens, o Aikido analisa os seus contentores à procura de vulnerabilidades. Se (ou, mais provavelmente, quando) encontrarmos vulnerabilidades, como sempre, alertamo-lo. Depois, em vez de lhe gritarmos para atualizar a sua imagem de base, fornecemos-lhe diferentes opções. Criamos uma tabela que lhe permite saber que versão da imagem de base irá resolver que CVEs, desta forma pode ver muito rapidamente que um pequeno aumento pode remover todos ou a maioria dos CVEs elevados, o que significa que esta é uma atualização adequada da imagem de base.
Se a atualização for um pequeno aumento, pode criar automaticamente um pull request para aumentar a versão.
São horas de trabalho poupadas
Conclusão:
- Atualizar imagens de base de contentores é realmente difícil.
- O conselho "basta atualizar" simplifica demasiado um processo complexo e cheio de riscos.
- As suas equipas têm razão em ser cautelosas, mas não devem ter de escolher entre segurança e estabilidade.
- O autofix do contentor Aikido faz o trabalho difícil por si, para que possa tomar uma decisão informada.
- Assim, da próxima vez que vir um alerta de vulnerabilidade de imagem de base, não entrará em pânico. Vai ter um PR.