Recomendações para proteger um ciclo de vida de desenvolvimento

Aplica-se a esta recomendação de lista de verificação de Segurança do Azure Well-Architected Framework:

SE:02 Mantenha um ciclo de vida de desenvolvimento seguro usando uma cadeia de fornecimento de software protegida, principalmente automatizada e auditável. Incorpore um design seguro usando a modelagem de ameaças para proteger contra implementações que derrotam a segurança.

Guia relacionado: Análise de ameaças

Este guia descreve as recomendações para proteger o código, o ambiente de desenvolvimento e a cadeia de fornecedores de software aplicando as melhores práticas de segurança ao longo do ciclo de desenvolvimento. Para entender essas diretrizes, você deve ter conhecimento de DevSecOps.

Um diagrama do ciclo de segurança.

O DevSecOps integra a segurança aos processos de DevOps:

  • Automatizando o teste de segurança e a validação.

  • Implementando ferramentas como pipelines de segurança para verificar o código e a IaC (infraestrutura como código) em busca de vulnerabilidades.

No núcleo de uma carga de trabalho está o código do aplicativo que implementa a lógica de negócios. O código e o processo de desenvolvimento de código devem estar livres de defeitos de segurança para garantir a confidencialidade, a integridade e a disponibilidade.

Não basta proteger apenas o plano de infraestrutura usando controles sobre identidade e rede e outras medidas. Impedir a implementação incorreta de código ou um bloco de código comprometido para fortalecer sua postura de segurança geral. O plano de uso, ou seja, o código do aplicativo, também deve ser protegido. O processo de integração da segurança ao ciclo de vida de desenvolvimento é essencialmente um processo de proteção. Assim como a proteção de recursos, o aprimoramento do desenvolvimento de código também é independente de contexto. O foco é aumentar a segurança e não os requisitos funcionais do aplicativo. Para obter informações relacionadas à proteção, consulte Recomendações para proteger recursos.

Definições

Termo Definição
SDL (Security Development Lifecycle) Um conjunto de práticas fornecidas pela Microsoft que dá suporte aos requisitos de garantia de segurança e conformidade.
SDLC (ciclo de vida de desenvolvimento de software) Um processo sistemático de vários estágios para o desenvolvimento de sistemas de software.

Principais estratégias de design

As medidas de segurança devem ser integradas em vários pontos ao SDLC (Ciclo de Vida de Desenvolvimento de Software) existente para garantir:

  • As opções de design não levam a lacunas de segurança.

  • O código e a configuração do aplicativo não criam vulnerabilidades devido à implementação explorável e às práticas de codificação inadequadas.

  • O software adquirido por meio da cadeia de suprimentos não introduz ameaças à segurança.

  • Os processos de código do aplicativo, build e implantação não são adulterados.

  • As vulnerabilidades reveladas por meio de incidentes são atenuadas.

  • Os ativos não utilizados são desativados corretamente.

  • Os requisitos de conformidade não são comprometidos ou reduzidos.

  • O log de auditoria é implementado em ambientes de desenvolvedor.

As seções a seguir fornecem estratégias de segurança para as fases comumente praticadas do SDLC.

Fase de requisitos

O objetivo da fase de requisitos é coletar e analisar os requisitos funcionais e não funcionais de um aplicativo ou um novo recurso de um aplicativo. Essa fase é importante porque facilita a criação de proteções adaptadas aos objetivos do aplicativo. Proteger os dados e a integridade do aplicativo deve ser um requisito fundamental em todas as fases do ciclo de vida de desenvolvimento.

Por exemplo, considere um aplicativo que precisa dar suporte a fluxos de usuário críticos que permitem que o usuário carregue e manipule dados. As opções de design de segurança devem abranger garantias para a interação do usuário com o aplicativo, como autenticar e autorizar a identidade do usuário, permitir apenas ações permitidas nos dados e impedir a injeção de SQL. Da mesma forma, abrange os requisitos não funcionais, como disponibilidade, escalabilidade e manutenção. As opções de segurança devem incluir limites de segmentação, entrada e saída de firewall e outras preocupações de segurança de corte cruzado.

