Executando containers Docker com segurança em produção

Um modo de obter o hardening de containers Docker em produção é tornando-os “imutáveis”, ou seja, no modo read only (somente leitura). Outros métodos para executar containers de forma segura incluem minimizar o attack surface e aplicar tanto o procedimento padrão de hardening do Linux, como os que são específicos a um ambiente de container.

Um container pode ser executado no modo somente leitura usando a flag –read-only ao iniciá-lo. Isso impede qualquer processo de escrita para o sistema de arquivos. Qualquer tentativa resulta em erro. A execução dessa infraestrutura imutável também tem relação com outras melhores práticas recomendadas para pipelines de deploy de software.

Embora a imutabilidade evite a execução de qualquer script malicioso ou alterações que possam acontecer através de vulnerabilidades presentes em outros softwares rodando dentro do contêiner, até que ponto esse modo é viável para aplicativos no mundo real? Aplicativos que geram log de arquivos e usam bancos de dados, por exemplo, necessitam de escrita.

Uma solução possível para o log seria usar um sistema de log centralizado como o Elasticsearch/Logstash/Kibana (ELK) para que todos os logs sejam coletados em um local central, possivelmente outro container, que não seja acessado diretamente pelo usuário final. Outra alternativa é exportar os logs para fora do contêiner usando a flag –log-driver ao iniciar o container. Para aplicativos que precisam de acesso de gravação para diretórios temporários como /tmp, uma solução é montar um sistema de arquivos temporário no container para esses diretórios.

Os bancos de dados não são acessados diretamente pelo usuário final, portanto, o risco é menor. No entanto, isso não impede ataques, a menos que os aplicativos voltados para o usuário contemplem o hardening.

Nos casos em que é inevitável ter um sistema de arquivos gravável, o Docker fornece auditoria e reverte as alterações. O sistema de arquivos em um container Docker é empilhado como uma série de camadas. Quando um novo container é criado, uma nova camada é adicionada na parte superior onde pode ser gravada. O driver de armazenamento Docker oculta a ação nos bastidores e o apresenta como um sistema de arquivos regular para o usuário. As gravações criadas em um container em execução são feitas nesta nova camada. Isso geralmente é chamado Copy-On-Write (COW).

Alterações de configuração esperada são fáceis de detectar em um container Docker. O comando ‘docker diff’ exibe as alterações feitas no sistema de arquivos – sejam eles arquivos adicionados, removidos ou modificados.
Além de executar um container no modo somente leitura, se possível, outras recomendações para proteger containers em produção incluem:

  • Executar uma imagem mínima como Alpine Linux, que foi projetada com tendo a segurança em mente. O kernel é corrigido com uma porta não oficial do grsecurity. O grsecurity é um conjunto de melhorias de segurança para o kernel Linux, que inclui controle de acesso e eliminação de vulnerabilidades baseadas em corrupção de memória, minimizando as formas pelas quais um sistema pode ser atacado.
  • Reforço de limites de recursos (CPU/RAM) para evitar ataques DoS
  • Configuração de limites de threads e processos no sistema operacional
  • Aplicação de procedimentos padrão de hardening do kernel Linux como o sysctl hardening
  • Execução de um único aplicativo por container. Isso é recomendado porque reduz a o attack surface, ou seja, a quantidade de vulnerabilidades possíveis para um determinado container é limitada àquelas que podem estar presentes no aplicativo desse container.

Fonte: InfoQ

21