특수 HTTP 헀더

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 헀더와 달리 ν˜„μž¬ μš”μ²­μ„ 처리 쀑인 ν”„λ‘μ‹œκ°€ μ²˜λ¦¬ν•˜κ³  μ†ŒλΉ„ν•˜λ„λ‘ μ„€κ³„λœ ν—€λ”μž…λ‹ˆλ‹€.

  • 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 λ°μŠ€μ‹±ν¬κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. ν”„λ‘μ‹œ ν”„λŸ°νŠΈμ—”λ“œλŠ” 초기 μš”μ²­μ˜ 본문을 보낼 μ€€λΉ„κ°€ λ˜μ–΄ μžˆμ—ˆκΈ° λ•Œλ¬Έμ— 본문을 보내고, λ°±μ—”λ“œλŠ” 이λ₯Ό μƒˆλ‘œμš΄ μš”μ²­μœΌλ‘œ μ²˜λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€.
  • Expect: y 100-continue λ³€ν˜•μ„ 보내도 0.CL λ°μŠ€μ‹±ν¬κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.
  • λ°±μ—”λ“œκ°€ 404둜 μ‘λ‹΅ν•œ 경우 μœ μ‚¬ν•œ 였λ₯˜λ‘œ CL.0 λ°μŠ€μ‹±ν¬κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. μ•…μ˜μ μΈ μš”μ²­μ΄ 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-cacheλŠ” Cache-Control: no-cache와 동일함
  • Warning: 일반 HTTP 헀더인 **Warning**은 λ©”μ‹œμ§€ μƒνƒœμ™€ κ΄€λ ¨ν•œ κ°€λŠ₯ν•œ λ¬Έμ œμ— λŒ€ν•œ 정보λ₯Ό ν¬ν•¨ν•©λ‹ˆλ‹€. 응닡에 볡수의 Warning 헀더가 λ‚˜νƒ€λ‚  수 μžˆμŠ΅λ‹ˆλ‹€. 예: Warning: 110 anderson/1.3.37 "Response is stale"

쑰건뢀 μš”μ²­

  • 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μž„μ„ λ‚˜νƒ€λƒ…λ‹ˆλ‹€.

Range μš”μ²­

  • Accept-Ranges: μ„œλ²„κ°€ Range μš”μ²­μ„ μ§€μ›ν•˜λŠ”μ§€, μ§€μ›ν•œλ‹€λ©΄ μ–΄λ–€ λ‹¨μœ„λ‘œ λ²”μœ„λ₯Ό ν‘œν˜„ν•  수 μžˆλŠ”μ§€ λ‚˜νƒ€λƒ…λ‹ˆλ‹€. Accept-Ranges: <range-unit>
  • Range: μ„œλ²„κ°€ λ°˜ν™˜ν•΄μ•Ό ν•˜λŠ” λ¬Έμ„œμ˜ 뢀뢄을 λ‚˜νƒ€λƒ…λ‹ˆλ‹€. 예: Range:80-100은 μ›λž˜ μ‘λ‹΅μ˜ λ°”μ΄νŠΈ 80μ—μ„œ 100을 λ°˜ν™˜ν•˜λ©° μƒνƒœ μ½”λ“œλŠ” 206 Partial Contentκ°€ λ©λ‹ˆλ‹€. λ˜ν•œ μš”μ²­μ—μ„œ Accept-Encoding 헀더λ₯Ό μ œκ±°ν•˜λŠ” 것을 κΈ°μ–΅ν•˜μ„Έμš”.
  • μ΄λŠ” μ›λž˜λΌλ©΄ μ΄μŠ€μΌ€μ΄ν”„λ˜λŠ” μž„μ˜μ˜ λ°˜μ‚¬λœ μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œλ₯Ό ν¬ν•¨ν•œ 응닡을 μ–»λŠ” 데 μœ μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ 이λ₯Ό μ•…μš©ν•˜λ €λ©΄ μš”μ²­μ— 이런 헀더듀을 μ£Όμž…ν•΄μ•Ό ν•©λ‹ˆλ‹€.
  • 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μž„μ„ leakν•˜κ³  μžˆλŠ” κ²ƒμž…λ‹ˆλ‹€.

μ„œλ²„ 정보

  • 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) 응닡을 κΈ°λ‹€λ¦½λ‹ˆλ‹€. 이 λ©”μ»€λ‹ˆμ¦˜μ€ μ„œλ²„ 확인을 κΈ°λ‹€λ¦ΌμœΌλ‘œμ¨ λ„€νŠΈμ›Œν¬ μ‚¬μš©μ„ μ΅œμ ν™”ν•˜λŠ” 데 도움을 μ€λ‹ˆλ‹€.

λ‹€μš΄λ‘œλ“œ