Todas essas decisões devem levar a uma boa definição da postura de segurança do aplicativo. Documente os requisitos de segurança em uma especificação acordada e reflita-os na lista de pendências. Ele deve declarar explicitamente os investimentos em segurança e as compensações e riscos que a empresa está disposta a assumir se os investimentos não forem aprovados pelos stakeholders empresariais. Por exemplo, você pode documentar a necessidade de usar um WAF (firewall de aplicativo Web) na frente do aplicativo, como o Azure Front Door ou Gateway de Aplicativo do Azure. Se os stakeholders de negócios não estiverem preparados para aceitar o custo adicional da execução de um WAF, eles precisarão aceitar o risco de que ataques de camada de aplicativo possam ser direcionados para o aplicativo.

A coleta de requisitos de segurança é uma parte crítica dessa fase. Sem esse esforço, as fases de design e implementação serão baseadas em opções não declaradas, o que pode levar a lacunas de segurança. Talvez seja necessário alterar a implementação mais tarde para acomodar a segurança, o que pode ser caro.

Fase de design

Durante essa fase, os requisitos de segurança são convertidos em requisitos técnicos. Em sua especificação técnica, documente todas as decisões de design para evitar ambiguidade durante a implementação. Aqui estão algumas tarefas típicas:

Definir a dimensão de segurança da arquitetura do sistema

Sobreponha a arquitetura com controles de segurança. Por exemplo, controles práticos sobre os limites de isolamento de acordo com sua estratégia de segmentação, os tipos de identidades necessários para os componentes do aplicativo e o tipo de métodos de criptografia a serem usados. Para obter algumas arquiteturas de exemplo, consulte as ilustrações nas seções Exemplo dos artigos Gerenciamento de identidade e acesso e Rede .

Avaliar as funcionalidades fornecidas pela plataforma

É importante entender a divisão de responsabilidade entre você e o provedor de nuvem. Evite a sobreposição com controles de segurança nativos do Azure, por exemplo. Você obterá uma melhor cobertura de segurança e poderá realocar recursos de desenvolvimento para as necessidades do aplicativo.

Por exemplo, se o design chamar um firewall de aplicativo Web na entrada, você poderá descarregar essa responsabilidade para um balanceador de carga como Gateway de Aplicativo ou Azure Front Door. Evite replicar recursos como código personalizado em seu aplicativo.

Escolha apenas estruturas confiáveis, bibliotecas e software da cadeia de suprimentos. Seu design também deve especificar o controle de versão seguro. As dependências do aplicativo devem ser originadas de partes confiáveis. Fornecedores de terceiros devem ser capazes de atender aos seus requisitos de segurança e compartilhar seu plano de divulgação responsável. Qualquer incidente de segurança deve ser imediatamente relatado para que você possa tomar as ações necessárias. Além disso, determinadas bibliotecas podem ser proibidas pela sua organização. Por exemplo, o software pode estar seguro contra vulnerabilidades, mas ainda não permitido devido a restrições de licenciamento.

Para garantir que essas diretrizes sejam seguidas por todos os colaboradores do software, mantenha uma lista de estruturas, bibliotecas e fornecedores aprovados e/ou não aprovados. Quando possível, coloque os guardrails nos pipelines de desenvolvimento para dar suporte à lista. Tanto quanto possível, automatize o uso de ferramentas para verificar dependências em busca de vulnerabilidades.

Determine os padrões de design de segurança que o código do aplicativo deve implementar.

Os padrões podem dar suporte a preocupações de segurança, como segmentação e isolamento, autorização forte, segurança de aplicativo uniforme e protocolos modernos. Alguns padrões operacionais, como o padrão de quarentena, podem ajudar a verificar e bloquear o uso de software que poderia potencialmente introduzir vulnerabilidades de segurança.

Para obter mais informações, consulte Padrões de design de nuvem que dão suporte à segurança.

Armazenar segredos do aplicativo com segurança

