English version available here
Este post faz parte de uma coleção de posts sobre segurança de software ao longo do processo de desenvolvimento e operação (DevSecOps). O tipo de vulnerabilidade abordado neste artigo é negação de serviço através da exploração por requisições pesadas (payload).
Se você não leu o primeiro artigo da série de DoS, recomendo sua leitura antes de continuar, pois ali são explicados alguns conceitos importantes, como o próprio DoS e log de acessos!
Certa vez, enquanto homologava um site para receber o selo SiteBlindado, recebi uma notificação de que várias operações do sistema estavam suscetíveis a receber um tráfego muito maior de dados do que de fato necessitavam. Foi então que precisei configurar limites específicos para tamanhos de requisições e me dei conta que esta é uma boa proteção contra DoS.
Como identificar um DoS por requisições pesadas
A maneira mais eficaz para identificar este ataque é analisando o tamanho das requisições que seus servidores estão recebendo. Esta informação geralmente está disponível nos formatadores dos logs de acesso (por exemplo, no nginx usa-se a variável $request_length). Um log de tráfego normal seria:
2020-06-05T10:14:02Z GET / 1.1.1.1 459 "Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"
2020-06-05T10:15:23Z GET /products 2.2.2.2 257 "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1"
2020-06-05T10:16:53Z POST /admin 3.3.3.3 523 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:58.0) Gecko/20100101 Firefox/58.0"
2020-06-05T10:17:20Z GET / 4.4.4.4 289 "Mozilla/5.0 (Android 4.4.2; Tablet; rv:65.0) Gecko/65.0 Firefox/65.0"
2020-06-05T10:18:22Z GET / 5.5.5.5 336 "Mozilla/5.0 (Android 4.4.2; Tablet; rv:65.0) Gecko/65.0 Firefox/65.0"
2020-06-05T10:19:11Z GET /products 318 6.6.6.6 "Mozilla/5.0 (Linux; U; Android 5.0.2; en-US; XT1068 Build/LXB22.46-28) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.10.2.1164 Mobile Safari/537.36"
A informação mais importante neste caso é o número entre o IP do cliente que enviou a requisição e o valor do cabeçalho User Agent. Por exemplo, na terceira requisição, este número é 523. É o tamanho total da requisição em bytes, incluindo cabeçalhos e corpo.
Caso o seu serviço esteja sofrendo tentativas de ataque com requisições pesadas, você perceberá uma diferença grande entre o tamanho normal das suas requisições e o que está recebendo durante o ataque. Por isso a importância de conhecer os limites normais do seu software. Quanto costuma ser, em um tráfego de operação normal, o tamanho das suas requisições?. Nesta situação, poderíamos ter um aumento no tamanho da terceira requisição (normalmente estes ataques utilizam os seus recursos que aceitam postagem de dados, como upload de imagens ou cadastramento de formulários):
2020-06-05T10:16:53Z POST /admin 3.3.3.3 9000000 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:58.0) Gecko/20100101 Firefox/58.0"
Neste novo log, tivemos um aumento no tamanho da requisição, indo de ~0.5kb para 9mb! Geralmente este sintoma vem acompanhado da repetição da requisição por várias vezes (o que abordamos no primeiro post):
2020-06-05T10:14:02Z GET / 1.1.1.1 459 "Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"
2020-06-05T10:15:23Z GET /products 2.2.2.2 257 "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1"
2020-06-05T10:16:53Z POST /admin 3.3.3.3 9000000 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:58.0) Gecko/20100101 Firefox/58.0"
2020-06-05T10:17:20Z GET / 4.4.4.4 289 "Mozilla/5.0 (Android 4.4.2; Tablet; rv:65.0) Gecko/65.0 Firefox/65.0"
2020-06-05T10:18:22Z GET / 5.5.5.5 336 "Mozilla/5.0 (Android 4.4.2; Tablet; rv:65.0) Gecko/65.0 Firefox/65.0"
2020-06-05T10:18:53Z POST /admin 3.3.3.3 9000000 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:58.0) Gecko/20100101 Firefox/58.0"
2020-06-05T10:18:53Z POST /admin 3.3.3.3 9000000 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:58.0) Gecko/20100101 Firefox/58.0"
2020-06-05T10:18:53Z POST /admin 3.3.3.3 9000000 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:58.0) Gecko/20100101 Firefox/58.0"
2020-06-05T10:18:53Z POST /admin 3.3.3.3 9000000 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:58.0) Gecko/20100101 Firefox/58.0"
2020-06-05T10:18:53Z POST /admin 3.3.3.3 9000000 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:58.0) Gecko/20100101 Firefox/58.0"
2020-06-05T10:18:53Z POST /admin 3.3.3.3 9000000 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:58.0) Gecko/20100101 Firefox/58.0"
2020-06-05T10:18:53Z POST /admin 3.3.3.3 9000000 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:58.0) Gecko/20100101 Firefox/58.0"
2020-06-05T10:19:11Z GET /products 318 6.6.6.6 "Mozilla/5.0 (Linux; U; Android 5.0.2; en-US; XT1068 Build/LXB22.46-28) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.10.2.1164 Mobile Safari/537.36"
Algo não está certo neste tipo de aumento considerável e repetitivo. É hora de agir!
Configurando corretamente os limites dos seus servidores
A solução para mitigar esta exploração é estabelecer limites para os tamanhos de requisições, evitando assim que seus servidores trabalhem desnecessariamente em requisições pesadas e que excedam o normal aceitável para a operação do serviço.
Você pode configurar estes limites de "fora para dentro", desde firewalls cloud (como o AWS WAF, Akamai Web Protector e CloudFlare WAF) até seus servidores de proxy reverso ou de aplicação. A grande maioria dos servidores fornece a opção de limitar o tamanho das requisições. Vou citar alguns, em camadas diferentes da arquitetura:
- Limitando no firewall;
- Limitando no proxy reverso ou balancer;
- Limitando no servidor de aplicação;
- Limitando no código da aplicação;
Conclusão
- Monitore constantemente sua aplicação e seus servidores;
- Conheça os limites normais da sua aplicação;
- Caso você esteja sofrendo ataques, saber o tamanho do seu tráfego normal facilitará bastante na identificação.
- Adote a filosofia de "limitar por baixo até que seja necessário";
- Estabeleça limites pequenos para os tamanhos das suas requisições (a melhor dica é estabelecer uma média de tamanho com base nos seus pontos de entrada que recebem a maior quantidade de dados).
- Aumente estes limites de forma granular e especifica (por ex: se você precisa fazer upload de arquivos, ajuste a configuração para permitir um limite maior especificamente na operação de upload).
Top comments (0)