HTTP μ‘λ‹΅μ˜ Content-Disposition ν—€λ”λŠ” νŒŒμΌμ„ μ›ΉνŽ˜μ΄μ§€ λ‚΄μ—μ„œ ν‘œμ‹œν• μ§€(인라인) μ•„λ‹ˆλ©΄ **첨뢀(λ‹€μš΄λ‘œλ“œ)**둜 μ²˜λ¦¬ν• μ§€ μ§€μ‹œν•©λ‹ˆλ‹€. 예λ₯Ό λ“€λ©΄:

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 μ½”λ“œλ₯Ό 기본적으둜 μ•ˆμ „ν•˜κ²Œ λ§Œλ“­λ‹ˆλ‹€.

// 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

이 ν—€λ”λŠ” MIME type sniffing을 λ°©μ§€ν•©λ‹ˆλ‹€. μ΄λŠ” XSS μ·¨μ•½μ μœΌλ‘œ μ΄μ–΄μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€. λΈŒλΌμš°μ €κ°€ μ„œλ²„μ—μ„œ μ§€μ •ν•œ MIME νƒ€μž…μ„ μ‘΄μ€‘ν•˜λ„λ‘ 보μž₯ν•©λ‹ˆλ‹€.

X-Content-Type-Options: nosniff

X-Frame-Options

이 ν—€λ”λŠ” clickjacking을 λ°©μ§€ν•˜κΈ° μœ„ν•΄ λ¬Έμ„œκ°€ <frame>, <iframe>, <embed>, λ˜λŠ” <object> νƒœκ·Έμ— μ–΄λ–»κ²Œ 포함될 수 μžˆλŠ”μ§€λ₯Ό μ œν•œν•˜λ©°, λͺ¨λ“  λ¬Έμ„œκ°€ 포함 ν—ˆμš©μ„ λͺ…μ‹œμ μœΌλ‘œ μ§€μ •ν•  것을 ꢌμž₯ν•©λ‹ˆλ‹€.

X-Frame-Options: DENY

크둜슀-μ˜€λ¦¬μ§„ λ¦¬μ†ŒμŠ€ μ •μ±… (CORP) 및 크둜슀-μ˜€λ¦¬μ§„ λ¦¬μ†ŒμŠ€ 곡유 (CORS)

CORPλŠ” μ›Ήμ‚¬μ΄νŠΈμ—μ„œ λ‘œλ“œν•  수 μžˆλŠ” λ¦¬μ†ŒμŠ€λ₯Ό μ§€μ •ν•˜λŠ” 데 맀우 μ€‘μš”ν•˜λ©°, cross-site leaksλ₯Ό μ™„ν™”ν•©λ‹ˆλ‹€. CORSλŠ” 반면 보닀 μœ μ—°ν•œ cross-origin λ¦¬μ†ŒμŠ€ 곡유 λ©”μ»€λ‹ˆμ¦˜μ„ ν—ˆμš©ν•˜μ—¬ νŠΉμ • μ‘°κ±΄μ—μ„œ same-origin policyλ₯Ό μ™„ν™”ν•©λ‹ˆλ‹€.

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

ꡐ차 좜처 μž„λ² λ” μ •μ±… (COEP) 및 ꡐ차 좜처 μ˜€ν”„λ„ˆ μ •μ±… (COOP)

COEP와 COOPλŠ” ꡐ차 좜처 격리λ₯Ό κ°€λŠ₯ν•˜κ²Œ ν•˜λŠ” 데 ν•„μˆ˜μ μ΄λ©°, Spectre-like attacks의 μœ„ν—˜μ„ 크게 μ€„μ—¬μ€λ‹ˆλ‹€. 이듀은 각각 ꡐ차 좜처 λ¦¬μ†ŒμŠ€μ˜ λ‘œλ”©κ³Ό ꡐ차 좜처 창과의 μƒν˜Έμž‘μš©μ„ μ œμ–΄ν•©λ‹ˆλ‹€.

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

Permissions-Policy (formerly Feature-Policy)

Permissions-PolicyλŠ” μ›Ή κ°œλ°œμžκ°€ λ¬Έμ„œ λ‚΄μ—μ„œ νŠΉμ • λΈŒλΌμš°μ € κΈ°λŠ₯κ³Ό API의 λ™μž‘μ„ μ„ νƒμ μœΌλ‘œ ν™œμ„±ν™”Β·λΉ„ν™œμ„±ν™”ν•˜κ±°λ‚˜ μˆ˜μ •ν•  수 있게 ν•©λ‹ˆλ‹€. μ΄λŠ” ν˜„μž¬ 폐기된 Feature-Policy ν—€λ”μ˜ ν›„μ†μž…λ‹ˆλ‹€. 이 ν—€λ”λŠ” μ•…μš©λ  수 μžˆλŠ” κ°•λ ₯ν•œ κΈ°λŠ₯에 λŒ€ν•œ 접근을 μ œν•œν•˜μ—¬ attack surfaceλ₯Ό μ€„μ΄λŠ” 데 도움을 μ€λ‹ˆλ‹€.

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

일반 λ””λ ‰ν‹°λΈŒ:

