Impedindo pacotes maliciosos antes de chegarem à produção
Um programador pode introduzir código malicioso num projeto sem escrever uma única linha suspeita. Instalar um pacote pode ser suficiente. A dependência pode parecer legítima, ter um nome familiar e, ainda assim, executar código indesejado durante a instalação.
Isto faz com que a segurança dos pacotes seja um problema muito antes de uma aplicação chegar à produção. A primeira ação arriscada pode acontecer numa estação de trabalho Windows de um programador, dentro de um executor de CI ou durante uma compilação automatizada. Os controlos colocados apenas perto da implementação deixam grande parte desse caminho exposta.
O risco começa na máquina do programador
Os projetos modernos incluem grandes árvores de dependências. Um programador pode instalar deliberadamente dez pacotes enquanto o gestor de pacotes obtém centenas de dependências transitivas em segundo plano. Poucas pessoas inspecionam todos os pacotes dessa cadeia, e fazê-lo manualmente tornaria o desenvolvimento normal dolorosamente lento.
Os atacantes exploram essa confiança. Alguns pacotes maliciosos tentam roubar variáveis de ambiente, credenciais, dados do navegador ou tokens de autenticação. Outros transferem outra carga útil ou executam código através de scripts de instalação antes de o programador chegar a abrir o pacote.
No Windows, o ambiente afetado pode incluir sessões do PowerShell, credenciais do gestor de pacotes, chaves SSH, ferramentas da cloud e ficheiros disponíveis para a conta de utilizador atual. O WSL acrescenta outro ambiente de desenvolvimento à mesma máquina, em vez de eliminar o risco subjacente da cadeia de fornecimento.
Uma dependência maliciosa nem sempre parece maliciosa
Os ataques através de pacotes são mais difíceis de detetar quando o componente malicioso se assemelha àquilo que os programadores já esperam ver. Os pontos de entrada variam:
- Typosquatting: Um pacote utiliza um nome que difere de uma dependência popular por um ou dois carateres;
- Confusão de dependências: Um pacote público colide com uma dependência interna e pode ser selecionado por uma compilação automatizada;
- Contas de mantenedores comprometidas: Um pacote de confiança recebe uma versão maliciosa depois de um atacante obter acesso de publicação;
- Atualizações maliciosas: Um projeto anteriormente inofensivo altera o comportamento numa versão posterior;
- Dependências transitivas ocultas: Código perigoso entra vários níveis abaixo do pacote que um programador selecionou.
A popularidade não é uma garantia de segurança. Um projeto comprometido pode herdar anos de reputação de versões limpas anteriores, enquanto um novo pacote malicioso pode acumular transferências antes de o comportamento suspeito ser detetado.
Analisar mais tarde pode ser tarde demais
Muitas equipas já analisam as dependências e essas verificações continuam a ser importantes. A análise de composição de software pode identificar vulnerabilidades conhecidas. Os analisadores de repositórios podem assinalar segredos expostos ou código arriscado. As verificações de segurança de CI podem impedir que uma compilação problemática seja implementada.
O momento altera o que esses controlos podem impedir.
Se um programador executar um comando de instalação no Windows Terminal e o pacote pedido contiver um script de instalação malicioso, o código pode ser executado localmente antes de ocorrer a primeira verificação séria de CI. Um ambiente de produção limpo não anula o roubo de credenciais na máquina onde a compilação começou.
A análise de vulnerabilidades conhecidas também responde a uma questão diferente. É eficaz a encontrar versões associadas a problemas de segurança conhecidos, mas um pacote malicioso recém-publicado pode ainda não ter uma CVE nem um registo de vulnerabilidade estabelecido.
Verificar os pacotes antes de serem autorizados a entrar
Uma abordagem consiste em colocar um controlo entre o programador ou o sistema de compilação e o registo de pacotes. Em vez de permitir que todos os pacotes solicitados entrem diretamente no ambiente, o controlo avalia-o primeiro e pode bloquear software que cumpra critérios suspeitos.
Esta é a ideia básica por trás de um firewall de dependências.
A parte útil é onde a decisão acontece. Um pacote pode ser avaliado antes da instalação em vez de ser descoberto como um problema depois de já ter entrado no ambiente. Os sinais podem incluir padrões de publicação suspeitos, pacotes recém-criados que imitam pacotes estabelecidos ou outros comportamentos que merecem uma análise mais aprofundada.
Isso não torna o controlo infalível. Os falsos positivos também são importantes. Os pacotes recém-lançados podem ser legítimos e a atividade de publicação invulgar não é automaticamente maliciosa. Se as verificações de pacotes interromperem constantemente as atualizações legítimas, os programadores podem começar a procurar formas de as contornar.
O desenvolvimento no Windows acrescenta a sua própria exposição
As configurações de desenvolvimento no Windows combinam frequentemente Git, Node.js, Python, PowerShell, Visual Studio Code, Docker Desktop, WSL, CLIs da cloud e credenciais armazenadas localmente numa única estação de trabalho. Isso torna as permissões das contas e a segurança local relevantes para o risco dos pacotes.
Algumas escolhas comuns reduzem a superfície de ataque disponível:
- Mantenha o desenvolvimento de rotina em contas sem privilégios de administrador sempre que possível;
- Evite executar comandos de instalação desconhecidos com privilégios elevados do PowerShell;
- Separe as credenciais de produção das credenciais locais do programador;
- Reveja os pacotes que introduzem subitamente scripts de instalação ou pós-instalação;
- Utilize ambientes isolados para software que ainda não conquistou confiança.
As funcionalidades de segurança do Windows podem ajudar ao nível do sistema operativo, mas não conseguem decidir se todos os pacotes de terceiros numa árvore de dependências pertencem a um determinado projeto.
Os lockfiles ajudam, mas não conseguem decidir o que é seguro
Os lockfiles tornam as versões dos pacotes mais previsíveis e reduzem alterações inesperadas entre instalações. Não determinam se a própria versão fixada é maliciosa.
A mesma limitação aplica-se a outros controlos quando são utilizados isoladamente. A fixação de versões proporciona consistência. A revisão de código deteta alterações que os programadores conseguem realmente ver. A análise de vulnerabilidades encontra pontos fracos conhecidos. A proteção de pontos finais monitoriza a atividade na máquina.
As equipas também podem exigir MFA para publicar pacotes internos, remover dependências abandonadas, monitorizar alterações nos lockfiles, restringir scripts de instalação desnecessários e investigar alterações súbitas de propriedade em projetos críticos de terceiros.
A abordagem mais robusta é em camadas. Nenhum controlo individual cobre todo o caminho desde o registo de pacotes até à máquina do programador, ao sistema de compilação e ao ambiente de produção.
Pare o pacote no primeiro ponto útil
A segurança de produção começa antes da produção. Quando uma dependência maliciosa aparece numa compilação implementada, pode já ter passado por portáteis de programadores, caches de pacotes, sistemas de compilação e infraestruturas de CI.
Aproximar as verificações de pacotes da instalação reduz essa janela sem eliminar a necessidade de análises posteriores. Para as equipas baseadas em Windows, proteger a estação de trabalho é importante porque as máquinas de desenvolvimento estão frequentemente próximas do código-fonte, das credenciais, das ferramentas da cloud e dos sistemas internos.
A questão prática não é se uma ferramenta consegue garantir que todos os pacotes são seguros. É saber quão cedo o processo de desenvolvimento pode rejeitar um pacote que nunca deveria ter sido autorizado a ser executado.
Leia a nossa página de divulgação para descobrir como pode ajudar o Windows Report a sustentar a equipe editorial. Read more
User forum
0 messages