Porque é que estão aqui?
Quer saber a verdadeira resposta a duas perguntas sobre a segurança do Docker:
O Docker é seguro para utilização em produção?
Sime não. O Docker usa um modelo de segurança que se baseia em namespaces e isolamento de recursos, tornando os processos mais seguros contra ataques específicos do que executar seus aplicativos diretamente de uma VM em nuvem ou sistema bare metal. Apesar dessa camada, ainda existem muitas maneiras de os invasores acessarem seu contêiner, permitindo que eles leiam informações confidenciais, executem ataques de negação de serviço (DoS) ou até mesmo obtenham acesso root ao sistema host.
Como posso melhorar a segurança do meu Docker (de uma forma não muito dolorosa)?
Vamosguiá-lo através das vulnerabilidades mais comuns e graves do Docker, pulando as recomendações básicas que você encontrará em todo o Google, como usar imagens oficiais e manter seu host atualizado. Em vez disso, vamos levá-lo diretamente para novas opções de docker e linhas de Dockerfile que tornarão sua nova implantação de contêiner Docker padrão muito mais segura do que nunca.

A lista de verificação de segurança do Docker sem barreiras
Tornar os sistemas de ficheiros em contentor apenas de leitura
O que é que ganha?
Evita que um atacante edite o ambiente de tempo de execução do seu contentor Docker, o que poderia permitir-lhe recolher informações úteis sobre a sua infraestrutura, reunir dados do utilizador ou conduzir diretamente um ataque DOS ou ransomware.
Como é que se define?
Existem duas opções, em tempo de execução ou na configuração do Docker Compose.
Em tempo de execução: docker run --read-only your-app:v1.0.1
No seu ficheiro Docker Compose:
serviços:
webapp:
image: your-app:v1.0.1read_only: true
...
Escalada de privilégios de bloqueio
O que é que ganha?
Você impede que seu contêiner Docker - ou um invasor que esteja mexendo no contêiner - habilite novos privilégios, até mesmo no nível de raiz, com setuid ou setgid. Com acesso mais permissivo ao seu contêiner, um invasor pode acessar credenciais na forma de senhas ou chaves para partes conectadas da sua implantação, como um banco de dados.
Como é que se define?
Mais uma vez, em tempo de execução ou na configuração do Docker Compose.
Em tempo de execução: docker run --security-opt=no-new-privileges your-app:v1.0.1
No seu ficheiro Docker Compose:
serviços:
webapp:
image: your-app:v1.0.1
security_opt:
- no-new-privileges:true
...
Isolar as suas redes de contentor para contentor
O que é que ganha?
Por defeito, o Docker permite que todos os contentores comuniquem através da rede docker0, o que pode permitir que um atacante se desloque lateralmente de um contentor comprometido para outro. Se você tiver serviços discretos A
e B
em contentores Y
e Z
Se as redes de um utilizador final não precisam de comunicar diretamente, isolar as suas redes proporciona a mesma experiência ao utilizador final e impede o movimento lateral para uma melhor segurança do Docker.
Como é que se define?
É possível especificar redes Docker em tempo de execução ou na configuração do Docker Compose. No entanto, primeiro é necessário criar a rede:
docker network create your-isolated-network (rede isolada)
Em tempo de execução, adicione o --Opção de rede
n: docker run --network your-isolated-network your-app:v1.0.1
Ou a opção equivalente no seu ficheiro Docker Compose:
serviços:
webapp:
image: your-app:v1.0.1
networks:
- sua-rede-isolada
...
Definir um utilizador não-root adequado
O que é que ganha?
O utilizador predefinido num contentor é raiz
, com um uid de 0
. Ao especificar um utilizador distinto, evita que um atacante aumente os seus privilégios para outro utilizador que possa tomar medidas sem restrições, como o root, o que anularia quaisquer outras medidas de segurança do Docker que tenha trabalhado arduamente para implementar.
Como é que se define?
Crie o seu utilizador durante o processo de construção ou em tempo de execução. Em tempo de execução, é possível criar o utilizador pela primeira vez ou substituir a função UTILIZADOR
que já definiu na construção.
Durante o processo de construção, no seu Dockerfile
:
...
EXECUTAR groupadd -r seu-utilizador
EXECUTAR useradd -r -g seu-utilizador seu-utilizador
UTILIZADOR meuutilizador
...
Em tempo de execução: docker run -u seu-usuário sua-app:v1.0.1
Largar as capacidades do kernel Linux
O que é que ganha?
Por padrão, os contêineres do Docker podem usar um conjunto restrito de recursos do kernel do Linux. Você pode pensar que o pessoal do Docker criou esse conjunto restrito para ser completamente seguro, mas muitos recursos existem para compatibilidade e simplicidade. Por exemplo, os contentores predefinidos podem alterar arbitrariamente a propriedade dos ficheiros, alterar o seu diretório raiz, manipular UIDs de processos e ler sockets. Ao eliminar alguns ou todos esses recursos, você minimiza o número de vetores de ataque.
Como é que se define?
É possível eliminar capacidades e definir novas capacidades em tempo de execução. Por exemplo, pode eliminar todas as capacidades do kernel e permitir ao seu contentor apenas a capacidade de alterar a propriedade dos ficheiros existentes.
docker run --cap-drop ALL --cap-add CHOWN your-app:v1.0.1
Ou para o Docker Compose:
serviços:
webapp:
image: your-app:v1.0.1
cap_drop:
- TODOS
cap_add:
- CHOWN
...
Prevenir as bombas de garfo
O que é que ganha?
Fork bombs são um tipo de ataque DoS que replica infinitamente um processo existente. Em primeiro lugar, reduzem o desempenho e restringem os recursos, o que inevitavelmente aumenta os custos e pode, em última análise, fazer crashar os seus contentores ou o sistema anfitrião. Uma vez iniciada uma fork bomb, não há outra forma de a parar para além de reiniciar o contentor ou o anfitrião.
Como é que se define?
Em tempo de execução, pode limitar o número de processos (PIDs) que o seu contentor pode criar.
docker run --pids-limit 99 sua-app:v1.0.1
Ou com o Docker Compose:
serviços:
webapp:
imagem: your-app:v1.0.1
deploy
limites:
pids: 99
Melhore a segurança do Docker monitorizando as suas dependências de código aberto
O que é que ganha?
Os aplicativos que você conteinerizou para implantação com o Docker provavelmente têm uma ampla árvore de dependências.
Como é que se define?
A forma mais "não-BS" é com a análise de dependências de código aberto do Aikido. A nossa monitorização contínua analisa projectos escritos em mais de uma dúzia de idiomas com base na presença de ficheiros de bloqueio na sua aplicação e fornece uma visão geral instantânea das vulnerabilidades e malware. Com a triagem automática que filtra os falsos positivos, o Aikido dá-lhe conselhos de correção com os quais pode começar a trabalhar imediatamente... e não apenas depois de ler uma dúzia de outros documentos de referência e problemas do GitHub.
Na Aikido, adoramos projectos open-source estabelecidos como o Trivy, o Syft e o Grype. Também sabemos por experiência própria que utilizá-los isoladamente não é uma experiência particularmente boa para o programador. Por baixo do capô, o Aikido melhora estes projectos com regras personalizadas para colmatar lacunas e revelar falhas de segurança que não conseguiria encontrar de outra forma. Ao contrário de encadear várias ferramentas de código aberto, o Aikido liberta-o da necessidade de construir um script de verificação ou criar um trabalho personalizado no seu CI/CD.