Implemente com segurança o uso de segredos do aplicativo e chaves pré-compartilhadas que seu aplicativo usa. Credenciais e segredos do aplicativo nunca devem ser armazenados na árvore de código-fonte. Use recursos externos como o Azure Key Vault para garantir que, se o código-fonte ficar disponível para um invasor em potencial, nenhum acesso adicional poderá ser obtido. Em geral, encontre maneiras de evitar segredos. Usar identidades gerenciadas, quando possível, é uma maneira de atingir essa meta. Para obter mais informações, consulte Recomendações para gerenciar segredos do aplicativo.

Definir planos de teste

Defina casos de teste claros para requisitos de segurança. Avalie se você pode automatizar esses testes em seus pipelines. Se sua equipe tiver processos para teste manual, inclua requisitos de segurança para esses testes.

Observação

Execute a modelagem de ameaças durante essa fase. A modelagem de ameaças pode confirmar que as opções de design estão alinhadas com os requisitos de segurança e expor lacunas que você deve atenuar. Se sua carga de trabalho lidar com dados altamente confidenciais, invista em especialistas em segurança que possam ajudá-lo a conduzir a modelagem de ameaças.

O exercício inicial de modelagem de ameaças deve ocorrer durante a fase de design quando a arquitetura do software e o design de alto nível estão sendo definidos. Fazer isso durante essa fase ajuda você a identificar possíveis problemas de segurança antes que eles sejam incorporados à estrutura do sistema. No entanto, este exercício não é uma atividade única. É um processo contínuo que deve continuar durante toda a evolução do software.

Para obter mais informações, consulte Recomendações para análise de ameaças.

Fase de desenvolvimento e teste

Durante essa fase, a meta é evitar falhas de segurança e adulteração em pipelines de código, build e implantação.

Seja bem treinado em práticas de código seguro

A equipe de desenvolvimento deve ter treinamento formal e especializado em práticas de codificação seguras. Por exemplo, os desenvolvedores da Web e da API podem precisar de treinamento específico para proteger contra ataques de script entre sites, e os desenvolvedores de back-end podem se beneficiar do treinamento detalhado para evitar ataques no nível do banco de dados, como ataques de injeção de SQL.

Os desenvolvedores devem ser obrigados a concluir esse treinamento antes de obter acesso ao código-fonte de produção.

Você também deve executar revisões internas de código par para promover o aprendizado contínuo.

Usar ferramentas de teste de segurança

Execute a modelagem de ameaças para avaliar a segurança da arquitetura do aplicativo.

Use o SAST (teste de segurança de aplicativo estático) para analisar o código em busca de vulnerabilidades. Integre essa metodologia ao ambiente do desenvolvedor para detectar vulnerabilidades em tempo real.

Use o DAST (teste de segurança de aplicativo dinâmico) durante o runtime. Essa cadeia de ferramentas pode marcar erros em domínios de segurança e simular um conjunto de ataques para testar a resiliência de segurança do aplicativo. Quando possível, integre essa ferramenta aos pipelines de build.

Siga os padrões do setor para práticas de codificação seguras. Para obter mais informações, consulte a seção Recursos da comunidade deste artigo.

Use linters e analisadores de código para impedir que as credenciais sejam enviadas por push para o repositório de código-fonte. Por exemplo, .NET Compiler Platform (Roslyn) Analisadores inspecionam o código do aplicativo.

Durante o processo de build, use complementos de pipeline para capturar credenciais no código-fonte. Examine todas as dependências, como bibliotecas de terceiros e componentes de estrutura, como parte do processo de integração contínua. Investigue os componentes vulneráveis sinalizados pela ferramenta. Combine essa tarefa com outras de verificação de código que inspecionam rotatividade de código, resultados de teste e cobertura.

Use uma combinação de testes. Para obter informações sobre testes de segurança em geral, consulte Recomendações para testes de segurança.

Escrever apenas código suficiente

Ao reduzir o volume de código, você também reduz as chances de defeitos de segurança. Reutilize código e bibliotecas que já estão em uso e passaram por validações de segurança em vez de duplicar código.

Aproveitar os recursos do Azure é outra maneira de evitar código desnecessário. Uma maneira é usar serviços gerenciados. Para obter mais informações, consulte Usar as opções de PaaS (plataforma como serviço).

