Cabeçalhos HTTP especiais

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

Wordlists & Tools

Headers to Change Location

Reescrever origem do IP:

  • X-Originating-IP: 127.0.0.1
  • X-Forwarded-For: 127.0.0.1
  • X-Forwarded: 127.0.0.1
  • Forwarded-For: 127.0.0.1
  • X-Forwarded-Host: 127.0.0.1
  • X-Remote-IP: 127.0.0.1
  • X-Remote-Addr: 127.0.0.1
  • X-ProxyUser-Ip: 127.0.0.1
  • X-Original-URL: 127.0.0.1
  • Client-IP: 127.0.0.1
  • X-Client-IP: 127.0.0.1
  • X-Host: 127.0.0.1
  • True-Client-IP: 127.0.0.1
  • Cluster-Client-IP: 127.0.0.1
  • Via: 1.0 fred, 1.1 127.0.0.1
  • Connection: close, X-Forwarded-For (Verificar hop-by-hop headers)

Reescrever localização:

  • X-Original-URL: /admin/console
  • X-Rewrite-URL: /admin/console

Hop-by-Hop headers

Um cabeçalho hop-by-hop é projetado para ser processado e consumido pelo proxy que está manuseando a requisição no momento, ao invés de ser um cabeçalho end-to-end.

  • Connection: close, X-Forwarded-For

hop-by-hop headers

HTTP Request Smuggling

  • Content-Length: 30
  • Transfer-Encoding: chunked

HTTP Request Smuggling / HTTP Desync Attack

The Expect header

É possível que o cliente envie o cabeçalho Expect: 100-continue e então o servidor responda com HTTP/1.1 100 Continue para permitir que o cliente continue enviando o body da requisição. No entanto, alguns proxies não gostam desse cabeçalho.

Resultados interessantes de Expect: 100-continue:

  • Enviar um HEAD request com um body — o servidor não levou em conta que HEAD requests não têm body e mantém a conexão aberta até timeout.
  • Alguns servidores enviaram dados estranhos: dados aleatórios lidos do socket na resposta, chaves secretas ou até permitiram que o front-end não removesse valores de cabeçalho.
  • Também causou um desync 0.CL porque o backend respondeu com um 400 em vez de 100, mas o proxy front-end estava preparado para enviar o body da requisição inicial; então ele envia o body e o backend o interpreta como uma nova requisição.
  • Enviar uma variação Expect: y 100-continue também causou o desync 0.CL.
  • Um erro similar onde o backend respondeu com um 404 gerou um desync CL.0 porque a requisição maliciosa indicava um Content-Length, então o backend envia a requisição maliciosa + os bytes do Content-Length da próxima requisição (de uma vítima). Isso desincroniza a fila porque o backend envia a resposta 404 para a requisição maliciosa + a resposta da requisição da vítima, mas o front-end achava que apenas 1 requisição havia sido enviada, então a segunda resposta é enviada para uma segunda vítima e a resposta dessa é enviada para a próxima…

Para mais info sobre HTTP Request Smuggling confira:

HTTP Request Smuggling / HTTP Desync Attack

Cache Headers

Server Cache Headers:

  • X-Cache na resposta pode ter o valor miss quando a requisição não foi cacheada e o valor hit quando foi cacheada
  • Comportamento similar no cabeçalho Cf-Cache-Status
  • Cache-Control indica se um recurso está sendo cacheado e quando será a próxima vez que o recurso será cacheado novamente: Cache-Control: public, max-age=1800
  • Vary é frequentemente usado na resposta para indicar cabeçalhos adicionais que são tratados como parte da chave do cache, mesmo que normalmente não façam parte da chave.
  • Age define o tempo em segundos que o objeto esteve no cache do proxy.
  • Server-Timing: cdn-cache; desc=HIT também indica que um recurso foi cacheado

Cache Poisoning and Cache Deception

Local Cache headers:

  • Clear-Site-Data: Cabeçalho para indicar o cache que deve ser removido: Clear-Site-Data: "cache", "cookies"
  • Expires: Contém a data/hora quando a resposta deve expirar: Expires: Wed, 21 Oct 2015 07:28:00 GMT
  • Pragma: no-cache mesmo que Cache-Control: no-cache
  • Warning: O cabeçalho geral HTTP Warning contém informações sobre possíveis problemas com o status da mensagem. Mais de um Warning pode aparecer em uma resposta. Warning: 110 anderson/1.3.37 "Response is stale"

Conditionals

  • Requisições que usam esses cabeçalhos: If-Modified-Since e If-Unmodified-Since serão respondidas com dados apenas se o header de resposta Last-Modified contiver um tempo diferente.
  • Requisições condicionais usando If-Match e If-None-Match usam um valor Etag, então o web server enviará o conteúdo da resposta se o dado (Etag) tiver mudado. O Etag é obtido do HTTP response.
  • O valor do Etag geralmente é calculado com base no conteúdo da resposta. Por exemplo, ETag: W/"37-eL2g8DEyqntYlaLp5XLInBWsjWI" indica que o Etag é o Sha1 de 37 bytes.