Utilizar apenas imagens fiáveis para segurança do Docker
O que é que ganha?
O Docker Content Trust (DCT) é um sistema para assinar e validar o conteúdo e a integridade das imagens oficiais que extrai dos registos do Docker, como o Docker Hub. Extrair apenas imagens assinadas pelo autor dá-lhe mais garantias de que não foram adulteradas para criar vulnerabilidades na sua implementação.
Como é que se define?
A forma mais fácil é definir a variável de ambiente na sua shell, o que o impede a si ou a qualquer outra pessoa de trabalhar com imagens não confiáveis.
exportDOCKER_CONTENT_TRUST=1
docker run ...
Ou pode definir a variável de ambiente sempre que executar o Docker:
DOCKER_CONTENT_TRUST=1 docker run ...
Atualizar tempos de execução de fim de vida (EOL)
O que é que ganha?
Uma recomendação comum para a segurança de contentores Docker é fixar imagens e dependências a uma versão específica em vez de mais recente
. Em teoria, isso impede-o de utilizar inconscientemente novas imagens, mesmo que tenham sido adulteradas, que introduzem novas vulnerabilidades.
Como é que se define?
Existem alguns projectos de código aberto disponíveis para o ajudar a descobrir EOLs e a preparar-se melhor. O projeto endoflife.date(repositório GitHub) rastreia mais de 300 produtos, agregando dados de várias fontes e disponibilizando-os através de uma API pública. Tem algumas opções com o endoflife.date e projectos semelhantes:
- Verifique manualmente se o projeto tem actualizações nas dependências de que as suas aplicações dependem e crie bilhetes ou problemas para as actualizações necessárias.
- Escreva um script (Bash, Python, etc.) para obter as datas de EOL das dependências da API e execute-o regularmente, como um cron job.
- Incorpore a API pública, ou esse script personalizado, na sua plataforma de CI para falhar as compilações que usam um projeto que está próximo ou atingiu o EOL.
Como desenvolvedor, entendemos que seu tempo é valioso e muitas vezes limitado. É aqui que o Aikido pode proporcionar uma sensação de segurança - o nosso recurso de verificação EOL rastreia o seu código e contentores, dando prioridade aos tempos de execução com maior impacto e exposição, como o Node.js ou um servidor Web Nginx. Como de costume, não apenas automatizamos a coleta de informações, mas também fornecemos alertas com a gravidade apropriada para informar, e não sobrecarregar.