Escreva código com uma abordagem negar tudo por padrão. Crie listas de permitidos somente para entidades que precisam de acesso. Por exemplo, se você tiver um código que precisa determinar se uma operação privilegiada deve ser permitida, escreva-a para que o resultado da negação seja o caso padrão e o resultado de permissão ocorra somente quando especificamente permitido pelo código.

Proteger ambientes de desenvolvedor

As estações de trabalho do desenvolvedor precisam ser protegidas com fortes controles de rede e identidade para evitar a exposição. Verifique se as atualizações de segurança são aplicadas diligentemente.

Os agentes de build são altamente privilegiados e têm acesso ao servidor de build e ao código. Eles devem ser protegidos com o mesmo rigor que os componentes da carga de trabalho. Isso significa que o acesso aos agentes de build deve ser autenticado e autorizado, eles devem ser segmentados na rede com controles de firewall, eles devem estar sujeitos à verificação de vulnerabilidades e assim por diante. Os agentes de build hospedados pela Microsoft devem ser preferenciais em relação aos agentes de build auto-hospedados. Os agentes hospedados pela Microsoft fornecem benefícios como limpo máquinas virtuais para cada execução de um pipeline.

Os agentes de build personalizados adicionam complexidade de gerenciamento e podem se tornar um vetor de ataque. As credenciais do computador de build devem ser armazenadas com segurança e você precisa remover regularmente quaisquer artefatos de build temporários do sistema de arquivos. Você pode obter isolamento de rede permitindo apenas o tráfego de saída do agente de build, pois ele está usando o modelo de pull de comunicação com o Azure DevOps.

O repositório de código-fonte também deve ser protegido . Conceda acesso a repositórios de código com base na necessidade de saber e reduza a exposição de vulnerabilidades o máximo possível para evitar ataques. Tenha um processo completo para examinar o código quanto a vulnerabilidades de segurança. Use grupos de segurança para essa finalidade e implemente um processo de aprovação baseado em justificativas comerciais.

Implantações de código seguro

Não basta apenas proteger o código. Se ele for executado em pipelines exploráveis, todos os esforços de segurança serão inúteis e incompletos. Ambientes de build e lançamento também devem ser protegidos porque você deseja impedir que atores mal-intencionados executem código mal-intencionado em seu pipeline.

Manter um inventário atualizado de cada componente integrado ao seu aplicativo

Cada novo componente integrado a um aplicativo aumenta a superfície de ataque. Para garantir a responsabilidade e os alertas adequados quando novos componentes forem adicionados ou atualizados, você deve ter um inventário desses componentes. Armazene-o fora do ambiente de build. Regularmente, marcar que seu manifesto corresponda ao que está em seu processo de build. Isso ajuda a garantir que nenhum componente novo que contenha portas traseiras ou outros malwares seja adicionado inesperadamente.

Tarefas de pipeline

  • Efetuar pull de tarefas em seu pipeline de fontes confiáveis, como Azure Marketplace. Execute tarefas que são gravadas pelo fornecedor do pipeline. Recomendamos tarefas ou GitHub Actions do GitHub. Se você usar fluxos de trabalho do GitHub, prefira tarefas criadas pela Microsoft. Além disso, valide as tarefas porque elas são executadas no contexto de segurança do pipeline.

  • Segredos do pipeline. Os ativos de implantação executados dentro de um pipeline têm acesso a todos os segredos nesse pipeline. Tenha uma segmentação adequada em vigor para diferentes estágios do pipeline para evitar exposição desnecessária. Use repositórios de segredos integrados ao pipeline. Lembre-se de que você pode evitar o uso de segredos em algumas situações. Explore o uso de identidades de carga de trabalho (para autenticação de pipeline) e identidades gerenciadas (para autenticação serviço a serviço).

Manter ambientes diferentes separados

Os dados usados em ambientes diferentes devem ser mantidos separados. Os dados de produção não devem ser usados em ambientes inferiores porque esses ambientes podem não ter os controles de segurança estritos que a produção tem. Evite se conectar de um aplicativo de não produção a um banco de dados de produção e evite conectar componentes de não produção a redes de produção.

