Partilhar via


Práticas recomendadas para uma cadeia de suprimentos de software segura

O código aberto está em toda parte. Está em muitas bases de código proprietárias e projetos comunitários. Para organizações e indivíduos, a questão hoje não é se você está ou não usando código aberto, mas qual código de código aberto você está usando e quanto.

Se você não estiver ciente do que está em sua cadeia de suprimentos de software, uma vulnerabilidade upstream em uma de suas dependências pode ser fatal, tornando você e seus clientes vulneráveis a um possível comprometimento. Neste documento, vamos nos aprofundar no que o termo "cadeia de suprimentos de software" significa, por que é importante e como você pode ajudar a proteger a cadeia de suprimentos do seu projeto com as melhores práticas.

O Estado do Octoverso 2020 - Código Aberto

Dependências

O termo cadeia de suprimentos de software é usado para se referir a tudo o que entra no seu software e de onde ele vem. É das dependências e propriedades das suas dependências que a cadeia de suprimentos de software depende. Uma dependência é o que o seu software precisa para ser executado. Pode ser código, binários ou outros componentes, e de onde eles vêm, como um repositório ou gerenciador de pacotes.

Ele inclui quem escreveu o código, quando ele foi contribuído, como ele foi revisado para problemas de segurança, vulnerabilidades conhecidas, versões suportadas, informações de licença e praticamente qualquer coisa que o toque em qualquer ponto do processo.

Sua cadeia de suprimentos também abrange outras partes de sua pilha além de um único aplicativo, como seus scripts de compilação e empacotamento ou o software que executa a infraestrutura na qual seu aplicativo depende.

Vulnerabilidades

Hoje, as dependências de software são generalizadas. É bastante comum que seus projetos usem centenas de dependências de código aberto para funcionalidades que você não precisava escrever. Isso pode significar que a maior parte do seu aplicativo consiste em código que você não criou.

O Estado do Octoverse 2020 - Dependências

Possíveis vulnerabilidades em suas dependências de terceiros ou de código aberto são presumivelmente dependências que você não pode controlar tão rigorosamente quanto o código que você escreve, o que pode criar riscos potenciais de segurança em sua cadeia de suprimentos.

Se uma dessas dependências tiver uma vulnerabilidade, é provável que você também tenha uma vulnerabilidade. Isso pode ser assustador, pois uma de suas dependências pode mudar sem que você saiba. Mesmo que uma vulnerabilidade exista hoje numa dependência, mas não seja explorável, pode ser explorável no futuro.

Ser capaz de alavancar o trabalho de milhares de desenvolvedores de código aberto e autores de bibliotecas significa que milhares de estranhos podem efetivamente contribuir diretamente para o seu código de produção. O seu produto, através da sua cadeia de fornecimento de software, é afetado por vulnerabilidades não corrigidas, erros inocentes ou até mesmo ataques maliciosos contra dependências.

Comprometimento da cadeia de suprimentos

A definição tradicional de cadeia de abastecimento provém do fabrico; é a cadeia de processos necessários para fazer e fornecer algo. Inclui planejamento, fornecimento de materiais, fabricação e varejo. Uma cadeia de fornecimento de software é semelhante, exceto que em vez de materiais, é código. Em vez de fabricar, é desenvolvimento. Em vez de extrair minério do chão, o código é proveniente de fornecedores, comerciais ou de código aberto, e, em geral, o código de fonte aberta vem de repositórios. Adicionar código de um repositório significa que seu produto depende desse código.

Um exemplo de um ataque à cadeia de suprimentos de software ocorre quando um código mal-intencionado é adicionado propositalmente a uma dependência, usando a cadeia de suprimentos dessa dependência para distribuir o código para suas vítimas. Os ataques à cadeia de abastecimento são reais. Existem muitos métodos para atacar uma cadeia de suprimentos, desde inserir diretamente código malicioso como um novo contribuidor, até assumir a conta de um colaborador sem que outros percebam, ou até mesmo comprometer uma chave de assinatura para distribuir software que não é oficialmente parte da dependência.

Um ataque à cadeia de suprimentos de software raramente é o objetivo final, em vez disso, é o início de uma oportunidade para um invasor inserir malware ou fornecer um backdoor para acesso futuro.

O Estado do Octoverse 2020 - Ciclo de Vida da Vulnerabilidade

Software sem patches

