특수 HTTP 헤더

Reading time: 10 minutes

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기

단어 목록 & 도구

위치를 변경할 헤더

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 (hop-by-hop 헤더 확인)

위치 재작성:

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

Hop-by-Hop 헤더

Hop-by-Hop 헤더는 end-to-end 헤더와는 달리 현재 요청을 처리 중인 proxy에서 처리되고 소비되도록 설계된 헤더입니다.

  • Connection: close, X-Forwarded-For

hop-by-hop headers

HTTP Request Smuggling

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

HTTP Request Smuggling / HTTP Desync Attack

Expect 헤더

클라이언트가 Expect: 100-continue 헤더를 보내고 서버가 HTTP/1.1 100 Continue로 응답하여 클라이언트가 요청 본문 전송을 계속하도록 허용할 수 있습니다. 다만 일부 프록시는 이 헤더를 제대로 좋아하지 않습니다.

Expect: 100-continue의 흥미로운 결과:

  • 본문을 가진 HEAD 요청을 보냈을 때, 서버가 HEAD 요청에는 본문이 없다는 점을 고려하지 않아 타임아웃까지 연결을 열어 둔 경우가 있음.
  • 일부 서버는 응답에 소켓에서 읽은 랜덤 데이터, 비밀 키 등의 이상한 데이터를 보냈거나, 프론트엔드가 헤더 값을 제거하지 못하도록 허용함.
  • 또한 백엔드가 100 응답 대신 400 응답으로 응답하여 0.CL desync가 발생하기도 했습니다. 이 경우 프록시 프론트엔드는 초기 요청의 본문 전송을 준비하고 있었기 때문에 본문을 보내고, 백엔드는 이를 새로운 요청으로 받아들였습니다.
  • Expect: y 100-continue 같은 변형도 0.CL desync를 유발함.
  • 백엔드가 404로 응답한 유사한 오류는 CL.0 desync를 생성했는데, 이는 악성 요청이 Content-Length를 표시했기 때문에 백엔드가 악성 요청 + 다음 요청(피해자)의 Content-Length 바이트를 보내서 큐가 비동기화된 사례입니다. 백엔드는 악성 요청에 대해 404 응답을 보내고 피해자 요청들의 응답을 뒤이어 보냈지만, 프론트엔드는 단 하나의 요청만 보냈다고 생각하여 두 번째 응답을 다른 피해자에게 전송하고 그 응답이 다시 다음 요청으로 전달되는 등의 문제가 발생했습니다.

HTTP Request Smuggling에 대한 자세한 내용은 다음을 확인하세요:

HTTP Request Smuggling / HTTP Desync Attack

캐시 헤더

서버 캐시 헤더:

  • X-Cache 응답에서 값이 **miss**이면 요청이 캐시되지 않았음을, **hit**이면 캐시되었음을 나타낼 수 있습니다.
  • 유사한 동작을 하는 헤더로 **Cf-Cache-Status**가 있습니다.
  • **Cache-Control**은 자원이 캐시되는지 및 다음에 언제 다시 캐시될지를 나타냅니다: Cache-Control: public, max-age=1800
  • **Vary**는 응답에서 자주 사용되며, 일반적으로 캐시 키에 포함되지 않는 추가 헤더들을 캐시 키의 일부로 취급함을 표시합니다.
  • **Age**는 객체가 프록시 캐시에 머문 시간을 초 단위로 정의합니다.
  • Server-Timing: cdn-cache; desc=HIT 또한 자원이 캐시되었음을 나타냅니다.

Cache Poisoning and Cache Deception

로컬 캐시 헤더:

  • Clear-Site-Data: 제거해야 할 캐시 유형을 지정하는 헤더: Clear-Site-Data: "cache", "cookies"
  • Expires: 응답이 만료되는 날짜/시간을 포함: Expires: Wed, 21 Oct 2015 07:28:00 GMT
  • Pragma: no-cacheCache-Control: no-cache와 동일
  • Warning: 일반 HTTP 헤더로 메시지 상태의 가능한 문제에 대한 정보를 포함합니다. 응답에 여러 Warning 헤더가 나타날 수 있습니다. 예: Warning: 110 anderson/1.3.37 "Response is stale"