Range requests

  • Accept-Ranges: Indica se o servidor suporta range requests, e em qual unidade o range pode ser expresso. Accept-Ranges: <range-unit>
  • Range: Indica a parte de um documento que o servidor deve retornar. Por exemplo, Range:80-100 retornará os bytes 80 a 100 da resposta original com o status 206 Partial Content. Também lembre-se de remover o cabeçalho Accept-Encoding da requisição.
  • Isso pode ser útil para obter uma resposta com código JavaScript refletido arbitrário que de outra forma poderia ser escapado. Mas para abusar disso você precisaria injetar esses headers na requisição.
  • If-Range: Cria uma requisição condicional de range que só é satisfeita se o etag ou data fornecida corresponder ao recurso remoto. Usado para evitar baixar dois ranges de versões incompatíveis do recurso.
  • Content-Range: Indica onde, em uma mensagem completa, uma mensagem parcial pertence.

Message body information

  • Content-Length: O tamanho do recurso, em número decimal de bytes.
  • Content-Type: Indica o media type do recurso
  • Content-Encoding: Usado para especificar o algoritmo de compressão.
  • Content-Language: Descreve a(s) língua(s) humana(s) destinada(s) ao público, permitindo que o usuário diferencie de acordo com sua preferência.
  • Content-Location: Indica uma localização alternativa para os dados retornados.

Do ponto de vista de um pentest essa informação é normalmente “inútil”, mas se o recurso estiver protegido por um 401 ou 403 e você conseguir alguma maneira de get essa info, isso pode ser interessante.
Por exemplo, uma combinação de Range e Etag em um HEAD request pode leak o conteúdo da página via HEAD requests:

  • Uma requisição com o header Range: bytes=20-20 e com uma resposta contendo ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y" está leak que o SHA1 do byte 20 é ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y

Server Info

  • Server: Apache/2.4.1 (Unix)
  • X-Powered-By: PHP/5.3.3

Controls

  • Allow: Esse header é usado para comunicar os métodos HTTP que um recurso pode manipular. Por exemplo, pode ser especificado como Allow: GET, POST, HEAD, indicando que o recurso suporta esses métodos.
  • Expect: Utilizado pelo cliente para transmitir expectativas que o servidor precisa cumprir para que a requisição seja processada com sucesso. Um caso de uso comum envolve o header Expect: 100-continue, que sinaliza que o cliente pretende enviar um payload grande. O cliente aguarda uma resposta 100 (Continue) antes de prosseguir com a transmissão. Esse mecanismo ajuda a otimizar o uso da rede aguardando a confirmação do servidor.

Downloads

  • O cabeçalho Content-Disposition em respostas HTTP indica se um arquivo deve ser exibido inline (dentro da página) ou tratado como um attachment (baixado). Por exemplo:
Content-Disposition: attachment; filename="filename.jpg"

Isso significa que o arquivo chamado “filename.jpg” destina-se a ser baixado e salvo.

Cabeçalhos de Segurança

Política de Segurança de Conteúdo (CSP)

Content Security Policy (CSP) Bypass

Trusted Types

Ao impor Trusted Types via CSP, as aplicações podem ser protegidas contra ataques DOM XSS. Trusted Types garantem que apenas objetos especificamente criados, conformes com políticas de segurança estabelecidas, possam ser usados em chamadas de APIs web perigosas, protegendo assim o código JavaScript por padrão.

// Feature detection
if (window.trustedTypes && trustedTypes.createPolicy) {
// Name and create a policy
const policy = trustedTypes.createPolicy('escapePolicy', {
createHTML: str => str.replace(/\</g, '&lt;').replace(/>/g, '&gt;');
});
}
// Assignment of raw strings is blocked, ensuring safety.
el.innerHTML = "some string" // Throws an exception.
const escaped = policy.createHTML("<img src=x onerror=alert(1)>")
el.innerHTML = escaped // Results in safe assignment.

X-Content-Type-Options

Este cabeçalho previne a detecção do tipo MIME, uma prática que pode levar a vulnerabilidades de XSS. Ele garante que os navegadores respeitem os tipos MIME especificados pelo servidor.

X-Content-Type-Options: nosniff

X-Frame-Options

Para combater clickjacking, este header restringe como documentos podem ser embutidos em <frame>, <iframe>, <embed>, ou <object> tags, recomendando que todos os documentos especifiquem explicitamente suas permissões de incorporação.

X-Frame-Options: DENY

Política de Recursos Cross-Origin (CORP) e Compartilhamento de Recursos Cross-Origin (CORS)

CORP é crucial para especificar quais recursos podem ser carregados por websites, mitigando cross-site leaks. CORS, por outro lado, permite um mecanismo mais flexível de compartilhamento de recursos cross-origin, relaxando a same-origin policy em certas condições.

Cross-Origin-Resource-Policy: same-origin
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

Cross-Origin Embedder Policy (COEP) and Cross-Origin Opener Policy (COOP)

