Como identificar vulnerabilidades no código fonte?
Tags: webdev, appsec, security, devops
Published: 2023-11-21 15:34:52

Se você é um profissional ou estudante de Segurança de Aplicações, é provável que já tenha se deparado com esta pergunta: “_Como posso identificar vulnerabilidades no código fonte?_”. Embora pareça uma questão simples, a resposta pode variar bastante, e às vezes uma solução pode parecer mais completa que outra.

Com base na minha experiência na área e em referências importantes, elaborei este artigo para ajudá-lo a responder a essa pergunta com confiança.

Mas, antes de mergulharmos nesse assunto, vamos entender alguns conceitos básicos.

## O que é vulnerabilidade?
Segundo o artigo “[Risk Management Framework for Information Systems and Organizations: A System Life Cycle Approach for Security and Privacy”](https://csrc.nist.gov/pubs/sp/800/37/r2/final) do NIST (National Institute of Standards and Technology), vulnerabilidades são pontos fracos que podem permitir que uma fonte de ameaça cause danos a um sistema de informação ou aos dados nele armazenados. 

Esses pontos fracos, ou brechas, podem ser causados por falhas no design da aplicação, problemas no código, na configuração, nos procedimentos ou nas medidas de segurança do sistema.

Para isso, a identificação de vulnerabilidades é o primeiro passo no processo conhecido como gestão de vulnerabilidades.

## É crucial entender a gestão de vulnerabilidades antes de qualquer coisa
Segundo o NIST, o gerenciamento de vulnerabilidades é definido como a atividade de identificar, avaliar, tratar e reduzir as vulnerabilidades que poderiam ser exploradas ou acionadas por uma fonte de ameaça.

Além desse conceito, a própria [Microsoft](https://www.microsoft.com/en-us/security/business/security-101/what-is-vulnerability-management) traz também em seus documentos uma outra abordagem para essa proposta, traduzido na seguinte definição:

> “O gerenciamento de vulnerabilidades é **uma abordagem baseada em risco** para descobrir, priorizar e remediar vulnerabilidades e configurações incorretas.”

**Um aspecto frequentemente negligenciado na identificação de vulnerabilidades é o risco associado**. Afinal, o objetivo do gerenciamento de vulnerabilidades é minimizar o risco para a organização, mitigando o máximo de vulnerabilidades possível.

Então, antes de iniciar o processo de  identificação de vulnerabilidades, é crucial avaliar o risco de cada aplicação do negócio. Essa avaliação pode ajudar a priorizar quais vulnerabilidades precisam de atenção imediata.

Isso destaca a importância de uma organização utilizar **práticas de gestão de riscos** para orientar seu programa de vulnerabilidades. Mas como fazer isso? Cada organização acaba personalizando seus critérios com base em regras de negócio ou questões técnicas específicas.  

Um framework interessante para conduzir a gestão de riscos dos ativos é o [ISO 31000](https://www.controladoria.go.gov.br/pcm/assets/files/material-logo-2022/trilha6/comp/A%C3%A7%C3%A3o%2016%20-%20ABNT-NBR-ISO-31000-2018.pdf), que oferece um conjunto de princípios, diretrizes e processos.

Antes de iniciar o processo de identificação de vulnerabilidades, é importante avaliar o risco de todos os ativos digitais do negócio. Além disso, existem mandatos de _Compliance_ que obrigam a organização a agir em relação a alguns sistemas em específico. Ter esse conhecimento pode ajudar a priorizar as aplicações que precisam de atenção especial.

## Deixando tudo pronto para a identificação de vulnerabilidades
Com a gestão de riscos de ativos bem definida, é crucial que algumas questões sejam esclarecidas e estabelecidas antes de iniciar a identificação de vulnerabilidades. Isso garantirá que as vulnerabilidades sejam identificadas e tratadas de maneira consistente.

Aqui estão algumas perguntas que você precisa ter em mente:

- Quem é responsável por identificar e corrigir as vulnerabilidades? É importante definir claramente as responsabilidades e os papéis.
- Quais ferramentas e técnicas serão utilizadas para identificar as vulnerabilidades? A escolha das ferramentas e técnicas adequadas é crucial.
- Quando as vulnerabilidades serão identificadas e corrigidas? É necessário estabelecer um cronograma.
- Quais serão os canais de comunicação entre os responsáveis? Como os resultados serão comunicados aos responsáveis? É importante definir um fluxo de comunicação eficaz.
- Como o processo será medido e aprimorado?

Com o escopo, a estratégia, as condições e o ambiente bem definidos, estamos prontos para a execução.

## Identificando vulnerabilidades: quanto mais cedo, melhor 
A melhor estratégia para identificar vulnerabilidades no código fonte é integrá-las ao processo de desenvolvimento. Isso permite que as falhas sejam detectadas mais cedo, quando são mais fáceis de corrigir.


### Análises automatizadas
Como estamos focando na etapa de construção de código, logo, vamos entender que no instante de realizar a codificação já é possível começar com uma identificação direta no ambiente do desenvolvedor a partir de ferramentas do tipo SAST (Static Application Security Testing).

Implementar [revisões automáticas de teste de segurança no ambiente de desenvolvimento integrado (IDE)](https://semgrep.dev/blog/2023/semgrep-vscode-extension/) pode ajudar os desenvolvedores a identificar vulnerabilidades mais cedo. Isso pode economizar tempo se os desenvolvedores também realizarem treinamentos em codificação segura.

O SAST também pode ser implementado na pipeline de desenvolvimento, juntamente com o SCA (Software Composition Analysis), para avaliar bibliotecas e pacotes de terceiros. Isso ajuda a garantir que todas as vulnerabilidades sejam identificadas antes que o código seja integrado à branch principal.

Existem outras ferramentas de segurança que também podem ser integradas à pipeline de desenvolvimento. No entanto, é importante entender as limitações das ferramentas de análise estática, pois elas não detectam todas as vulnerabilidades, especialmente as mais complexas.

### Análises manuais
Temos, por outro lado, a análise manual do código, o famoso Code Review tão comum ao universo de quem desenvolve aplicações. Nesse caso, é importante que os revisores estejam familiarizados com os tipos de vulnerabilidades mais comuns - [como o OWASP TOP 10](https://owasp.org/Top10/) -  e com as técnicas para identificá-las. 

Normalmente, essa tarefa é realizada por profissionais de AppSec ou desenvolvedores com conhecimento em segurança.

É importante destacar que, conforme o Guia de Code Review da OWASP, o [Code Review](https://owasp.org/www-pdf-archive/OWASP_Code_Review_Guide_v2.pdf) é um um processo crucial no ciclo de desenvolvimento seguro, sendo uma das melhores maneiras de identificar vulnerabilidades. 

Para realizar a análise manual do código, abordei um pouco do assunto [neste artigo](https://blog.convisoappsec.com/dicas-de-como-resolver-desafios-de-seguranca-em-ruby-on-rails-para-desenvolvedores/). Ele pode ajudar a construir a mentalidade necessária para a revisão de código manual, já que este é um tema complexo que exige um conhecimento profundo em arquitetura e lógica de programação.

## Identificando vulnerabilidades em execução
Com a aplicação em execução, podemos realizar uma análise mais ampla e prática da superfície de ataque. A superfície de ataque, segundo a [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/Attack_Surface_Analysis_Cheat_Sheet.html), descreve todos os pontos onde um invasor pode entrar em um sistema e obter dados.

Com isso em mente, podemos realizar testes de forma experimental, ou seja, de maneira dinâmica.

### Análises dinâmicas
As análises dinâmicas testam a segurança de uma aplicação em execução. Elas podem ser realizadas por ferramentas automatizadas, conhecidas como DAST (Dynamic Application Security Testing), que simulam ataques reais contra o software.

A vantagem desse tipo de análise é que ela cobre uma grande parte da superfície de ataque da aplicação, detectando problemas que só aparecem em cenários específicos e fornecendo evidências concretas dos riscos de segurança. No entanto, como qualquer ferramenta de segurança, o DAST tem suas limitações e pode não detectar todas as vulnerabilidades existentes.

De tal maneira, é recomendado utilizar uma abordagem integrada de teste de segurança, que combine as diferentes técnicas e ferramentas disponíveis.

Se você quiser saber mais sobre as ferramentas de segurança para automatizar em seu fluxo DevOps, recomendo [este guia da OWASP](https://owasp.org/www-project-web-security-testing-guide/).

### Penetration testing (testes de penetração)
Outra atividade fundamental para a identificação de vulnerabilidades é a realização dos testes manuais do tipo pentesting, também denominados como teste de intrusão ou teste de invasão.

O pentesting é conduzido por profissionais especializados em segurança, usando ferramentas e técnicas específicas. Além disso, existem diferentes abordagens para o pentesting, conhecidas como gray, white e black box:

- **Gray Box**: Neste tipo de teste, os pentesters têm algum conhecimento e acesso ao sistema. Isso permite uma abordagem mais focada, pois os testadores têm uma ideia de onde as vulnerabilidades podem estar.

- **White Box**: Aqui, os pentesters têm acesso total ao código fonte e ao sistema. Isso permite uma análise mais profunda e detalhada, mas também é mais demorado.

- **Black Box**: Neste cenário, os pentesters não têm nenhum conhecimento prévio do sistema. Isso simula um ataque realista de um invasor externo.


Em suma, o processo envolve uma análise ativa da aplicação, simulando ataques reais, em busca de quaisquer vulnerabilidades, falhas técnicas ou fraquezas, tanto conhecidas quanto desconhecidas.

Vale destacar que, diferentemente dos outros métodos, o pentesting pode revelar as vulnerabilidades mais críticas e prioritárias de um sistema, permitindo que sejam corrigidas antes que sejam exploradas por agentes maliciosos. Por outro lado, o pentesting pode criar uma falsa sensação de segurança, se não for feito de forma regular, abrangente e consistente com as demais práticas de identificação de vulnerabilidades.

Existem vários frameworks disponíveis para ajudar a conduzir testes de penetração de maneira eficaz. Um exemplo é o [Penetration Testing Execution Standard (PTES)](http://www.pentest-standard.org/index.php/Main_Page), que fornece um conjunto de diretrizes para realizar testes de penetração. 


## Identificar vulnerabilidades requer uma mentalidade proativa e criativa

A criação de uma **política de gestão de vulnerabilidades bem documentada** é um passo inicial importante. Esta política deve consolidar as políticas e o escopo do processo, definir papéis e responsabilidades, objetivos do processo, postura de gestão de riscos, tecnologias e ambientes envolvidos, além de quaisquer requisitos adicionais de regulamentação ou conformidade. Isso fornece uma estrutura para o gerenciamento eficaz das vulnerabilidades, incluindo considerações de conformidade.

**Automatizar o processo de identificação de vulnerabilidades** é outro passo crucial para garantir uma avaliação consistente e periódica de todas as aplicações do negócio. Mas isso é apenas o começo. **Treinar os desenvolvedores em codificação segura** também é essencial para minimizar a introdução de vulnerabilidades no código desde o início e introduzir uma cultura de segurança no processo.

Portanto, à medida que novas vulnerabilidades são descobertas, é essencial manter nossas ferramentas e técnicas atualizadas. Isso requer uma mentalidade proativa e criativa, sempre buscando aprender e inovar. 

Nesse sentido, o **monitoramento de logs** pode ser um método para identificar vulnerabilidades, fornecendo insights valiosos sobre atividades suspeitas que podem indicar a presença de uma vulnerabilidade. Além disso, a **modelagem de ameaças**, quando aplicada a uma aplicação já desenvolvida, pode ser uma estratégia interessante para identificar potenciais vulnerabilidades e entender melhor o panorama de ameaças. 
Diferentes práticas, quando combinadas, podem fortalecer significativamente a postura de segurança de uma organização.

**Me diz agora: você acha que faltou alguma atividade ou algo importante no texto? Estou ansioso para ler seu comentário. **