un

guest
1 / ?
back to lessons

Cabeçalhos como Sacos

Frameworks de log HTTP tratam dos cabeçalhos de solicitação como um saco de pares chave-valor. A API de log expõe o saco completo. Operadores habilitam o log de cabeçalhos para depuração: quando uma solicitação falha, os cabeçalhos contam a história. Sem lista de negação embutida. Sem filtragem de credenciais na documentação. Cabeçalhos completos para o disco.

Os cabeçalhos de credenciais em uma solicitação típica:

- Authorization: Bearer eyJhbGciOiJIUzI1NiJ9... (JWT ou token OAuth)

- Cookie: session=abc123; auth=xyz789

- X-API-Key: sk-live-abc123...

- X-Auth-Token: ghp_abc123... (padrão de token de acesso pessoal do GitHub)

Esses valores autenticam a solicitação. Escritos em um arquivo de log, eles autenticam qualquer solicitação.

A Pipeline de Credenciais

Uma credencial escrita em um arquivo de log não fica em um lugar. Ela viaja:

1. Servidor web escreve em /var/log/nginx/access.log

2. Agente de rotação de log (logrotate) copia para /var/log/nginx/access.log.1

3. Navio de log (Fluentd, Filebeat, Logstash) lê e envia para agregador

4. Agregador de log (Elasticsearch, Splunk, Datadog) indexa e armazena

5. Mantido por 30-90 dias conforme política padrão

A credencial existe em todos os cinco locais ao mesmo tempo. Revogar o token de sessão não remove a credencial do agregador de log. Ele permanece acessível, exportável e acessível a qualquer um com acesso ao log durante todo o período de retenção.

A Janela de Exposição

Janela de exposição para uma credencial na memória: max(duração da sessão, vida do processo). Sessão: horas a dias. Processo: horas a semanas.

Janela de exposição para uma credencial em um log: max(duração da sessão, retenção do log). Sessão: horas a dias. Retenção: 30-90 dias.

Uma credencial roubada da memória exigia que o atacante estivesse presente durante a janela de sessão. Uma credencial roubada de um log só exige acesso ao agregador de log, disponível retroativamente, por todo o período de retenção.

MOAD-0003 vs MOAD-0004

MOAD-0003 (Contexto Revelado): uma credencial na memória se leaka para o manipulador de solicitação errado. Acessível apenas durante a janela do processo, através da piscina de threads. Transitório.

MOAD-0004 (Logged Secret): uma credencial no disco persiste através da rotação do log, envio de log e agregação de log. Acessível retroativamente, por qualquer um com acesso ao log, por 30-90 dias. Persistente.

A diferença estrutural: temporário versus persistente. A correção opera em um nível diferente.

Temporário vs Persistente

A distinção entre temporário e persistente determina a superfície de risco, o nível de correção e os requisitos de resposta a incidentes.

Por que o MOAD-0004 apresenta maior risco do que o MOAD-0003? Compare onde cada credencial vive e por quanto tempo.

Denylist de Credenciais na Camada de Serialização

A correção: um denylist de credenciais na camada de serialização. Antes que qualquer valor de cabeçalho chegue ao saída do log, verifique o nome do cabeçalho contra um denylist. Substitua o valor por [REDACTED].

CREDENTIAL_HEADERS = {
    'authorization',
    'cookie',
    'x-api-key',
    'x-auth-token',
    'x-csrf-token',
    'proxy-authorization',
}

def sanitize_headers(headers: dict) -> dict:
    return {
        k: '[REDACTED]' if k.lower() in CREDENTIAL_HEADERS else v
        for k, v in headers.items()
    }

A denylist deve estar no nível de serialização, não no nível de consulta de log. A empreita de consulta de log: aplica-se após o credenciamento chegar ao disco; o valor bruto ainda existe, apenas ocultado da exibição. A empreita no nível de serialização: o credenciamento nunca chega ao disco. O valor bruto nunca entra no arquivo de log, no empacotador de log ou no agregador de log.

Testando a Denylist

Três padrões de teste:

- Positivo: uma solicitação com Authorization: Bearer token123 produz uma entrada de log com Authorization: [REDACTED]

- Negativo: uma solicitação com Content-Type: application/json produz uma entrada de log com o valor intacto

- Case-insensitive: AUTHORIZATION: Bearer token123 também produz [REDACTED] (nomes de cabeçalho HTTP insensíveis ao caso)

A denylist requer manutenção: novos padrões de cabeçalho de credenciamento (por exemplo, cabeçalhos personalizados X-Service-Auth) precisam ser adicionados explicitamente. A solução é estrutural, mas não é auto-mantenedora.

Aplicar a Denylist

Uma equipe configura o formato de log de acesso do Nginx para incluir todos os cabeçalhos de solicitação para depurar um incidente de produção. A configuração:

log_format debug_format '$remote_addr - $request - $http_authorization - $http_cookie';
access_log /var/log/nginx/debug.log debug_format;

Eles resolvem o incidente e pretendem remover a configuração de depuração, mas a mudança não chega à produção antes do próximo ciclo de implantação (7 dias depois).

Identifique o defeito. Quais cabeçalhos de credenciamento poderiam ser expostos? Descreva a abordagem da denylist: onde ela se aplica, o que verifica e o que produz?