O uso de código aberto hoje é significativo e não se espera que desacelere tão cedo. Dado que não vamos parar de usar software de código aberto, a ameaça à segurança da cadeia de suprimentos é o software sem patch. Sabendo disso, como você pode lidar com o risco de que uma dependência do seu projeto tenha uma vulnerabilidade?

  • Saber o que está no seu ambiente. Isso requer descobrir suas dependências e quaisquer dependências transitivas para entender os riscos dessas dependências, como vulnerabilidades ou restrições de licenciamento.
  • Gerencie suas dependências. Quando uma nova vulnerabilidade de segurança é descoberta, você deve determinar se foi afetado e, em caso afirmativo, atualizar para a versão mais recente e o patch de segurança disponível. Isso é especialmente importante para revisar as alterações que introduzem novas dependências ou auditar regularmente as dependências mais antigas.
  • Monitorize a sua cadeia de abastecimento. Isso ocorre auditando os controles que você tem em vigor para gerenciar suas dependências. Isso irá ajudá-lo a impor condições mais restritivas que devem ser cumpridas para as suas dependências.

O Estado da Octoverse 2020 - Avisos

Abordaremos várias ferramentas e técnicas que o NuGet e o GitHub fornecem, que você pode usar hoje para lidar com riscos potenciais dentro do seu projeto.

Saber o que está no seu ambiente

Pacotes com vulnerabilidades conhecidas

📦 Consumidor de Pacotes | 📦🖊 Autor do pacote

O .NET 8 e o Visual Studio 17.8 adicionaram o NuGetAudit, que avisará sobre pacotes diretos com vulnerabilidades conhecidas durante a restauração. O .NET 9 e o Visual Studio 17.12 também alteraram o padrão para avisar sobre pacotes transitivos.

O NuGetAudit requer uma fonte para fornecer um banco de dados de vulnerabilidades conhecidas, portanto, se você não estiver usando nuget.org como uma fonte de pacote, deverá adicioná-la como uma fonte de auditoria.

No momento em que o NuGet o avisa, a vulnerabilidade é conhecida publicamente. Os atacantes podem usar essa divulgação pública para desenvolver ataques para alvos que não corrigiram seus aplicativos. Portanto, quando você recebe um aviso de que um pacote que seu projeto está usando tem uma vulnerabilidade conhecida, você deve agir rapidamente.

Gráfico de dependência do NuGet

📦 Pacote do Consumidor

Você pode exibir suas dependências do NuGet em seu projeto examinando diretamente o respetivo arquivo de projeto.

Isso normalmente é encontrado em um dos dois lugares:

Dependendo do método usado para gerenciar suas dependências do NuGet, você também pode usar o Visual Studio para exibir suas dependências diretamente no Gerenciador de Soluções ou no Gerenciador de Pacotes NuGet.

Para ambientes CLI, você pode usar o dotnet list package comando para listar as dependências do seu projeto ou solução. Você também pode usar o dotnet nuget why comando para entender por que pacotes transitivos (aqueles não referenciados diretamente pelo seu projeto) estão sendo incluídos no gráfico de pacotes do seu projeto.

Para obter mais informações sobre como gerenciar dependências do NuGet, consulte a documentação a seguir.

Gráfico de dependência do GitHub

📦 Consumidor de Pacotes | 📦🖊 Autor do pacote

Você pode usar o gráfico de dependência do GitHub para ver os pacotes dos quais seu projeto depende e os repositórios que dependem dele. Isso pode ajudá-lo a ver quaisquer vulnerabilidades detetadas em suas dependências.

Para obter mais informações sobre as dependências do repositório GitHub, consulte a documentação a seguir.

Versões de dependência

📦 Consumidor de Pacotes | 📦🖊 Autor do pacote

Para garantir uma cadeia de suprimentos segura de dependências, convém garantir que todas as suas dependências e ferramentas sejam atualizadas regularmente para a versão estável mais recente, pois geralmente incluirão as funcionalidades e patches de segurança mais recentes para vulnerabilidades conhecidas. Suas dependências podem incluir código do qual você depende, binários que você consome, ferramentas que você usa e outros componentes. Isto pode incluir:

Gerencie suas dependências

Dependências obsoletas e vulneráveis do NuGet

📦 Consumidor de Pacotes | 📦🖊 Autor do pacote

Você pode usar a CLI dotnet para listar quaisquer dependências conhecidas, obsoletas ou vulneráveis que você possa ter dentro de seu projeto ou solução. Você pode usar o comando dotnet list package --deprecated ou dotnet list package --vulnerable para fornecer uma lista de quaisquer desativações ou vulnerabilidades conhecidas. O NuGetAudit pode avisá-lo sobre dependências vulneráveis conhecidas e é habilitado por padrão quando uma fonte fornece um banco de dados de vulnerabilidades.

Dependências vulneráveis do GitHub

📦 Consumidor de Pacotes | 📦🖊 Autor do pacote