λ””λ ‰ν‹°λΈŒμ„€λͺ…
accelerometerAccelerometer μ„Όμ„œμ— λŒ€ν•œ 접근을 μ œμ–΄ν•©λ‹ˆλ‹€
cameraλΉ„λ””μ˜€ μž…λ ₯ μž₯치(μ›ΉμΊ )에 λŒ€ν•œ 접근을 μ œμ–΄ν•©λ‹ˆλ‹€
geolocationGeolocation API에 λŒ€ν•œ 접근을 μ œμ–΄ν•©λ‹ˆλ‹€
gyroscopeGyroscope μ„Όμ„œμ— λŒ€ν•œ 접근을 μ œμ–΄ν•©λ‹ˆλ‹€
magnetometerMagnetometer μ„Όμ„œμ— λŒ€ν•œ 접근을 μ œμ–΄ν•©λ‹ˆλ‹€
microphoneμ˜€λ””μ˜€ μž…λ ₯ μž₯μΉ˜μ— λŒ€ν•œ 접근을 μ œμ–΄ν•©λ‹ˆλ‹€
paymentPayment Request API에 λŒ€ν•œ 접근을 μ œμ–΄ν•©λ‹ˆλ‹€
usbWebUSB API에 λŒ€ν•œ 접근을 μ œμ–΄ν•©λ‹ˆλ‹€
fullscreenFullscreen API에 λŒ€ν•œ 접근을 μ œμ–΄ν•©λ‹ˆλ‹€
autoplayλ―Έλ””μ–΄μ˜ μžλ™ μž¬μƒ ν—ˆμš© μ—¬λΆ€λ₯Ό μ œμ–΄ν•©λ‹ˆλ‹€
clipboard-readν΄λ¦½λ³΄λ“œ λ‚΄μš©μ„ μ½λŠ” 접근을 μ œμ–΄ν•©λ‹ˆλ‹€
clipboard-writeν΄λ¦½λ³΄λ“œμ— μ“°λŠ” 접근을 μ œμ–΄ν•©λ‹ˆλ‹€

ꡬ문 κ°’:

  • () - κΈ°λŠ₯을 μ™„μ „νžˆ λΉ„ν™œμ„±ν™”ν•©λ‹ˆλ‹€
  • (self) - λ™μΌν•œ μΆœμ²˜μ—μ„œλ§Œ κΈ°λŠ₯을 ν—ˆμš©ν•©λ‹ˆλ‹€
  • * - λͺ¨λ“  μΆœμ²˜μ— λŒ€ν•΄ κΈ°λŠ₯을 ν—ˆμš©ν•©λ‹ˆλ‹€
  • (self "https://example.com") - 동일 μΆœμ²˜μ™€ μ§€μ •λœ 도메인에 λŒ€ν•΄ ν—ˆμš©ν•©λ‹ˆλ‹€

예제 ꡬ성:

# 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")

From a security perspective, missing or overly permissive Permissions-Policy headers may allow attackers (e.g., through XSS or embedded iframes) to abuse powerful browser features. Always restrict features to the minimum necessary for your application.

Header Name Casing Bypass

HTTP/1.1 defines header field‐names as case-insensitive (RFC 9110 Β§5.1). Nevertheless, it is very common to find custom middleware, security filters, or business logic that compare the literal header name received without normalising the casing first (e.g. header.equals("CamelExecCommandExecutable")). If those checks are performed case-sensitively, an attacker may bypass them simply by sending the same header with a different capitalisation.

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. Identify a header that is filtered or validated server-side (for example, by reading source code, documentation, or error messages).
  2. Send the same header with a different casing (mixed-case or upper-case). Because HTTP stacks usually canonicalise headers only after user code has run, the vulnerable check can be skipped.
  3. If the downstream component treats headers in a case-insensitive way (most do), it will accept the attacker-controlled value.

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

헀더가 ν•„ν„°λ§λ˜μ§€ μ•Šμ€ 채 exec μ»΄ν¬λ„ŒνŠΈμ— λ„λ‹¬ν•˜μ—¬ Camel ν”„λ‘œμ„ΈμŠ€μ˜ κΆŒν•œμœΌλ‘œ remote command execution을 μ΄ˆλž˜ν•©λ‹ˆλ‹€.

탐지 및 μ™„ν™”

  • ν—ˆμš©/κ±°λΆ€ 비ꡐλ₯Ό μˆ˜ν–‰ν•˜κΈ° 이전에, λͺ¨λ“  헀더 이름을 ν•˜λ‚˜μ˜ μΌ€μ΄μŠ€(보톡 μ†Œλ¬Έμž)둜 μ •κ·œν™”ν•˜μ„Έμš”.
  • μ˜μ‹¬μŠ€λŸ¬μš΄ 쀑볡을 κ±°λΆ€ν•˜μ„Έμš”: Header:와 HeAdEr:κ°€ λ™μ‹œμ— μ‘΄μž¬ν•˜λ©΄ 이λ₯Ό 이상(anomaly)으둜 μ²˜λ¦¬ν•˜μ„Έμš”.
  • μ •κ·œν™” 이후에 μ μš©λ˜λŠ” 긍정적 ν—ˆμš© λͺ©λ‘(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 μ§€μ›ν•˜κΈ°