조건부 요청

  • If-Modified-SinceIf-Unmodified-Since 헤더를 사용하는 요청은 응답 헤더의 **Last-Modified**가 다른 시간을 포함하는 경우에만 데이터가 반환됩니다.
  • If-Match 및 **If-None-Match**을 사용하는 조건부 요청은 Etag 값을 사용하여 데이터(Etag)가 변경된 경우에만 웹 서버가 응답 내용을 전송합니다. Etag는 HTTP 응답에서 가져옵니다.
  • Etag 값은 보통 응답의 **내용(content)**을 기반으로 계산됩니다. 예를 들어 ETag: W/"37-eL2g8DEyqntYlaLp5XLInBWsjWI"Etag37 바이트Sha1임을 나타냅니다.

Range 요청

  • Accept-Ranges: 서버가 range 요청을 지원하는지, 지원한다면 어떤 단위로 범위를 표현할 수 있는지 나타냅니다. Accept-Ranges: <range-unit>
  • Range: 서버가 반환해야 할 문서의 부분을 나타냅니다. 예를 들어 Range:80-100은 원본 응답의 바이트 80~100을 반환하며 상태 코드는 206 Partial Content가 됩니다. 또한 요청에서 Accept-Encoding 헤더를 제거하는 것을 잊지 마세요.
  • 이는 통상적으로 이스케이프되는 반사된 javascript 코드를 임의로 포함한 응답을 얻는 데 유용할 수 있습니다. 다만 이를 악용하려면 요청에 해당 헤더들을 주입해야 합니다.
  • If-Range: 주어진 etag나 날짜가 원격 자원과 일치하는 경우에만 충족되는 조건부 범위 요청을 만듭니다. 서로 호환되지 않는 버전의 리소스로부터 두 개의 범위를 다운로드하지 않도록 방지하기 위해 사용됩니다.
  • Content-Range: 부분 메시지가 전체 바디 메시지의 어디에 속하는지를 나타냅니다.

메시지 본문 정보

  • Content-Length: 리소스의 크기(십진수 바이트 수).
  • Content-Type: 리소스의 미디어 타입을 나타냅니다.
  • Content-Encoding: 압축 알고리즘을 지정하는 데 사용됩니다.
  • Content-Language: 대상 청중을 위한 인간의 언어를 설명하여 사용자가 선호하는 언어에 따라 구분할 수 있게 합니다.
  • Content-Location: 반환된 데이터의 대체 위치를 나타냅니다.

pentest 관점에서는 이 정보가 보통 "쓸모없다"보여질 수 있지만, 자원이 401 또는 403으로 보호되고 있고 이 정보를 얻을 수 있는 어떤 방법을 찾을 수 있다면 이는 흥미로울 수 있습니다.
예를 들어 HEAD 요청에서 **Range**와 **Etag**의 조합은 HEAD 요청을 통해 페이지의 내용을 leak할 수 있습니다:

  • Range: bytes=20-20 헤더를 가진 요청과 응답에 ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y"가 포함된 경우, 바이트 20의 SHA1이 ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y임을 leaking 하고 있는 것입니다.

서버 정보

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

제어

  • Allow: 이 헤더는 리소스가 처리할 수 있는 HTTP 메서드를 전달하는 데 사용됩니다. 예: Allow: GET, POST, HEAD는 해당 리소스가 이러한 메서드를 지원함을 나타냅니다.
  • Expect: 클라이언트가 요청 처리를 위해 서버가 충족해야 하는 기대사항을 전달하는 데 사용됩니다. 일반적인 사용 사례는 큰 데이터 페이로드를 전송하려는 의도를 알리는 Expect: 100-continue 헤더로, 클라이언트는 전송을 계속하기 전에 100 (Continue) 응답을 기다립니다. 이 메커니즘은 서버 확인을 대기함으로써 네트워크 사용을 최적화하는 데 도움이 됩니다.

다운로드

응답에서 Content-Disposition 헤더는 파일을 웹페이지 내에서 표시할지(inline) 아니면 attachment로 처리할지(다운로드) 지시합니다. 예를 들어:

Content-Disposition: attachment; filename="filename.jpg"

이는 "filename.jpg"라는 파일이 다운로드되어 저장될 의도임을 의미합니다.

보안 헤더

콘텐츠 보안 정책 (CSP)

Content Security Policy (CSP) Bypass

Trusted Types

CSP를 통해 Trusted Types를 강제하면 애플리케이션을 DOM XSS 공격으로부터 보호할 수 있습니다. Trusted Types는 수립된 보안 정책을 준수하는 특정하게 생성된 객체만이 위험한 web API 호출에 사용되도록 보장하여 JavaScript 코드를 기본적으로 안전하게 합니다.

javascript
// 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;');
});
}
javascript
// 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