COEP e COOP são essenciais para habilitar o isolamento cross-origin, reduzindo significativamente o risco de ataques semelhantes ao Spectre. Eles controlam o carregamento de recursos cross-origin e a interação com janelas cross-origin, respectivamente.

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin-allow-popups

HTTP Strict Transport Security (HSTS)

Por fim, o HSTS é um recurso de segurança que força os navegadores a se comunicarem com os servidores apenas por meio de conexões HTTPS seguras, aumentando assim a privacidade e a segurança.

Strict-Transport-Security: max-age=3153600

Permissions-Policy (formerly Feature-Policy)

Permissions-Policy permite que desenvolvedores web habilitem, desabilitem ou modifiquem seletivamente o comportamento de certas funcionalidades do navegador e APIs dentro de um documento. É o sucessor do cabeçalho Feature-Policy, agora obsoleto. Este cabeçalho ajuda a reduzir a superfície de ataque ao restringir o acesso a funcionalidades poderosas que podem ser abusadas.

Permissions-Policy: geolocation=(), camera=(), microphone=()

Diretivas comuns:

DiretivaDescrição
accelerometerControla o acesso ao sensor Accelerometer
cameraControla o acesso a dispositivos de entrada de vídeo (webcam)
geolocationControla o acesso à Geolocation API
gyroscopeControla o acesso ao sensor Gyroscope
magnetometerControla o acesso ao sensor Magnetometer
microphoneControla o acesso a dispositivos de entrada de áudio
paymentControla o acesso à Payment Request API
usbControla o acesso à WebUSB API
fullscreenControla o acesso à Fullscreen API
autoplayControla se a mídia pode reproduzir automaticamente
clipboard-readControla o acesso para ler o conteúdo da área de transferência
clipboard-writeControla o acesso para gravar na área de transferência

Valores de sintaxe:

  • () - Desativa totalmente o recurso
  • (self) - Permite o recurso apenas para a mesma origem
  • * - Permite o recurso para todas as origens
  • (self "https://example.com") - Permite para a mesma origem e para o domínio especificado

Exemplos de configurações:

# Restrictive policy - disable most features
Permissions-Policy: geolocation=(), camera=(), microphone=(), payment=(), usb=()

# Allow camera only from same origin
Permissions-Policy: camera=(self)

# Allow geolocation for same origin and a trusted partner
Permissions-Policy: geolocation=(self "https://maps.example.com")

Do ponto de vista de segurança, cabeçalhos Permissions-Policy ausentes ou excessivamente permissivos podem permitir que atacantes (por exemplo, via XSS ou iframes incorporados) abusem de funcionalidades poderosas do navegador. Sempre restrinja os recursos ao mínimo necessário para sua aplicação.

Header Name Casing Bypass

HTTP/1.1 define nomes de campos de header como insensíveis a maiúsculas/minúsculas (RFC 9110 §5.1). Ainda assim, é muito comum encontrar middleware customizados, filtros de segurança ou lógica de negócio que comparam o nome de header literal recebido sem normalizar a capitalização primeiro (ex.: header.equals("CamelExecCommandExecutable")). Se essas verificações forem feitas de forma sensível a maiúsculas/minúsculas, um atacante pode contorná‑las simplesmente enviando o mesmo header com uma capitalização diferente.

Typical situations where this mistake appears:

  • Custom allow/deny lists that try to block “dangerous” internal headers before the request reaches a sensitive component.
  • In-house implementations of reverse-proxy pseudo-headers (e.g. X-Forwarded-For sanitisation).
  • Frameworks that expose management / debug endpoints and rely on header names for authentication or command selection.

Abusing the bypass

  1. Identifique um header que seja filtrado ou validado no servidor (por exemplo, lendo código-fonte, documentação ou mensagens de erro).
  2. Envie o mesmo header com uma capitalização diferente (mixed-case ou upper-case). Como as pilhas HTTP normalmente normalizam os headers somente depois do código do usuário ser executado, a verificação vulnerável pode ser ignorada.
  3. Se o componente downstream tratar os headers de maneira insensível a maiúsculas/minúsculas (a maioria o faz), ele aceitará o valor controlado pelo atacante.

Example: Apache Camel exec RCE (CVE-2025-27636)

In vulnerable versions of Apache Camel the Command Center routes try to block untrusted requests by stripping the headers CamelExecCommandExecutable and CamelExecCommandArgs. The comparison was done with equals() so only the exact lowercase names were removed.

# Bypass the filter by using mixed-case header names and execute `ls /` on the host
curl "http://<IP>/command-center" \
-H "CAmelExecCommandExecutable: ls" \
-H "CAmelExecCommandArgs: /"

Os headers chegam ao componente exec sem filtragem, resultando em remote command execution com os privilégios do processo Camel.

Detecção e Mitigação

  • Normalizar todos os header names para um único case (usualmente lowercase) antes de realizar comparações allow/deny.
  • Rejeitar duplicados suspeitos: se tanto Header: quanto HeAdEr: estiverem presentes, trate como uma anomalia.
  • Use uma allow-list positiva aplicada após a canonicalização.
  • Proteja management endpoints com autenticação e segmentação de rede.

Referências

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks