Rodando o Brakeman neste repositório

Prévia grátis 6 min de leitura

O curso anterior terminou com uma auditoria e uma lista de coisas que uma pessoa precisa procurar. O Brakeman é a parte dessa lista que um programa consegue fazer: ele lê o seu código Rails, segue dados da entrada até chamadas perigosas, e reporta o que encontra.

Ele já rodou neste repositório. O relatório abaixo é o que bin/brakeman --no-pager produziu no dia em que este curso foi escrito, antes das correções das aulas 2, 3 e 7. Rode o mesmo comando neste repositório hoje e ele reporta zero avisos; os seis abaixo ficam porque triar um relatório real é o objetivo inteiro, e este é real.

bin/brakeman --no-pager
== Brakeman Report ==

Rails Version: 8.1.3.1
Brakeman Version: 8.0.4
Checks Run: BasicAuth, ..., SQL, ..., ValidationRegex, ... (79 checks)

== Overview ==

Controllers: 46
Models: 28
Templates: 82
Errors: 0
Security Warnings: 6

== Warning Types ==

Format Validation: 3
SQL Injection: 3

Seis avisos, em cerca de um segundo, sobre cento e cinquenta arquivos. As aulas 2 e 3 percorrem cada um, e no fim deste curso você vai saber quais eram reais, e pode confirmar você mesmo que o mesmo comando reporta zero hoje.

Esse é o formato inteiro de usar a ferramenta: ela produz uma lista, e o valor vem do que você faz com cada entrada.

O que ele é

O Brakeman é um analisador estático: ele lê código sem executá-lo. É isso que o torna rápido e o que determina tudo que ele consegue e não consegue fazer.

Porque ele não executa o código Consequência
Não precisa de banco, servidor nem dados de teste Roda em um segundo, em todo pull request
Enxerga todo desvio, inclusive os que os testes nunca alcançam Acha bugs que uma suíte passando esconde
Não consegue saber valores em tempo de execução Reporta o que pode ser entrada de fora, não o que é

Essa última linha é a origem de todo falso positivo que você vai ver dele, e a razão de a ferramenta reportar um nível de confiança em vez de um veredito.

flowchart LR
  S["Seu código"] --> P["Parse para uma árvore sintática"]
  P --> T["Rastreia o fluxo: params, cookies, atributos de model"]
  T --> C["79 checagens: dado não confiável chega a uma chamada perigosa?"]
  C --> W["Avisos, com um nível de confiança"]
  W --> H["Uma pessoa decide: real ou não?"]

Como ele decide que algo é perigoso

O Brakeman segue duas coisas e procura pelo encontro delas.

Fontes de dado não confiável: params, cookies, valores de request, e atributos de model definidos a partir de qualquer um desses. Ele propaga por atribuições e chamadas de método, e é por isso que consegue sinalizar um valor a três métodos de distância do controller que o recebeu.

Destinos perigosos: fragmentos de string SQL, render inline:, send, eval, system, redirect_to, raw e html_safe, constantize, File.read. Cada destino tem uma checagem que sabe como é o uso seguro dele.

Um aviso é um caminho de uma fonte a um destino que o Brakeman não conseguiu provar seguro. A formulação importa (não conseguiu provar seguro, não é inseguro) e é o jeito correto de ler o relatório inteiro.

Confiança

Nível O que costuma significar
High O padrão é inequívoco: uma construção sabidamente ruim
Medium Entrada de fora provavelmente chega ali, e a ferramenta não tem certeza
Weak Um padrão que vale olhar, muitas vezes tudo bem

Os seis avisos originais deste repositório eram três High e três Medium, e essa divisão já era informativa: os High são um padrão definido numa validação, e os Medium são um objeto de consulta fazendo algo que o Brakeman não consegue seguir. Confianças diferentes, tipos de trabalho diferentes.

Um aviso de confiança alta não é automaticamente uma vulnerabilidade real, e um fraco não é automaticamente ruído. A confiança descreve o quanto a ferramenta tem certeza sobre o padrão, não o quanto o resultado é explorável. Essa distinção é o assunto da aula 4.

O que ele não consegue achar

Vale dizer cedo, porque uma ferramenta que roda na CI convida à crença de que ela é a revisão de segurança:

  • Autorização faltando. Todo o A01 do curso anterior. Uma checagem faltando é código que não foi escrito, e não há o que analisar.
  • Falhas de regra de negócio. Um desconto que pode ser aplicado duas vezes é um bug nas suas regras, e o Brakeman não faz ideia de quais são.
  • Dependências vulneráveis. Isso é o bundle audit; o Brakeman analisa o seu código.
  • Qualquer coisa em tempo de execução. Configuração em produção, uma porta aberta, uma chave vazada.

O Brakeman é uma checagem de uma classe específica de erro (dado não confiável chegando a uma chamada perigosa) e ele é bom nessa classe. Tratá-lo como cobertura de tudo é como um time ganha um selo verde de CI e uma aplicação não auditada.

O que este curso cobre

  1. Rodando o Brakeman neste repositório (esta aula).
  2. Os três avisos de validação de formato.
  3. Os três avisos de injeção de SQL.
  4. Confiança e triagem.
  5. Convivendo com ele: CI, linhas de base e arquivos de exclusão.
  6. Além do Brakeman.
  7. Juntando tudo: um fluxo de segurança.

Pontos-chave

  • bin/brakeman --no-pager rodou 79 checagens sobre este repositório em cerca de um segundo e reportou 6 avisos quando este curso foi escrito; o mesmo comando reporta zero hoje, depois das correções das aulas 2, 3 e 7.
  • Análise estática lê código sem executá-lo: rápida, completa entre desvios, e incapaz de saber valores em execução.
  • Um aviso é um caminho de uma fonte não confiável a um destino perigoso que não pôde ser provado seguro.
  • A confiança descreve certeza sobre o padrão, não explorabilidade.
  • Ele não acha autorização faltando, falhas de regra de negócio, gems vulneráveis, nem nada sobre produção.
Aula 1 de 7 · grátis

Continue com a aula 2

Os avisos de validação de formato

Mostra por que uma regex de URL sem \z aceita quebras de linha e centraliza a correção num objeto.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...