이 헤더는 MIME type sniffing을 방지합니다. 이는 XSS 취약점으로 이어질 수 있는 행위이며, 브라우저가 서버에서 지정한 MIME 타입을 존중하도록 보장합니다.

X-Content-Type-Options: nosniff

X-Frame-Options

clickjacking을 방지하기 위해, 이 헤더는 문서가 <frame>, <iframe>, <embed>, 또는 <object> 태그에 어떻게 임베드될 수 있는지를 제한하며, 모든 문서가 임베딩 권한을 명시적으로 지정하도록 권장합니다.

X-Frame-Options: DENY

Cross-Origin Resource Policy (CORP) 및 Cross-Origin Resource Sharing (CORS)

CORP는 웹사이트가 로드할 수 있는 리소스를 지정하는 데 중요하며, 교차 사이트 leaks를 완화합니다. CORS는 반면에 보다 유연한 교차 출처 리소스 공유 메커니즘을 허용하여 특정 조건에서 동일 출처 정책을 완화합니다.

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

교차 출처 임베더 정책 (COEP) 및 교차 출처 오퍼너 정책 (COOP)

COEP와 COOP는 교차 출처 격리를 가능하게 하는 데 필수적이며 Spectre와 유사한 공격의 위험을 크게 줄입니다. 이들은 각각 교차 출처 리소스의 로딩과 교차 출처 창과의 상호작용을 제어합니다.

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

HTTP Strict Transport Security (HSTS)

마지막으로, HSTS는 브라우저가 서버와 오직 보안된 HTTPS 연결을 통해서만 통신하도록 강제하는 보안 기능으로, 이를 통해 개인정보 보호와 보안을 향상시킵니다.

Strict-Transport-Security: max-age=3153600

헤더 이름 대소문자 우회

HTTP/1.1은 헤더 필드 이름을 대소문자를 구별하지 않음으로 정의합니다 (RFC 9110 §5.1). 그럼에도 불구하고, 커스텀 미들웨어, 보안 필터, 또는 비즈니스 로직에서 수신된 문자 그대로의 헤더 이름을 먼저 정규화하지 않고 비교하는 경우가 매우 흔합니다(예: header.equals("CamelExecCommandExecutable")). 만약 이러한 검사들이 대소문자 구분으로 수행된다면, 공격자는 단순히 같은 헤더를 다른 대소문자 표기로 전송하는 것만으로 우회할 수 있습니다.

Typical situations where this mistake appears:

  • 요청이 민감한 컴포넌트에 도달하기 전에 “위험한” 내부 헤더를 차단하려는 커스텀 허용/거부 목록.
  • 리버스-프록시 의사 헤더의 사내 구현(예: X-Forwarded-For sanitisation).
  • 관리/디버그 엔드포인트를 노출하고 인증이나 명령 선택에 헤더 이름을 사용하는 프레임워크.

우회 악용

  1. 서버 측에서 필터링되거나 검증되는 헤더를 식별합니다(예: 소스 코드, 문서, 오류 메시지를 통해).
  2. 같은 헤더를 다른 대소문자 표기(혼합 대/소문자 또는 모두 대문자)로 전송합니다. HTTP 스택은 일반적으로 헤더를 사용자 코드가 실행된 후에 정규화하므로, 취약한 검사를 건너뛸 수 있습니다.
  3. 하위 구성요소가 헤더를 대소문자 구분 없이 처리한다면(대부분 그렇다), 공격자가 제어한 값을 수용하게 됩니다.

예시: Apache Camel exec RCE (CVE-2025-27636)

취약한 버전의 Apache Camel에서 Command Center 라우트는 신뢰할 수 없는 요청을 차단하기 위해 CamelExecCommandExecutableCamelExecCommandArgs 헤더를 제거하려고 합니다. 비교는 equals()로 수행되어 정확히 일치하는 소문자 이름만 제거되었습니다.

bash
# 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: /"

헤더가 exec 컴포넌트에 필터링 없이 전달되어 Camel 프로세스 권한으로 remote command execution이 발생합니다.

탐지 및 완화

  • 모든 헤더 이름을 단일 케이스(보통 lowercase)로 정규화하세요 — allow/deny 비교를 수행하기 전에.
  • 의심스러운 중복을 거부하세요: Header:HeAdEr:가 동시에 존재하면 이상으로 처리하세요.
  • 정규화(canonicalisation) 후에 적용되는 positive allow-list를 사용하세요.
  • 관리 엔드포인트는 인증과 네트워크 분리로 보호하세요.

참고 자료

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기