FlawOpen

flawopen.com/Vulnerabilities/Fixação de sessão e proteção de cookies

Fixação de sessão: troque o ID no login (CWE-384)

High Severity CWE-384 Cryptography & Auth
💡 Explicação simples — a ficha de bagagem presa

Imagine que alguém convence um viajante a usar um número de ficha de bagagem que o atacante já conhece. Se a companhia aérea mantiver esse número após o check-in, o atacante poderá retirar a mala. Na fixação de sessão, a aplicação aceita um identificador que o atacante consegue fazer a vítima usar e depois o transforma em uma sessão autenticada sem trocá-lo. As duas condições são necessárias; um link de phishing sozinho não fixa a sessão, a menos que a aplicação aceite ou permita definir esse identificador.

Alvo: gerenciamento de sessões no servidor e o identificador usado pelo navegador autenticado.
Pré-condição: o atacante consegue fazer a vítima usar um ID de sessão conhecido, por exemplo, por meio de ID na URL aceito pelo sistema ou injeção de cookie.
Falha: a aplicação mantém esse ID conhecido pelo atacante durante a transição de sessão anônima para autenticada.
Correção: emita um ID novo e imprevisível na autenticação; configure atributos de cookie para ameaças distintas.

Conceitos centrais e termos do subsistema

Fixação de sessão
Falha de gerenciamento de sessão em que a aplicação aceita um identificador conhecido pelo atacante e o mantém quando a vítima se autentica.
Rotação do ID de sessão
Emita um identificador novo e imprevisível quando a autenticação elevar os privilégios da sessão. Preserve somente os dados de sessão que a aplicação pretende manter.
Atributos de cookie
Secure restringe o envio do cookie a HTTPS; HttpOnly impede acesso ao cookie por JavaScript; SameSite controla parte do envio em contextos cross-site. São proteções distintas e não substituem a rotação do ID.
Prefixo __Host-
Em navegadores compatíveis, exige cookie Secure criado por HTTPS, com Path=/ e sem atributo Domain. Ajuda a impedir que um subdomínio irmão defina um cookie para o domínio pai com o mesmo nome.

Fluxo de ataque passo a passo

Step 1

O atacante obtém ou escolhe um identificador de sessão

Uma falha ou funcionalidade separada permite que o atacante obtenha um ID e faça o navegador da vítima enviá-lo. O método depende da aplicação; um link comum de phishing não funciona se IDs de sessão na URL não forem aceitos.

Step 2

A vítima usa o identificador conhecido pelo atacante

O navegador envia esse ID à aplicação, que o trata como uma sessão anônima válida. O atacante precisa conseguir reconhecer ou reutilizar o mesmo identificador.

Step 3

A autenticação eleva os privilégios da sessão

A vítima entra na conta. Se a aplicação associar a identidade autenticada ao ID existente sem trocá-lo, esse identificador conhecido passa a apontar para a sessão autenticada.

Step 4

O atacante reutiliza o identificador inalterado

Se o atacante ainda puder enviar o ID e o servidor não o tiver invalidado, poderá acessar a sessão da vítima. A rotação do ID durante a mudança de privilégio interrompe essa cadeia.

Mecanismo e causa raiz

A fixação de sessão exige tanto a influência do atacante sobre o identificador usado pela vítima quanto a falha da aplicação em substituí-lo após o login. Atributos de cookie são defesa em profundidade, mas nenhum substitui a rotação: HttpOnly limita a leitura por scripts, Secure restringe o transporte a HTTPS, SameSite reduz alguns envios cross-site e __Host- limita o escopo do cookie em navegadores compatíveis.

login_view.py (Padrão vulnerável)Vulnerável
# VULNERABLE: custom session code keeps the pre-authentication ID.
def login_view(request):
    user = authenticate(request, request.POST["username"],
                        request.POST["password"])
    if user is not None:
        # BUG: privilege changes, but the session ID does not.
        request.session["user_id"] = user.pk
        request.session["authenticated"] = True
        return redirect("/account/")
    return redirect("/login/")
login_view.py (Exemplo Django seguro)Protegido
# HARDENED: Django login() rotates the session key on authentication.
from django.contrib.auth import authenticate, login

def login_view(request):
    user = authenticate(request, request.POST["username"],
                        request.POST["password"])
    if user is not None:
        # Uses Django's supported authentication/session integration.
        login(request, user)
        return redirect("/account/")
    return redirect("/login/")

# settings.py: use HTTPS, host-only scope, and a deliberate SameSite policy.
SESSION_COOKIE_NAME = "__Host-sessionid"
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = "Lax"
SESSION_COOKIE_PATH = "/"
SESSION_COOKIE_DOMAIN = None

Sequência de ataque e exemplo conceitual

Regras de prevenção e proteção para engenharia

Fontes e tópicos relacionados de segurança:Diretório completo de segurança →
CWE-384: fixação de sessão → OWASP: guia de gerenciamento de sessão → OWASP WSTG: teste de fixação de sessão → Django: sessões e cycle_key() → MDN: cookies HTTP e prefixos →