Exposição progressiva

Use a exposição progressiva para liberar recursos para um subconjunto de usuários com base nos critérios escolhidos. Se houver problemas, o impacto será minimizado para esses usuários. Essa abordagem é uma estratégia comum de mitigação de risco porque reduz a área de superfície. À medida que o recurso amadurece e você tem mais confiança em garantias de segurança, você pode liberá-lo gradualmente para um conjunto mais amplo de usuários.

Fase de produção

A fase de produção apresenta a última oportunidade responsável para corrigir lacunas de segurança. Mantenha um registro da imagem dourada lançada em produção.

Manter artefatos com controle de versão

Mantenha um catálogo de todos os ativos implantados e suas versões. Essas informações são úteis durante a triagem de incidentes, quando você está mitigando problemas e quando está fazendo o sistema voltar ao estado de trabalho. Os ativos com controle de versão também podem ser comparados com os avisos de CVE (Vulnerabilidades e Exposições Comuns) publicados. Você deve usar a automação para executar essas comparações.

Correções de emergência

Seu design de pipeline automatizado deve ter a flexibilidade de dar suporte a implantações regulares e de emergência. Essa flexibilidade é importante para dar suporte a correções de segurança rápidas e responsáveis.

Uma versão normalmente está associada a vários portões de aprovação. Considere criar um processo de emergência para acelerar as correções de segurança. O processo pode envolver a comunicação entre as equipes. O pipeline deve permitir implantações rápidas de roll forward e reversão que abordam correções de segurança, bugs críticos e atualizações de código que ocorrem fora do ciclo de vida de implantação regular.

Observação

Sempre priorize as correções de segurança em vez de conveniência. Uma correção de segurança não deve introduzir uma regressão ou bug. Se você quiser acelerar a correção por meio de um pipeline de emergência, considere cuidadosamente quais testes automatizados podem ser ignorados. Estime o valor de cada teste em relação ao tempo de execução. Por exemplo, os testes de unidade geralmente são concluídos rapidamente. A execução de testes de integração ou de ponta a ponta podem ser muito demorada.

Fase de manutenção

O objetivo dessa fase é garantir que a postura de segurança não se decaia ao longo do tempo. O SDLC é um processo ágil contínuo. Os conceitos abordados nas fases anteriores se aplicam a essa fase porque os requisitos mudam ao longo do tempo.

Gerenciamento de patch. Mantenha os componentes de software, bibliotecas e infraestrutura atualizados com patches e atualizações de segurança.

Melhoria contínua. Avalie e melhore continuamente a segurança do processo de desenvolvimento de software levando em conta revisões de código, comentários, lições aprendidas e ameaças em evolução.

Desativar ativos herdados obsoletos ou que não estão mais em uso. Isso reduz a área de superfície do aplicativo.

A manutenção também inclui correções de incidentes. Se forem encontrados problemas na produção, eles precisarão ser prontamente integrados novamente ao processo para que não se repitam.

Aprimore continuamente suas práticas de codificação segura para acompanhar o cenário de ameaças.

Facilitação do Azure

O Microsoft SDL (Security Development Lifecycle) recomenda práticas seguras que você pode aplicar ao seu ciclo de vida de desenvolvimento. Para obter mais informações, consulte Ciclo de vida de desenvolvimento de segurança da Microsoft.

O Defender para DevOps e as ferramentas SAST são incluídos como parte do GitHub Advanced Security ou do Azure DevOps. Essas ferramentas podem ajudá-lo a acompanhar uma pontuação de segurança para sua organização.

Siga as recomendações de segurança do Azure descritas nestes recursos:

Para localizar credenciais no código-fonte, considere o uso de ferramentas como ferramentas de análise de código-fonte GitHub Advanced Security e OWASP.

Valide a segurança de qualquer código de código aberto em seu aplicativo. Essas ferramentas e recursos gratuitos podem ajudá-lo com sua avaliação:

Lista de verificação de segurança

Consulte o conjunto completo de recomendações.