No início deste ano, nossa equipe foi solicitada a ampliar nossas ferramentas de segurança existentes e práticas de desenvolvimento e teste de software para conformidade com PCI-DSS e SOC-2. Uma das principais áreas que tivemos que aumentar foi a varredura de vulnerabilidades para nossos microsserviços baseados em K8s e alguns serviços monolíticos. Como resultado, nossa equipe de DevOps teve que escolher entre algumas ferramentas comerciais e soluções de código aberto para implementar a varredura de vulnerabilidades em nosso software. Todas essas ferramentas fazem coisas muito semelhantes: elas escaneiam dependências (bibliotecas de projetos ou pacotes de SO) e as comparam com bancos de dados de vulnerabilidades (como o NVD do NIST e outros).
Existem algumas ferramentas de código aberto que podem ser usadas para criar sua própria solução de varredura de vulnerabilidades, ou você pode usar um produto comercial que adiciona recursos adicionais à varredura básica que podem facilitar sua vida. Exemplos incluem:
A maioria das soluções comerciais complementa o banco de dados público de vulnerabilidades com seu próprio banco de dados de vulnerabilidades para eliminar falsos positivos/negativos e fornecer resultados mais relevantes. Dito isto, todas essas ferramentas comerciais se tornam muito caras à medida que o número de desenvolvedores aumenta. Então você precisa considerar se é “melhor” para você comprar ou construir sua própria solução usando ferramentas de código aberto existentes.
Inicialmente, decidimos que a ferramenta comercial seria a mais adequada às nossas necessidades, dada a limitação de tempo que tínhamos. No entanto, depois de passar 3 meses implantando e testando um produto comercial líder do setor, enfrentamos muitos desafios: suporte limitado para golang, ele selecionava dependências incorretas e não fechava corretamente, problemas com contêineres criados do zero em comparação com aqueles criados com alguma imagem base, etc. Como resultado, decidimos desistir e começar a criar nossa própria ferramenta usando tecnologias de código aberto disponíveis.
Neste post, vou lhe fornecer uma base sólida para começar caso você decida adotar o código aberto. Além disso, no final do post há um link para nosso repositório de código aberto para você começar!
Existem basicamente duas coisas que você deseja verificar em busca de vulnerabilidades:
No futuro, é possível adicionar mais recursos, como verificação de licença ou análise de código estático, mas isso está fora do escopo deste post.
Primeiro, você quer garantir que nenhuma nova vulnerabilidade seja introduzida pelo seu código ou alteração na imagem do Docker, então é uma boa ideia verificar cada solicitação de mesclagem antes que ela seja mesclada.
Mas você também precisa fazer uma varredura periodicamente , pois novas vulnerabilidades podem aparecer com o tempo. Além disso, a gravidade pode mudar — uma gravidade baixa que você ignorou inicialmente pode se tornar crítica ao longo do tempo, à medida que um novo vetor de ataque ou exploração é encontrado. Enquanto as ferramentas comerciais lembram da última verificação e notificam você se uma nova vulnerabilidade for encontrada, em nossa solução de código aberto, simplesmente repetimos a verificação no branch master do projeto.
Há muitas ferramentas de código aberto disponíveis, mas nossa escolha foi o Trivy porque ele é simples de usar, está em desenvolvimento ativo e pode escanear vários projetos e tipos de sistemas operacionais.
Trivy é um scanner de vulnerabilidades simples e abrangente para contêineres e outros artefatos. Uma vulnerabilidade de software é uma falha, falha ou fraqueza presente no software ou em um sistema operacional. O Trivy detecta vulnerabilidades de pacotes de SO (Alpine, RHEL, CentOS, etc.) e dependências de aplicativos (Bundler, Composer, npm, yarn, etc.). O Trivy é fácil de usar — basta instalar o binário e você estará pronto para escanear! Tudo o que você precisa fazer para escanear é especificar um alvo, como um nome de imagem do contêiner.
Ele pode ser facilmente instalado e executado localmente na imagem Docker construída ou na raiz do projeto. Ele também suporta múltiplas saídas, incluindo JSON e saída de tabela:
Infelizmente, há projetos que o Trivy não consegue escanear (por exemplo, Golang), então tivemos que confiar no OWASP Dependency-Check, pois grande parte do nosso código está em golang.
Dependency-Check é uma ferramenta de Análise de Composição de Software (SCA) que tenta detectar vulnerabilidades divulgadas publicamente contidas nas dependências de um projeto. Ele faz isso determinando se há um identificador de Enumeração de Plataforma Comum (CPE) para uma determinada dependência. Se encontrado, ele gerará um relatório com links para as entradas CVE associadas.
Ele pode gerar páginas HTML com relatórios, saídas JUnit e JSON (e alguns outros).
Agora estamos chegando perto de coisas mais interessantes 😊
Como já usamos Elasticsearch + Kibana + Fluentd em nossas equipes de DevOps e SRE, foi natural usar a infraestrutura existente para analisar a saída JSON de nossas varreduras de segurança.
Precisávamos apenas encontrar uma maneira de enviar dados de uma infraestrutura não confiável (CI runners) para nosso Elasticsearch seguro. Para isso, decidimos ter uma fila de mensagens no meio. O Fluentd tem o plugin in_sqs para ler mensagens do Amazon SQS e também é simples de usar, então a arquitetura final se parece com isso:
Quando os dados chegam ao Elasticsearch, é simples criar alguns painéis com o Kibana ou usar o Discover para consultar vulnerabilidades com todos os detalhes, conforme necessário.
Agora que temos as digitalizações e um painel bacana, o que vem depois? Não podemos esperar que os desenvolvedores monitorem esses painéis regularmente. Em vez disso, decidimos reprovar o CI quando um problema de alta gravidade ou superior é encontrado e tem uma correção disponível, dessa forma a responsabilidade é transferida para os desenvolvedores e proprietários do projeto.
Naturalmente, precisávamos ter uma opção para colocar alguns CVEs na lista de permissões ou substituir esse comportamento padrão por projeto. Então criamos um repositório com perfis de verificação de segurança que são consumidos pela nossa ferramenta de verificação, que envolve a execução do Trivy e manipula seu comportamento e saída.
Agora qualquer desenvolvedor pode enviar uma solicitação de mesclagem para este repositório e solicitar uma exceção. Exemplo de perfil para o projeto Kibana :
Esta implementação de varredura de segurança é uma base sólida que pode ser estendida além dos nossos casos de uso iniciais. Por exemplo:
Você pode encontrar o Dockerfile e as ferramentas em nosso repositório público do Gitlab: https://gitlab.com/voltera.io/security-scanning
Obrigado a Jakub Pavlík .