Negação de serviço
O formulário de cadastro tem um campo de nome. Nada impede que um nome tenha dez milhões de caracteres.
// O que é enviado como `name`
'a'.repeat(10_000_000)Não há nada de código nessa string. Ela não será interpretada como nada. Ela só é enorme, e enorme já é o suficiente.
Guarde isso e o banco de dados cresce. Consulte isso e a consulta fica lenta. Faça backup e o backup também cresce, toda noite, para sempre. Faça isso algumas milhares de vezes e o serviço para de conseguir responder a qualquer pessoa.
Uma requisição não precisa ser engenhosa para causar dano. Ela só precisa ser cara.
Envie isso apenas contra o seu próprio serviço
Testes de volume são indistinguíveis de um ataque enquanto estão em andamento, e afetam todos os outros usuários de qualquer sistema para o qual sejam direcionados. Use apenas a sua própria aplicação, ou um sistema para o qual você tenha permissão explícita para testar.
Disponibilidade é uma propriedade de segurança
Segurança costuma ser discutida como manter segredos e manter dados corretos. Existe uma terceira propriedade, e este é o capítulo dela: disponibilidade, ou seja, se o serviço responde ou não.
Um ataque de negação de serviço, ou DoS, ataca justamente essa terceira propriedade. Ele não lê nada, não muda nada e não rouba nada. Ele torna o serviço incapaz de fazer o seu trabalho, o que para um negócio costuma ser o resultado mais caro.
Pense no que uma loja perde num dia em que não consegue abrir. Ali também nada foi roubado.
Quatro formas de derrubar um serviço
O curso agrupa esses ataques pelo que o atacante explora, e vale a pena manter esse agrupamento, porque cada um se combate de um jeito diferente.
| Forma | Como funciona | O que ela esgota |
|---|---|---|
| Bala mágica | Uma única mensagem cuidadosamente construída que viola uma regra do protocolo, como enviar mais dados do que um campo foi feito para armazenar | Um defeito específico, imediatamente |
| Baseado em volume | Tráfego suficiente ou entrada grande o bastante para saturar a conexão ou lotar o disco | Banda, memória, armazenamento |
| Protocolo | Abuso de como um protocolo foi especificado para funcionar, de forma que o servidor mantém recursos reservados sem nunca poder liberá-los | Tabelas de conexão, temporizadores, sockets |
| Distribuído | O mesmo tráfego, chegando de milhares de máquinas separadas ao mesmo tempo | Tudo o que foi listado acima, vindo de todo lugar |
Vale a pena ver o ataque de protocolo em detalhe, porque ele mostra o quão pouco tráfego um ataque eficaz pode exigir. Uma conexão TCP, o aperto de mão por trás da maior parte do tráfego da internet, se estabelece em três passos:
- O cliente envia um pacote
SYN, que significa "eu gostaria de me conectar". - O servidor responde
SYN-ACK, que significa "pode prosseguir", e passa a manter um espaço reservado enquanto espera. - O cliente responde
ACK, e a conexão é estabelecida.
Em uma inundação SYN, o atacante envia o primeiro passo com um endereço de retorno falsificado. O segundo passo vai para uma máquina que nunca pediu isso e não tem nada a responder. O terceiro passo nunca chega.
O servidor mantém um espaço reservado aberto e um temporizador rodando, enquanto o atacante já passou para o próximo endereço falsificado.
Nada aqui é de alto volume. É barato para quem envia e caro para quem recebe, repetidas vezes, até a tabela de conexões ficar cheia e um visitante de verdade não conseguir um espaço.
Uma negação de serviço distribuída, ou DDoS, é qualquer um desses ataques vindo de uma botnet: uma rede de máquinas comuns controladas pelo atacante, geralmente infectadas sem que seus donos percebam.
É isso que torna esse tipo difícil de combater. Cada máquina é um dispositivo real fazendo requisições que parecem reais, então não existe um único endereço para bloquear nem uma assinatura para filtrar.
Um aperto de mão falsificado custa um pacote para enviar e prende um espaço reservado por segundos. Esse desequilíbrio é todo o jogo, e é por isso que volume não é a única coisa a se observar.
As defesas se somam
Não existe um único controle aqui. O curso lista seis, e eles atuam em camadas diferentes de propósito:
- Redundância. Rode mais de uma instância de tudo: servidores, data centers, caminhos de rede, servidores de nomes. A regra prática é três, para que um possa estar falhando e outro sob ataque enquanto um terceiro ainda atende.
- Limitação e controle de taxa. A limitação de taxa recusa requisições acima de um teto. O controle de taxa as desacelera. Cem chamadas de API por minuto, cinco tentativas de login em dez minutos, um megabyte por segundo.
- Filtragem. Decida o que aceitar e de onde. Bloqueie endereços ou regiões, rejeite requisições com cargas claramente maliciosas, exija autenticação, faça triagem por cabeçalhos.
- Fortalecimento. Remova o que você não precisa. Todo serviço em execução é uma porta de entrada, assim como toda conta que ninguém usa: logins de administrador padrão, ex-funcionários que mantiveram acesso, permissões concedidas uma vez para uma migração.
- Aplicação de patches. O ataque de bala mágica depende de um defeito específico e conhecido. Aplicar a correção do fornecedor é o que o elimina.
- Monitoramento. Você não consegue identificar o anormal sem conhecer o normal. Um serviço que costuma receber mil requisições por hora e de repente recebe cem mil só fica obviamente errado se alguém tiver registrado o número mil.
Especificamente para o nome de dez milhões de caracteres, a resposta é um limite de tamanho, verificado no servidor antes de o valor ser armazenado. Isso é validação de esquema, e é a camada para a qual esta seção está caminhando.
Redundância ganha tempo. Limites de taxa limitam o dano. Monitoramento é como você descobre o que está acontecendo. Aplicação de patches remove a brecha específica. Elas cobrem momentos diferentes, então você quer todas elas, em vez de escolher a melhor.
Coloque em prática
O formulário de cadastro aceita name, email e password, os armazena, e retorna os dois primeiros. Sem limites em lugar nenhum.
Resolva três coisas:
- Qual requisição custa mais caro ao servidor, e o que a torna cara?
- Qual das seis defesas impediria essa requisição, e qual apenas reduziria o dano?
- Qual é a mudança mais barata que resolve isso?
Compare suas respostas
1. A requisição mais cara. Um name ou password muito longo. Custa memória para analisar, armazenamento para guardar, tempo em toda consulta que toca a linha, e espaço em todo backup a partir daí.
password é o pior dos dois se a aplicação faz hash dele. O hashing é deliberadamente lento, então um valor enorme transforma uma operação já cara em uma muito mais cara ainda.
2. Quais defesas fazem efeito.
- Impedem completamente: filtragem e um limite de tamanho. O servidor rejeita a requisição antes de fazer o trabalho caro.
- Reduzem o dano: limitação e controle de taxa. Elas limitam a frequência da repetição, mas a requisição individual ainda chega.
- Nenhuma das duas coisas: redundância, aplicação de patches e monitoramento. Elas ajudam você a sobreviver ao ataque, removem brechas não relacionadas, e permitem descobrir que ele está acontecendo.
3. A mudança mais barata. Um comprimento máximo em todo campo de texto, aplicado no servidor. É uma linha por campo em um esquema, e isso elimina a classe inteira do problema, o que explica por que esta seção dedica os capítulos restantes a acertar esse esquema.
Para onde isso leva
Dois capítulos depois, e ambos os bugs vêm da mesma etapa que faltou. Nada verificou o que chegava antes de a aplicação agir sobre isso.
Injeção de SQL é o terceiro e o mais direto. Uma entrada que não apenas fica armazenada no banco de dados, mas diz a ele o que fazer.

