DoS usando colisão de hash no ASP .net
Este fim de semana na 28C3 Alexander “alech” Klink and Julian “zeri” Wälde apresentaram DoS efetivo contra plataformas de aplicações web que pode fazer um server ficar com 99% de CPU ocupada usando poucos recursos.
Nos meus testes, um simples post HTTP, com cerca de 100k hashes colididos (cerca de 1,2MB) deixou uma thread do servidor por horas usando 99% de CPU, conforme a imagem abaixo:
Se mais thread forem usadas, o servidor ficará facilmente sobrecarregado. No estudo, alech e zeri concluiram que com uma conexão de 30 kbits/s é suficiente para manter uma thread de um Core2 usando 99% de CPU indefinidamente, em um servidor rodando ASP .net. E uma conexão de 1 Gbit/s conseguirá ocupar cerca de ~30k thread do Core2. Um atacante por facilmente derrubar um pequeno datacenter usando uma conexão banda larga comum.
O Ataque
O problema ocorre pela forma como o ASP .net gerencia Forms, Cookies, Session e Query Strings. Todas essas coleções são armazenadas usando a NameValueCollection, que internamente usa StringComparer.OrdinalIgnoreCase para obter o hash das strings.
A função GetHashCode pode retornar valores iguais para strings diferentes e o método usado para calcular o hash é conhecido e pode ser adivinhado. O atacante pode gerar uma grande coleção de hashes colididos para postar em qualquer página ASP .net. O servidor tentará construir o objeto Request, e por causa das chaves colididas do Form, a chaves do NameValueCollection levarão muito tempo para serem criadas e o servidor utilizará muita CPU para comparar todos os valores.
Nos meus testes, usando IIS 7.5 e ASP .net 4.0, o servidor levou mais de uma hora usando 99% na thread afetada. O servidor não pode parar o processamento no tempo padrão (90s) porque a requisição foi afetada no começo do Pipeline do ASP .net.
A solução
Um módulo HTTP que verifique a requisição antes dela ser passada ao ASP .net e que pode para-lá caso um ataque seja detectado.
Eu comecei a criar este módulo, que é funcional mas não está pronto para uso em produção. Por enquanto, é para estudos, visto que a descoberta da falha ainda é recente.
O módulo HTTP e seu código fonte pode ser baixado do GitHub.
Qualquer comentário para ajudar a melhorar e garantir qualidade de produção ao módulo são bem vindos.