Se seu projeto estiver hospedado no GitHub, você poderá aproveitar a Segurança do GitHub para encontrar vulnerabilidades e erros de segurança em seu projeto e o Dependabot os corrigirá abrindo uma solicitação pull em sua base de código.

Capturar dependências vulneráveis antes que elas sejam introduzidas é um dos objetivos do movimento "Shift Left". Ser capaz de ter informações sobre suas dependências, como sua licença, dependências transitivas e a idade das dependências ajuda você a fazer exatamente isso.

Para obter mais informações sobre alertas Dependabot e atualizações de segurança, consulte a documentação a seguir.

Configuração do NuGet

📦 Consumidor de Pacote

Adicione um nuget.config arquivo na raiz do repositório do projeto. Isso é considerado uma prática recomendada, pois promove a repetibilidade e garante que diferentes usuários tenham a mesma configuração do NuGet. Recomendamos adicionar clear elementos para garantir que nenhuma configuração específica do usuário ou da máquina seja aplicada. Leia mais sobre como as configurações são aplicadas.

Por exemplo:

<configuration>
  <packageSources>
    <clear />
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
  <packageSourceMapping>
    <clear />
  </packageSourceMapping>
</configuration>

Feeds NuGet

📦 Pacote para Consumidor

Utilize repositórios de pacotes em que confia. Ao usar vários feeds de origem NuGet públicos ou privados, um pacote pode ser baixado de qualquer um dos feeds. Para garantir que a sua compilação seja previsível e segura contra ataques conhecidos, como a Confusão de Dependência, saber de que feeds específicos os seus pacotes estão a vir é um procedimento recomendado. Você pode usar um único feed ou um feed privado com capacidades de upstreaming para proteção.

Para obter mais informações para proteger seus feeds de pacotes, consulte 3 maneiras de reduzir o risco ao usar feeds de pacotes privados.

Ao usar um feed privado, consulte as práticas recomendadas de segurança para gerenciar credenciais.

Políticas de confiança do cliente

📦 Utilizador de Pacotes

Há políticas nas quais você pode optar por participar nas quais você exige que os pacotes que você usa sejam assinados. Isso permite que você confie em um autor de pacote, desde que ele seja assinado pelo autor, ou confie em um pacote se ele for de propriedade de um usuário específico ou conta que seja um repositório assinado por NuGet.org.

Para configurar políticas de confiança do cliente, consulte a documentação a seguir.

Bloquear ficheiros

📦 Consumidor de Pacotes

Os arquivos de bloqueio armazenam o hash do conteúdo do seu pacote. Se o hash de conteúdo de um pacote que você deseja instalar corresponder ao arquivo de bloqueio, ele garantirá a repetibilidade do pacote.

Para habilitar arquivos de bloqueio, consulte a documentação a seguir.

Mapeamento de origem do pacote

📦 Consumidor de Pacotes

O Mapeamento de Origem do Pacote permite que você declare centralmente qual fonte cada pacote em sua solução deve restaurar em seu arquivo nuget.config.

Para habilitar o mapeamento de origem do pacote, consulte a documentação a seguir.

Computadores seguros

Permissões de diretório

📦 Consumidor de Pacote

No Windows e Mac, e em algumas distribuições Linux, os diretórios iniciais da conta de usuário são privados por padrão. No entanto, algumas distribuições Linux tornam os diretórios de usuários legíveis por outras contas no mesmo computador por padrão. Além disso, há várias opções de configuração para redirecionar a pasta de pacotes globais do NuGet e o cache HTTP para locais não padrão. Soluções, projetos e repositórios também podem ser criados fora do diretório base do usuário.

Se você usar quaisquer pacotes que não estejam no nuget.org, se qualquer outra conta no computador puder ler os pacotes globais ou diretórios de cache HTTP do NuGet, ou o diretório de saída de compilação do projeto, esses pacotes poderão ser divulgados para pessoas que não devem ter acesso a esses pacotes.

No Linux, dotnet nuget update source alterará nuget.config permissões de arquivo para torná-lo legível apenas pelo proprietário do arquivo. No entanto, se você editar o arquivo denuget.config de qualquer outra forma e o arquivo estiver em um local em que outras contas possam ler o arquivo, pode haver divulgação de informações sobre a URL de origem do pacote ou as credenciais de origem do pacote. Você deve garantir que qualquer arquivo nuget.config não possa ser lido por outros usuários do mesmo computador.

Soluções dentro do diretório de downloads

📦 Consumidor de Pacotes

Cuidado extra deve ser tomado se estiver trabalhando em soluções ou projetos em seu diretório de downloads. O NuGet acumulará configurações de vários arquivos de configuração, e o MSBuild normalmente importará Directory.Build.props, Directory.NuGet.props, Directory.Build.targets e potencialmente outros arquivos, de qualquer diretório pai, até a raiz do sistema de arquivos.

