Lições da SolarWinds – Uma avaliação de bibliotecas de terceiros

On By Jacob Emmert-Aronson11 Min Read
Lessons from SolarWinds – Evaluating third-party libraries

A SolarWinds divulgou em dezembro de 2020 que seu produto Orion esteve na mira de um ataque de grande escala, que, em contrapartida, deu ao responsável pelo ataque um backdoor na infraestrutura de diversos clientes da empresa, incluindo, em especial, várias agências governamentais. O âmbito dessa violação trouxe uma atenção em especial às vulnerabilidades da cadeia de fornecimento e ao papel das dependências de terceiros na segurança de um sistema de software. Embora nenhuma dessas ameaças seja uma novidade, o controle complementar, resultado resultante dos eventos atuais, suscitou nas organizações um profundo desejo de melhorar suas postura dea segurança, evitando, assim,para evitar que serjam o próximo alvo. Como uma equipe de engenharia de software, sua interação mais habitual com a cadeia de fornecimento é inerente àestá na escolha de bibliotecas externas que possam ser incorporadas em seus aplicativos.

Uma biblioteca externa bem preservada pode trazer excelentes benefícios às iniciativas de desenvolvimento, economizando incontáveis horas do tempo dagastas pela engenharia ao permitir que você se concentreque o foco se dê nos principais diferenciadores do seu próprio produto ao invés de precisar reimplantar uma funcionalidade usual. Por outro lado, bibliotecas mal implementadas podem ser difíceis de serem usadas, trazem vulnerabilidades de segurança que ameaçam sua empresa e seus clientes ou, em casos extremos, podem até mesmo interferir nos trabalhos de partes independentes do seu serviço ou indeterminarprejudicar toda sua arquitetura. Confira um panorama de diversas das considerações que usei para avaliar bibliotecas quanto à solidez de suas práticas de engenharia e suas possíveis implicações de segurança. Essas abordagens servem como um ponto de partida, não uma ditame regra a ser estritamente seguidaseguido. Encontre uma abordagem que atenda às suas próprias necessidades. Embora não haja soluções definitivas nessa área, garantir que seu projeto esteja associado somente a dependências de extrema qualidade pode reduzir, de forma substancial, sua superfície de ataque e garantir uma expansão e manutenção mais simples do seu produto.

Âmbito da biblioteca

Essa consideração inicial é importante pois é ela quem determina até que ponto uma avaliação é necessária ou adequada. Qual o nível de funcionalidade que a biblioteca oferece? Qual a importância dessa funcionalidade ao funcionamentopara o bom desempenho do seu produto? Uma biblioteca simples com uma pequena pegada exige muito menos análise quando comparada a uma estrutura ampla que será rigorosamente integrada em seu próprio código. Além disso, alguns indicadores que poderiam representar importantes sinais de alerta de funcionalidade-chave, como atualizações esparsas, podem ser normais ou esperados para bibliotecas menores que buscam apenas realizar uma atividade extremamente restritiva.

Uma dúvida conexarelacionada refere-se a como você pretende fazer uso da biblioteca. DAs dependências de desenvolvimento (ex.: uma ferramenta de análise estática ou um componente de uma estrutura de teste unitário) apresentam um risco muito menor em comparação aàs dependências de tempo de execução. Apesar deEmbora as falhas em seu pipeline de versão possam atrasar um lançamento ou provocar problemas de curto prazo aos desenvolvedores, não há um impacto direto no usuário e, em geral, elas não representam um risco à segurança do aplicativo.

Histórico de manutenção

A forma mais rápida de entender a integridade geral de um projeto é analisar seu histórico de controle de origem. Quando foi o último lançamento? Com que frequência os lançamentos são publicados e qual o índice de comprometimentos ao repositório do código de origem? Eu gosto de projetos que são atualizados com frequência, pois me passam uma maior confiança de que a biblioteca continuará a ser mantida no futuro. Por outro lado, um projeto que se manteve inativo por um longo período pode apresentar bugs não corrigidos ou pode suscitar problemas de incompatibilidade com as novas versões de dependências usuais ou até mesmo com o próprio tempo de execução do idioma.

Além disso, é muito importante se atentar ao changelog da biblioteca. Às vezes, as mudanças introduzidas por cada lançamento são descritas na página de lançamentos. Outras vezes, o changelog representa um arquivo no topo do repositório do código de origem. A informação ainda não está prontamente disponível?Se essa informação não estiver disponível de imediato, Esse é significa um importante sinal de alerta. Eu busco por descrições claras sobre as mudanças de um lançamento para o outro, além de quaisquer retrocompatibilidades explicitamente documentadas.assegurar que quaisquer incompatibilidades anteriores sejam documentadas explicitamente. Uma elevada frequência, no entanto, de mudanças de retrocompatibilidade ou correções de bugs na funcionalidade principal é, por si só, um motivo de preocupação, uma vez que sugere que o desenvolvedor foi infeliz ao planejar e depurar mudanças anteriormente ao lançamento.

