O blog da AWS
DevSecOps com DAST e Security Hub
Por Maria Ane Dias, Arquiteta de Soluções de segurança na AWS
e Wesley Rodrigues, Arquiteto de Soluções Sênior na AWS
Introdução
Os testes de software mais comumente encontrados são do tipo estático, que, por olharem apenas para o código fonte sem construir e executar a aplicação, são incapazes de encontrar problemas de segurança que aparecem apenas durante o uso. Tais problemas figuram entre os 10 riscos mais comuns mapeados pela OWASP.
Existem artigos detalhados sobre a implementação do ZAP como ferramenta de DAST em conjunto com o AWS CodePipeline. O objetivo deste artigo é expandir as possibilidades exploradas em artigos como o https://thinkwithwp.com/pt/blogs/aws-brasil/construindo-um-pipeline-de-ci-cd-aws-devsecops-de-ponta-a-ponta-com-ferramentas-de-codigo-aberto-sca-sast-e-dast/, do Srinivas Manepalli, trazendo cenários comuns entre clientes da AWS e permitindo que a solução seja adaptada para os mais diversos cenários.
Funcionamento
A etapa de testes dinâmicos de segurança pode ser modificada para funcionar na maioria das ferramentas de CI/CD como um passo adicional no pipeline da aplicação web. A ferramenta de CI vai implementar o código da aplicação web (um Moodle, Magento, WordPress, Joomla, ou mesmo uma aplicação customizada em Rails, Django, React.JS, etc.) em um servidor de testes. Em seguida, o CI faz uma chamada de API para o servidor do OWASP ZAP com a URL do servidor de testes com a aplicação web. O ZAP executa os testes na aplicação, e o CI publica os resultados no AWS Security Hub.
Um exemplo bastante comum pode ser encontrado na figura abaixo:
Figura 1 – exemplo de arquitetura de pipeline com DAST e AWS Security HUB
- O CI/CD Server busca as alterações no código fonte, executa os testes unitários, testes estáticos de segurança, etc.
- O CI/CD Server faz o deploy da aplicação em um servidor web de testes (em uma rede privada).
- O CI/CD Server faz uma chamada de API para o servidor do OWASP ZAP com a URL a ser verificada.
- O CI/CD Server publica os resultados no AWS Security Hub.
A flexibilidade em utilizar o ZAP para automação se dá principalmente pela API muito bem documentada, com a qual é possível:
- Iniciar uma varredura: http://URL_DO_ZAP/JSON/ascan/action/scan/
- Consultar o status de uma varredura: http://URL_DO_ZAP/JSON/ascan/view/status/
- Baixar o relatório: http://URL_DO_ZAP/JSON/alert/view/alertsSummary/
Estes passos podem ser implementados em HTTP, com CURL, ou com clientes em Python, Ruby, Java, entre outras linguagens. Para automatizar a execução do Spider Scan em Python, por exemplo, o código ficaria assim:
import requests
import os
headers = {
'Accept': 'application/json',
'X-ZAP-API-Key': os.environ['ZAP_API_KEY']
}
r = requests.get('http://URL_DO_ZAP/JSON/spider/action/scan/', params={
}, headers = headers)
print(r.json())
Detalhes da Implementação
Pré-requisitos
OWASP ZAP
Para utilizar o OWASP ZAP, é necessário instalar o programa em um servidor, que será acionado via API durante os testes. Neste exemplo foi utilizado um servidor Windows em uma instância EC2, mas Linux é perfeitamente suportado. O processo de instalação do ZAP requer apenas o Java, e é bastante simples:
Crie uma instância EC2. Inicie com um tamanho pequeno (para este exemplo, foi utilizada uma instância t2micro free tier Windows Server 2012). Escale conforme a necessidade, de acordo com a quantidade de jobs paralelos. Clique aqui para saber mais sobre como iniciar uma instância EC2.
O ZAP funciona com o JAVA 8, e a Amazon disponibiliza o Corretto, uma distribuição baseada na OpenJDK.
É nececssário liberar as portas do ZAP no security group, mas apenas para os IPs que serão autorizados a fazer as requisições — o IP do AWS CodeBuild/CodePipeline, neste caso. Para evitar expor o ZAP na Internet, o AWS CodeBuild pode ser configurado para executar no VPC, em uma subnet com acesso ao servidor do ZAP.
Ao abrir o OWASP ZAP pela primeira vez, o Windows Firewall irá bloqueá-lo. Uma janela será aberta com a opção Public Networks marcada, mas para que ele funcione corretamente, precisa ser liberado em ambos; public e private:
Figura 2 – Liberação do ZAP no firewall do Windows
Como o servidor está rodando em uma EC2, é preciso que em vez de responder no localhost ele responda no IP público da instância. Para isso, clique em Tools -> Options-> Local Proxies -> Address 0.0.0.0 e selecionar Behind NAT:
Figura 3 – Configuração do ZAP Proxy
Anote a chave da API. Clique em Tools -> Options -> API -> API Key:
Figura 4 – Obtendo a API Key
Autorize que a API seja acessada por IPs externos clicando em Add e adicionando o padrão .* à regra:
Figura 5 – Permitindo o acesso à API do ZAP
Reinicie o OWASP ZAP. Caso você precise ver os logs inicie o OWASP ZAP pela linha de comando (PowerShell), executando o arquivo zap.bat:
Figura 6 – Arquivos do ZAP
Nota: O IP publico da instância EC2 é modificado quando ela é reiniciada. Caso você deseje que o IP público não mude, use um IP Elástico associado a EC2. Os IPs elásticos só são cobrados quando não utilizados. Saiba mais clicando aqui.
AWS Security Hub e AWS Config
O AWS Security Hub oferece uma visão abrangente dos alertas de segurança de alta prioridade e do status de conformidade nas contas da AWS. Existem várias ferramentas de segurança avançadas à sua disposição, de firewalls e proteção de endpoints até verificadores de vulnerabilidades e conformidade. Mas, muitas vezes, sua equipe é obrigada a alternar entre essas ferramentas para lidar com centenas (e, às vezes, milhares) de alertas de segurança a cada dia. Com o Security Hub, agora você tem um único local que agrega, organiza e prioriza alertas de segurança, ou descobertas, de vários serviços da AWS, como o Amazon GuardDuty, o Amazon Inspector e o Amazon Macie, bem como das soluções de parceiros da AWS e soluções personalizadas, como a explicada neste artigo.
Figura 7 – Tela inicial do AWS Security Hub
O AWS Security Hub utiliza um formato padronizado baseado em JSON para receber as informações de descobertas. O Formato de descoberta de segurança da AWS (ASFF, do inglês AWS Security Finding Format) elimina a necessidade de esforços demorados de conversão de dados, e correlaciona as descobertas ingeridas nos produtos para priorizar as mais importantes. Filtrar campos de logs em JSON para transformá-los em ASFF é uma tarefa leve e bastante documentada.
O serviço AWS Security Hub utiliza o AWS Config para executar a maioria de suas verificações de segurança para controles. O AWS Config é um serviço que permite acessar, auditar e avaliar as configurações dos recursos da AWS. O AWS Config monitora e grava continuamente registros das configurações de recursos da AWS e lhe permite automatizar a avaliação das configurações registradas com base nas configurações desejadas.
Figura 8 – Regras do AWS Config
No canal do YouTube Amazon Web Services Latin America há vídeos explicando em detalhes como habilitar e configurar o AWS Security Hub, o AWS Config e diversos outros serviços relacionados à segurança, como estes: AWS Security Hub – Como habilitar em 5min e AWS Config Demo (Hands On).
Pipeline da Aplicação
No artigo do Srinivas Manepalli, o código implementa um passo do AWS CodePipeline que solicita alguns dados, como a URL do servidor ZAP e a API KEY, e todo o resto é executado sem que o usuário interaja com o serviço. Mas, de fato, o que está acontecendo durante a execução?
O código do pipeline é descrito neste YAML:
##Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. ##SPDX-License-Identifier: MIT-0
version: 0.2
phases:
install:
commands:
- echo "install phase....."
pre_build:
commands:
- scanid=$(curl "$OwaspZapURL/JSON/ascan/action/scan/?apikey=$OwaspZapApiKey&url=$ApplicationURL&recurse=true&inScopeOnly=&scanPolicyName=&method=&postData=&contextId=" | jq -r '.scan')
- |
stat=50;
while [ "$stat" != 100 ]; do
stat=$(curl "$OwaspZapURL/JSON/ascan/view/status/?apikey=zapapikey&scanId=$scanid" | jq -r '.status');
echo "OWASP ZAP scan status is $stat"
echo "OWASP Zap analysis status is in progress...";
sleep 5;
done
echo "OWASP Zap analysis status is completed...";
- high_alerts=$( curl "$OwaspZapURL/JSON/alert/view/alertsSummary/?apikey=$OwaspZapApiKey&baseurl=$ApplicationURL" | jq -r '.alertsSummary.High') - medium_alerts=$( curl "$OwaspZapURL/JSON/alert/view/alertsSummary/?apikey=$OwaspZapApiKey&baseurl=$ApplicationURL" | jq -r '.alertsSummary.Medium') - echo "high alerts are $high_alerts"
build:
commands:
- curl "$OwaspZapURL/OTHER/core/other/jsonreport/?apikey=$OwaspZapApiKey" | jq . > zap-scan-results.json
- echo "build stage completed"
post_build:
commands:
- |
jq "{ \"messageType\": \"CodeScanReport\", \"reportType\": \"OWASP-Zap\", \
\"createdAt\": $(date +\"%Y-%m-%dT%H:%M:%S.%3NZ\"), \"source_repository\": env.CODEBUILD_SOURCE_REPO_URL, \
\"source_branch\": env.CODEBUILD_SOURCE_VERSION, \
\"build_id\": env.CODEBUILD_BUILD_ID, \
\"source_commitid\": env.CODEBUILD_RESOLVED_SOURCE_VERSION, \
\"report\": . }" zap-scan-results.json > payload.json
aws lambda invoke --function-name ImportVulToSecurityHub --payload file://payload.json owaspzap_scan_report.json && echo "LAMBDA_SUCCEDED" || echo "LAMBDA_FAILED";
- if [ $high_alerts -gt 0 ] || [ $medium_alerts -gt 0 ]; then echo "there are high or medium alerts.. failing the build" && exit 1; else exit 0; fi
artifacts:
type: zip
files: '**/*'
Aqui, as ações são muito parecidas com o desenho do WordPress + Jenkins que foi explicado no início do artigo. Dentro do bloco de comandos, a linha que começa com – scanid=$(curl “$OwaspZapURL/JSON/ascan/action/scan/? está invocando a API de Scan do ZAP, passando entre os parâmetros a URL da aplicação web que será testada. Isso faz com que o scan seja iniciado, e seu ID seja salvo para consultar o status na sequência. A consulta de status é feita dentro de um loop: a cada 5 segundos o CI/CD verifica se o status do scan é 100 (completo). A verificação do status ocorre na linha que começa com stat=$(curl “$OwaspZapURL/JSON/ascan/view/status/?.
Depois que o job agendado termina de executar, a linha que começa com – curl “$OwaspZapURL/OTHER/core/other/jsonreport/ baixa o relatório em formato JSON, que é tratado e usado como payload para a função do AWS Lambda, que é invocada pelo CI/CD para atualizar o status no AWS Security Hub.
Considerações Finais
O fato do ZAP ter uma API completa e bem documentada, e de a AWS ter serviços para execução de código, como o AWS Lambda, para filas, como o Amazon SQS, de logs e eventos agendados, como o Amazon CloudWatch, de armazenamento de parâmetros, como o AWS Systems Manager Parameter Store, entre muitos outros, torna as possibilidades quase infinitas. Por exemplo:
- Após um problema de SQL Injection ser encontrado em uma aplicação que utiliza bancos de dados, um e-mail pode ser disparado automaticamente para o time de DBAs e para o time de segurança.
- O ZAP consegue testar formulários com listas de logins e senhas. Uma varredura que encontre um usuário do sistema com credenciais padrão ou definidas com senhas fracas como PASSWORD, 123456, etc., pode fazer com que uma função do AWS Lambda seja disparada, bloqueando e notificando o usuário automaticamente para que a senha seja trocada.
- Relatórios do ZAP de bibliotecas com vulnerabilidades conhecidas podem ser usados como insumo para a priorização de tarefas em times ágeis que dão manutenção nestes aplicativos.
Enfim, esperamos ter mostrado o quanto a solução é flexível e pode ser moldada para diferentes cenários. Segurança deve ser pensada em todas as etapas.
Sobre os autores
Maria Ane Dias é arquiteta de soluções de segurança na AWS e gosta bastante da área de Desenvolvimento e IoT além da vertical de Manufatura. Atua auxiliando clientes em suas jornadas seguras para a nuvem. Tem 16 anos de experiência em desenvolvimento e arquitetura de software e 3 com arquitetura de soluções.
Wesley Rodrigues é arquiteto de soluções sênior curioso e apaixonado por aprender novas tecnologias. Adora estudar segurança, inteligência artificial e eletrônica, e usa estes conhecimentos para ajudar os clientes do setor de educação em suas jornadas para a nuvem. Ama Linux, Open Source, música e boa comida com os amigos.