Snyking in - exploração de vulnerabilidade de negação de serviço por expressão regular no pacote ms
13 de março de 2019
0 minutos de leituraBoas-vindas a mais uma edição da nossa série de exploração Snyking In! Da última vez, analisamos uma exploração de vulnerabilidade de travessia de diretórios na biblioteca st. Neste episódio, vamos analisar a vulnerabilidade de negação de serviço por expressão regular, mostrar como ela pode ser explorada e explicar os riscos potenciais que representa para seus dados e sistemas.
Também vamos mostrar como encontrar e corrigir esse tipo de vulnerabilidade na sua aplicação. Sem mais delongas, confira o vídeo da exploração e, em seguida, mais informações sobre a vulnerabilidade de negação de serviço por expressão regular.

Negação de serviço por expressão regular
Negação de serviço (DoS) é o nome dado a uma família de ataques que têm como objetivo impedir o acesso de usuários legítimos a um sistema. Existem vários tipos de ataques DoS: desde sobrecarregar os canais de rede do sistema com um grande volume de tráfego gerado por várias máquinas (um ataque distribuído de negação de serviço, ou DDoS) até enviar solicitações criadas para fazer o sistema travar ou levar tempo demais para processá-las.
A negação de serviço por expressão regular (ReDoS) é um tipo de ataque de negação de serviço. Expressões regulares são extremamente poderosas, mas não são muito intuitivas e podem acabar facilitando o trabalho de invasores que querem tirar seu site do ar.
O relatório recente sobre o estado da segurança de código aberto, publicado pela Snyk, mostrou que as divulgações de vulnerabilidades de negação de serviço por expressão regular aumentaram 143% somente no último ano.

Retrocesso catastrófico
Vamos analisar a seguinte expressão regular:
Esta expressão regular faz o seguinte:
AA string precisa começar com a letraA(B|C+)+Em seguida, depois da letraA, a string precisa conter a letraBou uma ou mais ocorrências da letraC(o+corresponde a uma ou mais ocorrências). O+no final desta seção indica que podemos procurar uma ou mais correspondências desta seção.DPor fim, garantimos que esta seção da string termine com umD
A expressão corresponderia a entradas como ABBD, ABCCCCD, ABCBCCCD e ACCCCCD. Na maioria dos casos, o mecanismo de regex encontra uma correspondência rapidamente:
Todo o processo de testar uma string de 30 caracteres leva cerca de 52 ms. Mas, quando recebe uma string inválida, o teste demora quase dois segundos — mais de dez vezes o tempo necessário para testar uma string válida. Essa diferença drástica se deve à maneira como as expressões regulares são avaliadas.
A maioria dos mecanismos de regex funciona de maneira muito parecida, com pequenas diferenças. O mecanismo encontra a primeira forma possível de corresponder ao caractere atual e avança para o próximo. Se não conseguir corresponder ao caractere seguinte, ele volta atrás para verificar se havia outra maneira de processar o caractere anterior. Se avançar demais por esse caminho e só então descobrir que a string não corresponde ao padrão — e se muitos caracteres tiverem vários caminhos válidos na expressão regular —, o número de etapas de retrocesso pode se tornar muito grande. Esse fenômeno é conhecido como retrocesso catastrófico.
A exploração do pacote ms
O comando a seguir adiciona uma tarefa à lista de afazeres do nosso aplicativo Snyk Goof. O trecho in 20 minutes do texto é identificado pelo mecanismo de regex como uma indicação de tempo. A lógica de negócios do aplicativo pode usar essa informação para criar lembretes ou alertas, por exemplo.
Podemos tentar forçar o tamanho da entrada da tarefa da seguinte maneira. O comando imprime 60.000 5s como o número de minutos, mas retorna muito rápido, pois o padrão ainda corresponde.
Para causar uma negação de serviço, precisamos passar uma string que provoque um cenário de retrocesso catastrófico. Isso exige uma string de entrada longa, como no exemplo anterior, mas também precisamos garantir que o mecanismo de regex nunca corresponda ao padrão e, por isso, retroceda por todas as possibilidades antes de falhar. Esse atraso — ou a negação de serviço — é o que queremos provocar. Para isso, podemos alterar o texto minutes no conteúdo para minutea, por exemplo, um padrão ao qual o mecanismo de regex não corresponderá. O comando a seguir para adicionar uma tarefa causará uma negação de serviço de cerca de 10 a 15 segundos. Se passarmos 600.000 5s, vamos esperar o resto do dia até que o servidor conclua a solicitação.
Para testar se sua aplicação tem vulnerabilidades em bibliotecas de terceiros, como ms, experimente o Snyk gratuitamente.
Comece a resolver desafios de capture the flag
Aprenda a resolver desafios de capture the flag assistindo sob demanda ao nosso workshop virtual introdutório.
