Koa.JS Invulnerability Analysis, também conhecido como Por que a indústria de segurança não entende de software?
Minha frustração é alta porque acabou de acontecer de novo. Se você leu minha análise anterior intitulada CVE-2022–29622: (In)vulnerability Analysis , pode suspeitar do que estou me referindo. Mesma história, vítima diferente. No entanto, as datas são importantes neste caso. Minha análise de invulnerabilidade anterior é de 2022, hoje vou analisar outra questão de 2018.
Você pode perguntar: “Por que você tem que lidar com algo de 2018?” Excelente pergunta! Porque habilitei recentemente o Dependency Track para extrair informações de vulnerabilidade do índice OSS da Sonatype.
Hoje, enquanto eu examinava o SCA para ver se tínhamos algum componente vulnerável e, se tivéssemos, priorize o trabalho de remediação. Me deparei com algo muito surpreendente. Koa.JS tem uma vulnerabilidade crítica?! Depois do meu habitual “#FFS, minha semana inteira precisa ser reorganizada.”, Eu fiquei tipo: “Respire fundo e veja do que se trata. Você se lembra do que aconteceu da última vez…”
E foi o que fiz. Antes de tudo, o título deixa claro que o “problema” foi encontrado em 2018. Agora, por que eu teria uma vulnerabilidade em uma biblioteca que ainda é mantida e continuo atualizando para a versão mais recente? Nesse ponto, a parte investigativa do meu cérebro entrou em ação.
O que sabemos/vemos neste momento?
- Supostamente havia uma vulnerabilidade em Koa em 2018 com uma gravidade crítica atribuída
- De acordo com o Sonatype OSS Index and Dependency Track, o problema me afeta em 2022 enquanto executo a versão mais recente do Koa
- Quais versões da biblioteca Koa.JS foram afetadas pela “vulnerabilidade”
- Se a “vulnerabilidade” estiver presente no Koa.JS mais recente
Análise de problemas
Vamos ver do que se trata/era a “vulnerabilidade”. Deixe-me vincular rapidamente o problema relacionado nº 1250 do GitHub aqui. Vou apenas copiar e colar o exemplo (PoC?) abaixo para que possamos analisá-lo.
const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
ctx.redirect("javascript:alert(1);")
});
app.listen(3000);
“Como desenvolvedor de um aplicativo ou serviço da web, posso redirecionar seu navegador para onde eu quiser se você visitar meu site.”
Isso é o que o código acima significa. No PoC acima, não há vetor de ataque apresentado para um ator mal-intencionado explorar nada.
Se você quisesse fornecer um “PoC” adequado para essa não vulnerabilidade (sim, acabei de dizer), ficaria assim:
const Koa = require('koa');
const app = new Koa();
// Try: http://localhost:3000/?vector=javascript:alert(1);
app.use(async ctx => {
ctx.redirect(ctx.request.query.vector);
});
app.listen(3000);
Falando sobre uma vulnerabilidade XSS, se o que eu inseri como o valor do vector
parâmetro for exibido no contexto HTML de forma insegura, o aplicativo que implementei seria vulnerável a Cross Site Scripting. (Mais sobre isso mais tarde)
Ampliando como a Sonatype apresentou isso e analisando um pouco mais:
“Redirecionamento aberto levando a script entre sites”? Em primeiro lugar, não houve redirecionamento aberto. Só é aberto se você abrir e a diferença entre os dois PoCs (o original e o meu) mostra isso claramente. No primeiro, não havia vetor de ataque, portanto, não havia redirecionamento aberto. Meu PoC tinha um vetor de ataque, sem filtragem, portanto, havia um redirecionamento aberto. Mas, como você pode ver, se havia ou não um redirecionamento aberto dependia de mim, do desenvolvedor, e não do Koa.JS. Melhor ainda, se houve redirecionamento ou não, também dependia de mim. Se eu incluí a entrada fornecida pelo usuário como/no URL de redirecionamento de maneira insegura, também dependia de mim. De qual vulnerabilidade do Koa.JS estamos falando então? Tecnicamente, não havia uma vulnerabilidade e alguém ainda atribuiu gravidade Crítica a ela. Não exatamente profissional.
De qualquer forma, vamos “explorar” a dita “vulnerabilidade” implementada pelo próprio PoC. Observe que tive que alterar a porta de serviço de 3000 para 4444, pois já havia algo escutando na porta 3000.
Podemos ver que o Location
cabeçalho de resposta tem o valor javascript:alert(1)
. Em seguida, o navegador redireciona para…
Ei, estou segura! Não havia nenhuma caixa de alerta aparecendo. Sim, eu poderia inserir https://google.com
como o valor do vector
parâmetro de consulta e ser redirecionado para o Google, então meu aplicativo (PoC) é vulnerável ao redirecionamento aberto, mas não por causa do Koa, mas porque passei dados de usuário não filtrados para ctx.redirect
. Não é algo que me preocupe, eu nunca faria isso.
Uma coisa importante a observar nos comentários do problema no GitHub é o seguinte:
O problema decorre do fato de que o Koa imprime um hiperlink HTML no corpo da resposta de redirecionamento e isso pode desencadear um ataque de script entre sites.
Ah, isso faz um pouco mais de sentido! Vamos ver se ainda é assim.
Não, não é mais o caso. Não há corpo de resposta. Acho que posso concluir que essa “vulnerabilidade” não me afeta. Posso simplesmente marcá-lo como falso positivo no Dependency Track.
Análise de Contexto
Proponho que a “Análise de contexto” seja adotada por todos os profissionais de segurança e realizada antes de relatar “problemas”. Que este seja outro exemplo e mostre como se faz. (Eu ainda recomendo que você leia CVE-2022–29622: Análise de (In)vulnerabilidade , pois explica muito melhor a importância do contexto.)
- O Koa.JS pronto para uso não o redireciona para lugar nenhum. Portanto, existe e não houve “Redirecionamento Aberto” conforme declarado pelo Sonatype OSS Index.
- Com base no “PoC” fornecido no GitHub, havia uma oportunidade para um desenvolvedor fazer algo estúpido que poderia levar ao XSS. Mas, veja # 1 acima. Koa.JS não fez nenhum redirecionamento por conta própria. Veja o nº 2 abaixo.
- Um desenvolvedor deve ter implementado seu aplicativo de maneira insegura para que a “vulnerabilidade” relatada esteja presente. Isso praticamente significa que o Koa.JS, embora pudesse ter feito melhor, você não poderia chamá-lo de vulnerável. É contextualmente inapropriado. A vulnerabilidade em questão só pode estar presente em um aplicativo da Web implementado de forma insegura .
Deixe-me dar um exemplo de como situações como essa são melhor tratadas. Veja este problema que enviei ao Swagger Parser e como ele foi comunicado. Vamos analisar o relatório de problemas:
- O título diz “Comportamento inseguro do resolvedor”. Não estou falando sobre LFI (Local File Inclusion) no título. Isso ocorre porque, embora haja um potencial para inclusão de arquivo local SE EU BAGUNÇAR, cabe a mim, como desenvolvedor, saber com o que estou trabalhando e como estou trabalhando com isso. O comportamento padrão era (talvez ainda seja) inseguro. Mas, a biblioteca sozinha, sem o meu envolvimento não vai adiantar nada.
- Em seguida, declaro claramente de qual versão da biblioteca estou falando. Torno o contexto ainda mais claro listando as condições sob as quais o comportamento padrão inseguro da biblioteca afetaria um aplicativo. Isso deixa bem claro que a biblioteca em si não é vulnerável, mas tem um comportamento inseguro que pode ser melhorado para ajudar os desenvolvedores.
- Então, agora que o contexto está definido, eu forneço um PoC funcional, um trecho de código vulnerável (escrevi como um PoC, não faz parte do Swagger Parser!) e o resultado real da exploração de um aplicativo/serviço vulnerável que usa o biblioteca de forma insegura.
- Fiz algumas investigações e descobri que, como desenvolvedor, posso realmente configurar a biblioteca de forma a atenuar o problema. (até certo ponto) eu compartilhei isso com os desenvolvedores. Se nada mais, pelo menos eles podem atualizar a documentação para aumentar a conscientização.
- Forneci contexto adicional, análise e um exemplo de como as coisas poderiam ser melhoradas.
Conclusão
Em primeiro lugar, a Sonatype deve se sair melhor com o índice OSS e garantir que as informações de versão estejam disponíveis para cada vulnerabilidade no banco de dados. Isso é o mínimo. (Pontos de bônus por remover totalmente essa entrada específica do banco de dados.)
Eu suspeito que o Dependency Track sofre de FOMO, portanto, está disposto a relatar problemas puramente com base na correspondência do nome do componente se o número da versão não estiver disponível. Eu entendo até certo ponto que eles não correriam o risco de perder uma vulnerabilidade crítica. O problema desse comportamento (falsos positivos) é que ele não incentiva a adoção da Análise de Composição de Software. Isso assustará os desenvolvedores como os falsos positivos da análise de código estático. Contraproducente.
Contexto! O maldito contexto, pessoal! Eu proponho:
- “Análise de contexto” a ser adotada por todos os profissionais de segurança e realizada antes de relatar “problemas”
- Distinguir “comportamento inseguro” de “vulnerabilidade”
- Entendendo a diferença entre uma biblioteca de software e um aplicativo/serviço