diff --git a/src/network-services-pentesting/pentesting-web/special-http-headers.md b/src/network-services-pentesting/pentesting-web/special-http-headers.md index 1047db04a..84b31fe5b 100644 --- a/src/network-services-pentesting/pentesting-web/special-http-headers.md +++ b/src/network-services-pentesting/pentesting-web/special-http-headers.md @@ -1,15 +1,15 @@ -# Special HTTP headers +# 특수 HTTP 헤더 {{#include ../../banners/hacktricks-training.md}} -## Wordlists & Tools +## 단어 목록 & 도구 - [https://github.com/danielmiessler/SecLists/tree/master/Miscellaneous/Web/http-request-headers](https://github.com/danielmiessler/SecLists/tree/master/Miscellaneous/Web/http-request-headers) - [https://github.com/rfc-st/humble](https://github.com/rfc-st/humble) -## Headers to Change Location +## 위치를 변경할 헤더 -Rewrite **IP source**: +IP 출처 재작성: - `X-Originating-IP: 127.0.0.1` - `X-Forwarded-For: 127.0.0.1` @@ -26,19 +26,20 @@ Rewrite **IP source**: - `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` (Check hop-by-hop headers) +- `Connection: close, X-Forwarded-For` (hop-by-hop 헤더 확인) -Rewrite **location**: +위치 재작성: - `X-Original-URL: /admin/console` - `X-Rewrite-URL: /admin/console` -## Hop-by-Hop headers +## Hop-by-Hop 헤더 -A hop-by-hop header is a header which is designed to be processed and consumed by the proxy currently handling the request, as opposed to an end-to-end header. +Hop-by-Hop 헤더는 end-to-end 헤더와는 달리 현재 요청을 처리 중인 proxy에서 처리되고 소비되도록 설계된 헤더입니다. - `Connection: close, X-Forwarded-For` + {{#ref}} ../../pentesting-web/abusing-hop-by-hop-headers.md {{#endref}} @@ -48,20 +49,40 @@ A hop-by-hop header is a header which is designed to be processed and consumed b - `Content-Length: 30` - `Transfer-Encoding: chunked` + {{#ref}} ../../pentesting-web/http-request-smuggling/ {{#endref}} -## Cache Headers +## 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에 대한 자세한 내용은 다음을 확인하세요: + +{{#ref}} +../../pentesting-web/http-request-smuggling/ +{{#endref}} + + +## 캐시 헤더 **서버 캐시 헤더**: -- **`X-Cache`** 응답에서 요청이 캐시되지 않았을 때는 **`miss`** 값을 가질 수 있으며, 캐시되었을 때는 **`hit`** 값을 가집니다. -- 헤더 **`Cf-Cache-Status`**에서도 유사한 동작을 합니다. -- **`Cache-Control`**은 리소스가 캐시되고 있는지와 다음에 리소스가 다시 캐시될 시간에 대해 나타냅니다: `Cache-Control: public, max-age=1800` -- **`Vary`**는 응답에서 **추가 헤더**를 나타내는 데 자주 사용되며, 일반적으로 키가 없는 헤더라도 **캐시 키의 일부**로 처리됩니다. -- **`Age`**는 객체가 프록시 캐시에 있었던 시간을 초 단위로 정의합니다. -- **`Server-Timing: cdn-cache; desc=HIT`**는 리소스가 캐시되었음을 나타냅니다. +- **`X-Cache`** 응답에서 값이 **`miss`**이면 요청이 캐시되지 않았음을, **`hit`**이면 캐시되었음을 나타낼 수 있습니다. +- 유사한 동작을 하는 헤더로 **`Cf-Cache-Status`**가 있습니다. +- **`Cache-Control`**은 자원이 캐시되는지 및 다음에 언제 다시 캐시될지를 나타냅니다: `Cache-Control: public, max-age=1800` +- **`Vary`**는 응답에서 자주 사용되며, 일반적으로 캐시 키에 포함되지 않는 추가 헤더들을 캐시 키의 일부로 취급함을 **표시**합니다. +- **`Age`**는 객체가 프록시 캐시에 머문 시간을 초 단위로 정의합니다. +- **`Server-Timing: cdn-cache; desc=HIT`** 또한 자원이 캐시되었음을 나타냅니다. + {{#ref}} ../../pentesting-web/cache-deception/ @@ -69,67 +90,68 @@ A hop-by-hop header is a header which is designed to be processed and consumed b **로컬 캐시 헤더**: -- `Clear-Site-Data`: 제거해야 할 캐시를 나타내는 헤더: `Clear-Site-Data: "cache", "cookies"` -- `Expires`: 응답이 만료되어야 하는 날짜/시간을 포함합니다: `Expires: Wed, 21 Oct 2015 07:28:00 GMT` -- `Pragma: no-cache`는 `Cache-Control: no-cache`와 동일합니다. -- `Warning`: **`Warning`** 일반 HTTP 헤더는 메시지 상태에 대한 가능한 문제에 대한 정보를 포함합니다. 응답에 여러 개의 `Warning` 헤더가 나타날 수 있습니다. `Warning: 110 anderson/1.3.37 "Response is stale"` +- `Clear-Site-Data`: 제거해야 할 캐시 유형을 지정하는 헤더: `Clear-Site-Data: "cache", "cookies"` +- `Expires`: 응답이 만료되는 날짜/시간을 포함: `Expires: Wed, 21 Oct 2015 07:28:00 GMT` +- `Pragma: no-cache`는 `Cache-Control: no-cache`와 동일 +- `Warning`: 일반 HTTP 헤더로 메시지 상태의 가능한 문제에 대한 정보를 포함합니다. 응답에 여러 `Warning` 헤더가 나타날 수 있습니다. 예: `Warning: 110 anderson/1.3.37 "Response is stale"` -## Conditionals +## 조건부 요청 -- 이러한 헤더를 사용하는 요청: **`If-Modified-Since`** 및 **`If-Unmodified-Since`**는 응답 헤더 **`Last-Modified`**에 다른 시간이 포함된 경우에만 데이터로 응답합니다. -- **`If-Match`** 및 **`If-None-Match`**를 사용하는 조건부 요청은 Etag 값을 사용하여 데이터(Etag)가 변경된 경우 웹 서버가 응답의 내용을 전송합니다. `Etag`는 HTTP 응답에서 가져옵니다. -- **Etag** 값은 일반적으로 응답의 **내용**을 기반으로 **계산**됩니다. 예를 들어, `ETag: W/"37-eL2g8DEyqntYlaLp5XLInBWsjWI"`는 `Etag`가 **37 바이트**의 **Sha1**임을 나타냅니다. +- **`If-Modified-Since`** 및 **`If-Unmodified-Since`** 헤더를 사용하는 요청은 응답 헤더의 **`Last-Modified`**가 다른 시간을 포함하는 경우에만 데이터가 반환됩니다. +- **`If-Match`** 및 **`If-None-Match`**을 사용하는 조건부 요청은 Etag 값을 사용하여 데이터(Etag)가 변경된 경우에만 웹 서버가 응답 내용을 전송합니다. `Etag`는 HTTP 응답에서 가져옵니다. +- **Etag** 값은 보통 응답의 **내용(content)**을 기반으로 **계산**됩니다. 예를 들어 `ETag: W/"37-eL2g8DEyqntYlaLp5XLInBWsjWI"`는 `Etag`가 **37 바이트**의 **Sha1**임을 나타냅니다. -## Range requests +## Range 요청 -- **`Accept-Ranges`**: 서버가 범위 요청을 지원하는지 여부와 범위를 표현할 수 있는 단위를 나타냅니다. `Accept-Ranges: ` -- **`Range`**: 서버가 반환해야 하는 문서의 부분을 나타냅니다. 예를 들어, `Range:80-100`은 원래 응답의 80에서 100 바이트를 반환하며, 상태 코드는 206 Partial Content입니다. 요청에서 `Accept-Encoding` 헤더를 제거하는 것도 잊지 마세요. -- 이는 그렇지 않으면 이스케이프될 수 있는 임의의 반사된 자바스크립트 코드로 응답을 얻는 데 유용할 수 있습니다. 그러나 이를 악용하려면 요청에 이 헤더를 주입해야 합니다. -- **`If-Range`**: 주어진 etag 또는 날짜가 원격 리소스와 일치하는 경우에만 충족되는 조건부 범위 요청을 생성합니다. 이는 리소스의 호환되지 않는 버전에서 두 범위를 다운로드하는 것을 방지하는 데 사용됩니다. -- **`Content-Range`**: 전체 본문 메시지에서 부분 메시지가 속하는 위치를 나타냅니다. +- **`Accept-Ranges`**: 서버가 range 요청을 지원하는지, 지원한다면 어떤 단위로 범위를 표현할 수 있는지 나타냅니다. `Accept-Ranges: ` +- **`Range`**: 서버가 반환해야 할 문서의 부분을 나타냅니다. 예를 들어 `Range:80-100`은 원본 응답의 바이트 80~100을 반환하며 상태 코드는 206 Partial Content가 됩니다. 또한 요청에서 `Accept-Encoding` 헤더를 제거하는 것을 잊지 마세요. +- 이는 통상적으로 이스케이프되는 반사된 javascript 코드를 임의로 포함한 응답을 얻는 데 유용할 수 있습니다. 다만 이를 악용하려면 요청에 해당 헤더들을 주입해야 합니다. +- **`If-Range`**: 주어진 etag나 날짜가 원격 자원과 일치하는 경우에만 충족되는 조건부 범위 요청을 만듭니다. 서로 호환되지 않는 버전의 리소스로부터 두 개의 범위를 다운로드하지 않도록 방지하기 위해 사용됩니다. +- **`Content-Range`**: 부분 메시지가 전체 바디 메시지의 어디에 속하는지를 나타냅니다. -## Message body information +## 메시지 본문 정보 -- **`Content-Length`:** 리소스의 크기, 바이트의 10진수 수입니다. -- **`Content-Type`**: 리소스의 미디어 유형을 나타냅니다. +- **`Content-Length`**: 리소스의 크기(십진수 바이트 수). +- **`Content-Type`**: 리소스의 미디어 타입을 나타냅니다. - **`Content-Encoding`**: 압축 알고리즘을 지정하는 데 사용됩니다. -- **`Content-Language`**: 청중을 위한 의도된 인간 언어를 설명하여 사용자가 자신의 선호하는 언어에 따라 구분할 수 있도록 합니다. +- **`Content-Language`**: 대상 청중을 위한 인간의 언어를 설명하여 사용자가 선호하는 언어에 따라 구분할 수 있게 합니다. - **`Content-Location`**: 반환된 데이터의 대체 위치를 나타냅니다. -펜테스트 관점에서 이 정보는 일반적으로 "쓸모없다"고 여겨지지만, 리소스가 **401** 또는 **403**으로 **보호**되고 이 **정보**를 **얻는 방법**을 찾을 수 있다면, 이는 **흥미로울 수 있습니다.**\ -예를 들어, HEAD 요청에서 **`Range`**와 **`Etag`**의 조합은 HEAD 요청을 통해 페이지의 내용을 유출할 수 있습니다: +pentest 관점에서는 이 정보가 보통 "쓸모없다"보여질 수 있지만, 자원이 401 또는 403으로 보호되고 있고 이 정보를 얻을 수 있는 어떤 방법을 찾을 수 있다면 이는 흥미로울 수 있습니다.\ +예를 들어 HEAD 요청에서 **`Range`**와 **`Etag`**의 조합은 HEAD 요청을 통해 페이지의 내용을 leak할 수 있습니다: -- 헤더 `Range: bytes=20-20`와 응답에 `ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y"`가 포함된 요청은 바이트 20의 SHA1이 `ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y`임을 유출하고 있습니다. +- `Range: bytes=20-20` 헤더를 가진 요청과 응답에 `ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y"`가 포함된 경우, 바이트 20의 SHA1이 `ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y`임을 leaking 하고 있는 것입니다. -## Server Info +## 서버 정보 - `Server: Apache/2.4.1 (Unix)` - `X-Powered-By: PHP/5.3.3` -## Controls +## 제어 -- **`Allow`**: 이 헤더는 리소스가 처리할 수 있는 HTTP 메서드를 전달하는 데 사용됩니다. 예를 들어, `Allow: GET, POST, HEAD`로 지정될 수 있으며, 이는 리소스가 이러한 메서드를 지원함을 나타냅니다. -- **`Expect`**: 클라이언트가 요청이 성공적으로 처리되기 위해 서버가 충족해야 하는 기대를 전달하는 데 사용됩니다. 일반적인 사용 사례는 클라이언트가 대량의 데이터 페이로드를 전송할 의도가 있음을 나타내는 `Expect: 100-continue` 헤더입니다. 클라이언트는 전송을 진행하기 전에 `100 (Continue)` 응답을 찾습니다. 이 메커니즘은 서버 확인을 기다림으로써 네트워크 사용을 최적화하는 데 도움이 됩니다. +- **`Allow`**: 이 헤더는 리소스가 처리할 수 있는 HTTP 메서드를 전달하는 데 사용됩니다. 예: `Allow: GET, POST, HEAD`는 해당 리소스가 이러한 메서드를 지원함을 나타냅니다. +- **`Expect`**: 클라이언트가 요청 처리를 위해 서버가 충족해야 하는 기대사항을 전달하는 데 사용됩니다. 일반적인 사용 사례는 큰 데이터 페이로드를 전송하려는 의도를 알리는 `Expect: 100-continue` 헤더로, 클라이언트는 전송을 계속하기 전에 `100 (Continue)` 응답을 기다립니다. 이 메커니즘은 서버 확인을 대기함으로써 네트워크 사용을 최적화하는 데 도움이 됩니다. -## Downloads +## 다운로드 -- HTTP 응답의 **`Content-Disposition`** 헤더는 파일이 **인라인**(웹페이지 내)으로 표시되어야 하는지 또는 **첨부 파일**(다운로드)로 처리되어야 하는지를 지시합니다. 예를 들어: +응답에서 **`Content-Disposition`** 헤더는 파일을 웹페이지 내에서 표시할지(**inline**) 아니면 **attachment**로 처리할지(다운로드) 지시합니다. 예를 들어: ``` Content-Disposition: attachment; filename="filename.jpg" ``` -이것은 "filename.jpg"라는 이름의 파일이 다운로드되고 저장되도록 의도되었음을 의미합니다. +이는 "filename.jpg"라는 파일이 다운로드되어 저장될 의도임을 의미합니다. ## 보안 헤더 ### 콘텐츠 보안 정책 (CSP) + {{#ref}} ../../pentesting-web/content-security-policy-csp-bypass/ {{#endref}} -### **신뢰할 수 있는 유형** +### **Trusted Types** -CSP를 통해 신뢰할 수 있는 유형을 강제함으로써, 애플리케이션은 DOM XSS 공격으로부터 보호될 수 있습니다. 신뢰할 수 있는 유형은 특정 보안 정책을 준수하는 특별히 제작된 객체만 위험한 웹 API 호출에 사용될 수 있도록 보장하여, 기본적으로 JavaScript 코드를 안전하게 만듭니다. +CSP를 통해 Trusted Types를 강제하면 애플리케이션을 DOM XSS 공격으로부터 보호할 수 있습니다. Trusted Types는 수립된 보안 정책을 준수하는 특정하게 생성된 객체만이 위험한 web API 호출에 사용되도록 보장하여 JavaScript 코드를 기본적으로 안전하게 합니다. ```javascript // Feature detection if (window.trustedTypes && trustedTypes.createPolicy) { @@ -148,73 +170,73 @@ el.innerHTML = escaped // Results in safe assignment. ``` ### **X-Content-Type-Options** -이 헤더는 MIME 타입 스니핑을 방지하며, 이는 XSS 취약점으로 이어질 수 있는 행위입니다. 이 헤더는 브라우저가 서버에서 지정한 MIME 타입을 준수하도록 보장합니다. +이 헤더는 MIME type sniffing을 방지합니다. 이는 XSS 취약점으로 이어질 수 있는 행위이며, 브라우저가 서버에서 지정한 MIME 타입을 존중하도록 보장합니다. ``` X-Content-Type-Options: nosniff ``` ### **X-Frame-Options** -클릭재킹을 방지하기 위해, 이 헤더는 문서가 ``, `