Limitar a utilização de recursos do contentor
O que é que ganha?
Por padrão, os contêineres não têm restrições de recursos e usarão tanta memória ou CPU quanto o agendador do host. Limitar o uso de recursos de um contêiner específico pode minimizar o impacto de um ataque DoS. Em vez de fazer crashar o seu contentor ou sistema anfitrião devido a uma Exceção de Memória, o ataque DoS em curso terá "apenas" um impacto negativo na experiência do utilizador final.
Como é que se define?
Em tempo de execução, é possível utilizar o -memória
e --cpus
para definir limites para a utilização da memória e da CPU, respetivamente. A opção de memória assume números com g para gigabytes e m para megabytes, enquanto a opção de CPU reflecte o limite de CPUs dedicadas disponíveis para o contentor e os seus processos.
docker run --memory="1g" --cpus="2" sua-app:v1.0.1
Isto também funciona com o Docker Compose:
serviços:
webapp:
image: your-app:v1.0.1
deploy:
limites:
cpus: '2'
memória: 1G
...
O seu comando final e as opções do Compose para a segurança do Docker
Até agora, já viu algumas dicas de segurança do Docker e as opções ou configurações relevantes da CLI para as acompanhar, o que significa que está bastante entusiasmado para as implementar ou sobrecarregado com a forma de as juntar todas. Abaixo, reunimos todas as recomendações em um único comando ou modelo de configuração, que o ajudará a começar a implantar contêineres Docker mais seguros imediatamente.
Obviamente, irá querer alterar algumas das opções - como o nome de utilizador não-root, capacidades do kernel, limites de recursos - com base nas necessidades da sua aplicação.
exportDOCKER_CONTENT_TRUST=1
docker run \
--read-only \
--security-opt=no-new-privileges\
--network your-isolated-network \
--cap-drop ALL
--cap-add CHOWN \
--pids-limit 99 \
--memory="1g" --cpus="2" \
--user=seu-utilizador \
... # OUTRAS OPÇÕES VÃO AQUI
sua-app:v1.0.1
Pode até querer criar um alias drun com a shell do seu anfitrião que pode invocar sem ter de se lembrar de todos esses detalhes.
função drun {
docker run \
--read-only \
--security-opt=no-new-privileges\
--network your-isolated-network \
--cap-drop ALL
--cap-add CHOWN \
--pids-limit 99 \
--memory="1g" --cpus="2" \
--user=seu-utilizador \
$1 \
$2
}
De seguida, execute o seu alias da seguinte forma, com as suas opções e o nome da imagem: drun -it your-app:v1.0.1
Se for do tipo que gosta do Docker Compose, pode adaptar todas as mesmas opções num novo modelo de base do Docker Compose a partir do qual pode trabalhar no futuro:
serviços:
webapp:
image: your-app:v1.0.1
read_only: true
security_opt:
- no-new-privileges:true
networks:
- sua-rede-isolada
cap_drop:
- ALL
cap_add:
- CHOWN
deploy:
limits:
pids: 9
cpus: '2'
memory: 1G
... # OUTRAS OPÇÕES VÃO AQUI
Bónus: Executar o Docker com contentores sem raiz
Quando você instala o Docker em qualquer sistema, seu daemon opera com privilégios de nível de raiz. Mesmo que ative todas as opções acima e evite o escalonamento de privilégios dentro de um contentor Docker, o resto do tempo de execução do contentor no seu sistema anfitrião continua a ter privilégios de raiz. Isso inevitavelmente amplia sua superfície de ataque.
A solução são os contentores sem raiz, que um utilizador sem privilégios pode criar e gerir. A ausência de privilégios de raiz significa muito menos problemas de segurança para o seu sistema anfitrião.
Gostaríamos de poder ajudá-lo a usar contêineres sem raiz com uma única opção ou comando, mas não é tão simples assim. Você pode encontrar instruções detalhadas no site Rootless Containers, incluindo um guia de instruções para o Docker.
O que se segue para a sua segurança Docker?
Se você aprendeu alguma coisa com essa experiência, é que a segurança de contêineres é uma operação de cauda longa. Há sempre mais listas de verificação de endurecimento e artigos aprofundados para ler sobre como bloquear seus contêineres no Docker ou seu primo mais antigo e muitas vezes incompreendido, o Kubernetes. Não é possível almejar uma segurança de contêineres sem falhas - criar tempo em sua agenda de desenvolvimento ocupada para abordar a segurança e, em seguida, fazer melhorias incrementais com base no impacto e na gravidade, irá percorrer um longo caminho ao longo do tempo.
Para o ajudar a maximizar esse processo contínuo e a dar prioridade às correcções que irão melhorar significativamente a segurança das suas aplicações, existe o Aikido. Acabámos de angariar uma Série A de 17 milhões de dólares para a nossa plataforma de segurança para programadores "no BS" e gostaríamos que se juntasse a nós.