A pasta de downloads tem um risco adicional, uma vez que geralmente é o local padrão em que os navegadores da Web baixam arquivos da internet

Agentes de construção

📦 Consumidor de Pacotes

Os agentes de compilação (agentes de CI) que não são redefinidos para um estado inicial após cada compilação têm vários riscos que devem ser considerados.

Para saber mais sobre maneiras seguras de gerenciar credenciais, consulte os documentos sobre como consumir pacotes de feeds autenticados.

Para saber mais sobre como modificar os diretórios nos quais o NuGet armazena dados, consulte os documentos sobre como gerenciar os pacotes globais, o cache e as pastas temporárias. Esses diretórios devem ser configurados para um diretório que o agente de CI limpa após cada compilação.

Observe que todos os pacotes usados pelo seu projeto podem ser deixados no diretório de saída de compilação do seu projeto. Se seu projeto usa pacotes de fontes autenticadas, outros usuários do mesmo agente de CI podem obter acesso não autorizado aos assemblies de pacote. Portanto, você também deve limpar seu repositório no final da compilação, mesmo quando a compilação falhar ou for cancelada.

Monitorize a sua cadeia de abastecimento

Verificação secreta do GitHub

📦🖊 Autor do pacote

O GitHub verifica os repositórios em busca de chaves de API do NuGet para evitar usos fraudulentos de segredos que foram cometidos acidentalmente.

Para saber mais sobre a varredura secreta, consulte Sobre a varredura secreta.

Assinatura de Pacotes de Autor

📦🖊 Autor do pacote

A assinatura do autor permite que o autor de um pacote carimbe sua identidade em um pacote e que um consumidor verifique se ele veio de você. Isso protege você contra adulteração de conteúdo e serve como uma única fonte de verdade sobre a origem do pacote e a autenticidade do pacote. Quando combinado com políticas de confiança do cliente, você pode verificar se um pacote veio de um autor específico.

Para assinar um pacote, consulte Assinar um pacote.

Compilações reprodutíveis

📦🖊 Autor do pacote

As compilações reprodutíveis criam binários que são idênticos byte por byte cada vez que você o cria e contêm links de código-fonte e metadados do compilador que permitem que um consumidor de pacote recrie o binário diretamente e valide que o ambiente de compilação não foi comprometido.

Para saber mais sobre compilações reproduzíveis, consulte Produzindo pacotes com link de origem e a especificação de validação de compilação reproduzível .

Autenticação (2FA) Two-Factor

📦🖊 Autor do pacote

Todas as contas no nuget.org têm 2FA habilitado. Isso adiciona uma camada extra de segurança ao fazer login na sua conta do GitHub ou na sua conta NuGet.org.

Reserva de prefixo de ID do pacote

📦🖊 Autor do pacote

Para proteger a identidade de seus pacotes, você pode reservar um prefixo de ID de pacote com seu respetivo namespace para associar um proprietário correspondente se o prefixo de ID do pacote se enquadrar corretamente nos critérios especificados.

Para saber mais sobre como reservar prefixos de ID, consulte Reserva de prefixo de ID de pacote.

Substituir e cancelar a inclusão de um pacote vulnerável na lista

📦🖊 Autor do pacote

Para proteger o ecossistema de pacotes .NET quando você estiver ciente de uma vulnerabilidade em um pacote que você criou, faça o possível para remover e cancelar a lista do pacote para que ele fique oculto dos usuários que pesquisam pacotes. Se você estiver consumindo um pacote que está preterido e não listado, você deve evitar usar o pacote.

Para saber como obsoletar e remover da lista um pacote, consulte a documentação a seguir sobre obsoletar e remover pacotes da lista.

Considere também relatar a vulnerabilidade conhecida no GitHub Advisories Database.

Resumo

Sua cadeia de suprimentos de software é qualquer coisa que entra ou afeta seu código. Mesmo que os comprometimentos da cadeia de suprimentos sejam reais e estejam crescendo em popularidade, eles ainda são raros; Portanto, a coisa mais importante que você pode fazer é proteger sua cadeia de suprimentos, estando ciente de suas dependências, gerenciando suas dependências e monitorando sua cadeia de suprimentos.

Você aprendeu sobre vários métodos que o NuGet e o GitHub fornecem e que estão disponíveis para você hoje para ser mais eficaz na visualização, gerenciamento e monitoramento de sua cadeia de suprimentos.

Para obter mais informações sobre como proteger o software do mundo, consulte The State of the Octoverse 2020 Security Report.