Relações com o administrador

Uma avaliação mais aprofundada pode abranger a análise do rastreador de problemas de um projeto e outros canais públicos de comunicação. Quão eficazes os administradores são com os usuários? Eles são receptivos e abertos ao feedback ou geralmente assumem um tom mais agressivo? Qual a proporção de questões abertas para encerradas? Os administradores estão constantemente solucionando problemas do usuário ou os relatórios de bugs ficam ociosos por um longo período de tempo? Quão extensa é a documentação e qual sua eficácia em direcionar o usuário às práticas recomendadas de implementação? Há evidências de uma comunidade dinâmica no projeto? O encargo, por exemplo, do suporte ao usuário é de total responsabilidade do administrador principal ou há outros membros da comunidade que queiram, e possam, assumir alguma responsabilidade? Um projeto que mantém uma relação saudável com sua comunidade tem uma probabilidade muito maior de atender às necessidades específicas dos usuários e se adaptar rapidamente a um ambiente de mudança.

Dependências transitivas

Essa avaliação exige um esforço um pouco maior do que simplesmente ponderar a frequência de lançamentos; no entanto, fornece uma imensidãoum verdadeiro acervo de informações. A primeira coisa que quero entender é de quantas outras dependências a biblioteca depende, principalmente se extrai dependências de forma desnecessária. As dependências que oferecem funcionalidade importante a uma biblioteca são muito menos preocupantes quando comparadas a de muitas outras bibliotecas para tarefas sem qualquer relação. Cada dependência adicional significa maior complexidade e risco à cadeia de fornecimento. Se estiver em dúvida, uma ferramenta simples de avaliação é instalar a biblioteca a um contêiner de dockerportuário e observar quantas bibliotecas extras são adicionadas durante o processo.

A maior preocupação nessa categoria refere-se a quão facilmente é possível atualizar as dependências enquanto à medida que novas vulnerabilidades são descobertas. Por essa razão, uma parte importante dessa avaliação é observar se uma dependência é restritiva (compatível apenas com uma versão específica de uma biblioteca) ou permissiva (compatível com várias versões). O primeiro tipoAs dependências restritivas representam o mais preocupanteuma grande preocupação, uma vez que podem dificultar as iniciativas de correção ou até mesmo forçar o downgrade das bibliotecas das quais dependemos para outra funcionalidade. Outro aspecto relevante se trata de quão atuais essas dependências transitivas são. Uma dependência de versão que especifica um lançamento feito há dois meses traz muito menos preocupação do que uma dependência de um lançamento feito há dois anos. Seguindo a mesma linha, o histórico de atualizações frequentes, as quais mantêm as dependências atualizadas, é um sinal de que o projeto é bem executado.

Dependências linguística transversal

Esteja principalmente atento aos pacotes gravados em uma linguagem com dependências adicionais em outra linguagem (ex.: bibliotecas Python com extensões compiladas em C). Se as dependências secundárias abrangeremenvolverem uma linguagem ou ambiente de programação com o qual não esteja muito habituado, será mais difícil avaliar sua qualidade geral. Além disso, diferentes linguagens têm, em geral, diferentes conversões de pacoteconvenções de embalagem, e os administradores de projetos multilinguísticos muitas vezes não estão bem familiarizados com as melhoresnão possuem geralmente um bom entendimento das práticas recomendadas para todas as linguagens de programação com as quais operam, dificultando ainda mais a correção e a atualização.

Bibliotecas criptográficas

É necessária uma consideração especial quanto às bibliotecas criptográficas, o que se deve à complexidade algorítmica envolvida e o alto impacto de possíveis vulnerabilidades no espaço. Avalie com especial cuidado essas bibliotecas e não se esqueça de se basear somente em bibliotecas exaustivamente revisadas com um longo histórico. Algumas opções seguras são OpenSSL para C e C++, BouncyCastle para Java e biblioteca criptográfica de PyCA para Python. Suas opções podem estar restritas aos requisitos de conformidade ou da política de segurança da sua empresa. Atente-se às vulnerabilidades já conhecidas nas bibliotecas criptográficas e mantenha-se atualizado quanto aos novos lançamentos. De todas as dependências de terceiros, estas apresentam o maior impacto na segurança.

Qualidade de documentação e código

Estsa e a próxima seção são avaliações que exigem bastante esforço; este nível de avaliação, no entanto, justifica-se por vezes em casos de risco mais elevado. Quando eu busco entender a qualidade geral do código do projeto, eu busco pelo código de origem que use a funcionalidade que eu já conheço mais a fundo e avalio a qualidade da gravação da pequena área da sua base de código. Às vezes, analisarei a qualidade da documentação do projeto, concentrando-me na legibilidade e habilidade do autor em comunicar, com eficiência, conceitos complexos. Em ambos os casos, a meta é determinar se os administradores demonstram elevada atenção aos detalhes ou se, pelo contrário, preferem seguir pelos atalhos. O que se espera aqui é que o nível de atenção demonstrada a uma parte do projeto seja, presumivelmente, uma representação de um todo.

Vejamos um exemplo concreto. Se eu tivesse optado por analisar o processamento de SSL de um projeto Python, eu poderia me deparar com o seguinte:

  • São usados parâmetros padrão de conexão SSL ou há uma tentativa de personalizá-los a configurações mais seguras?
  • Se houver personalização, quão sensíveis são as mudanças?
  • O usuário tem a opção de fazer outras personalizações?
  • Se sim, são reutilizados os objetos SSLContext da biblioteca padrão do Python ou perdem tempo criando algo que já existe?

Em uma avaliação como essa, eu procuro identificar princípios sólidos de concepção, reuso de expressões padrão e que o autor é capaz de prognosticar as possíveis necessidades do usuário e oferecer extensibilidade para atendê-las.

Controle da vulnerabilidade

Fiz uma lista para esse último ponto pois se trata, geralmente, de uma impressão que crio com o tempo e que pode não ser tão útil para uma avaliação inicial. Além disso, é extremamente dependente de até que ponto Também depende muito do quanto uma determinada biblioteca é usada e relevante em termos de segurança, o que pode ser um fator, no entanto, ao decidir entre continuar a usar uma biblioteca que já existe ou tentar migrar para uma substituição.

Simplificando, eu busco avaliar a receptividade do administrador do projeto para corrigir vulnerabilidades e qual a facilidade de se obter benefícios com tais correções em suas próprias implantações. Um projeto que está frequentemente sujeito a divulgações de vulnerabilidade é de certa forma preocupante, embora possa ser igualmente um fator de ampla relevância de uso e segurança ao invés de práticas de manutenção e qualidade geral de código. O que acontece após uma vulnerabilidade ser identificada é considerado uma métrica melhor. As correção são rapidamente incorporadas em novos lançamentos? Quão simples é para fazer upgradefazer atualizações assim que as versões corrigidas são lançadas? Se o projeto geralmente faz mudanças radicais, principalmente se violam regularmente a compatibilidade com versões anteriores, elas se adaptam às mudanças nas versões antigas? Se a biblioteca é parte de uma distribuição Linux, então a responsabilidade pelo back-port das correções é, em geral, dos administradores de distribuição e não do desenvolvedor original; as mesmas perguntas, no entanto, podem ser aplicadas a como o responsável pelo pacote administra a biblioteca (as distribuições geralmente fazem uma distinção entre pacotes principais com manutenção ativa e pacotes mais periféricos, que, normalmente, monitoram lançamentos upstream com o mínimo de mudanças aplicadas).

Quando uma biblioteca demonstra um claro histórico de má administração de vulnerabilidades ou opera de forma que dificulte o aproveitamento das correções de segurança, geralmente recomendarei que minha equipe migre para uma substituição.

Conclusão

Avaliar a qualidade geral de um projeto de software e sua comunidade contígua é uma habilidade fundamental que apenas se tornará cada vez mais relevante à medida que os projetos de software ganham mais interdependência. Além disso, é uma habilidade extremamente individual; geralmente, você conseguirá o maior desempenho ao analisar as decisões dos administrações de bibliotecas em sua área de domínio. O processo de avaliação torna-se um procedimento de definir um níel de confiança e dar passos para garantir que a confiança não seja perdida, o que se deve ao fato de a validação completa de cada detalhe de um potencial fornecedor ser uma tarefa ais difícil do que construir a funcionalidade por si só. Por fim, aprender a avaliar as dependências de terceiros é uma parte importante de se criar uma cultura de engenharia que assume a responsabilidade pela confiabilidade e segurança do seu produto.

Sobre o autor

Jacob Emmert-Aronson é gerente sênior da equipe da Mindmeld, parte da empresa de inteligência do Webex. Jacob é um reconhecido líder em segurança da informação, DevOps e manutenção de software, sendo especialista em entender como esses assuntos intersectam-se

Gostaria de integrarfazer parte da equipe da MindMeld? Envie um e-mail para mindmeld-jobs@cisco.com!

Inscreva-se no Webex

Acesse nossa página inicial ou entre em contato conosco para obter assistência direta.


Clique aqui para saber mais sobre as ofertas do Webex e para se inscrever para uma conta grátis. 

About The Author

Jacob Emmert-Aronson
Jacob Emmert-Aronson Senior Engineer Cisco
Jacob Emmert-Aronson is a senior engineer on the Mindmeld team, part of the Webex Intelligence organization.
Learn more

Topics


More like this