Cookies Hacking

Support HackTricks

쿠키는 사용자의 브라우저에서 동작을 제어하는 여러 속성을 가지고 있습니다. 다음은 이러한 속성에 대한 설명입니다:

Expires and Max-Age

쿠키의 만료 날짜는 Expires 속성에 의해 결정됩니다. 반대로, Max-age 속성은 쿠키가 삭제될 때까지의 시간을 초 단위로 정의합니다. 더 현대적인 관행을 반영하는 Max-age를 선택하세요.

Domain

쿠키를 받을 호스트는 Domain 속성에 의해 지정됩니다. 기본적으로 이는 쿠키를 발급한 호스트로 설정되며, 하위 도메인은 포함되지 않습니다. 그러나 Domain 속성이 명시적으로 설정되면 하위 도메인도 포함됩니다. 이는 하위 도메인 간의 쿠키 공유가 필요한 시나리오에서 유용한 덜 제한적인 옵션입니다. 예를 들어, Domain=mozilla.org로 설정하면 developer.mozilla.org와 같은 하위 도메인에서 쿠키에 접근할 수 있습니다.

Path

Cookie 헤더가 전송되기 위해 요청된 URL에 반드시 존재해야 하는 특정 URL 경로는 Path 속성에 의해 표시됩니다. 이 속성은 / 문자를 디렉토리 구분자로 간주하여 하위 디렉토리에서도 일치를 허용합니다.

Ordering Rules

두 개의 쿠키가 동일한 이름을 가질 때, 전송을 위해 선택되는 쿠키는 다음에 따라 결정됩니다:

  • 요청된 URL에서 가장 긴 경로와 일치하는 쿠키.

  • 경로가 동일할 경우 가장 최근에 설정된 쿠키.

SameSite

  • SameSite 속성은 쿠키가 제3자 도메인에서 발생한 요청에 대해 전송되는지를 결정합니다. 세 가지 설정을 제공합니다:

  • Strict: 제3자 요청에서 쿠키가 전송되지 않도록 제한합니다.

  • Lax: 제3자 웹사이트에서 시작된 GET 요청과 함께 쿠키가 전송될 수 있도록 허용합니다.

  • None: 모든 제3자 도메인에서 쿠키가 전송될 수 있도록 허용합니다.

쿠키를 구성할 때 이러한 속성을 이해하면 다양한 시나리오에서 예상대로 동작하도록 보장할 수 있습니다.

Request Type

Example Code

Cookies Sent When

Link

<a href="..."></a>

NotSet*, Lax, None

Prerender

<link rel="prerender" href=".."/>

NotSet*, Lax, None

Form GET

<form method="GET" action="...">

NotSet*, Lax, None

Form POST

<form method="POST" action="...">

NotSet*, None

iframe

<iframe src="..."></iframe>

NotSet*, None

AJAX

$.get("...")

NotSet*, None

Image

<img src="...">

NetSet*, None

Table from Invicti and slightly modified. SameSite 속성이 있는 쿠키는 CSRF 공격을 완화합니다.

*Chrome80(2019년 2월)부터 쿠키에 SameSite 속성이 없는 경우 기본 동작은 lax입니다 (https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/). 이 변경을 적용한 후, Chrome에서 SameSite 정책이 없는 쿠키는 처음 2분 동안은 None으로 처리되고, 이후에는 최상위 교차 사이트 POST 요청에 대해 Lax로 처리됩니다.

Cookies Flags

HttpOnly

이 속성은 클라이언트가 쿠키에 접근하는 것을 방지합니다 (예: Javascript를 통해: document.cookie).

Bypasses

  • 페이지가 요청의 응답으로 쿠키를 전송하는 경우 (예: PHPinfo 페이지에서), XSS를 악용하여 이 페이지에 요청을 보내고 응답에서 쿠키를 훔칠 수 있습니다 (예제는 여기에서 확인하세요).

  • 서버의 응답으로 TRACE HTTP 요청을 사용하여 우회할 수 있습니다 (이 HTTP 메서드가 사용 가능한 경우). 이 기술은 Cross-Site Tracking이라고 합니다.

  • 이 기술은 모던 브라우저에서 JS로 TRACE 요청을 보내는 것을 허용하지 않음으로써 방지됩니다. 그러나 IE6.0 SP2에서 \r\nTRACE를 보내는 것과 같은 특정 소프트웨어에서 우회 방법이 발견되었습니다.

  • 또 다른 방법은 브라우저의 제로/데이 취약점을 악용하는 것입니다.

  • 쿠키 항아리 오버플로우 공격을 수행하여 HttpOnly 쿠키를 덮어쓸 수 있습니다:

Cookie Jar Overflow
  • Cookie Smuggling 공격을 사용하여 이러한 쿠키를 유출할 수 있습니다.

Secure

요청은 HTTP 요청이 보안 채널(일반적으로 HTTPS)을 통해 전송될 때만 쿠키를 전송합니다.

Cookies Prefixes

__Secure-로 접두사가 붙은 쿠키는 HTTPS로 보호되는 페이지와 함께 secure 플래그와 함께 설정되어야 합니다.

__Host-로 접두사가 붙은 쿠키는 여러 조건을 충족해야 합니다:

  • secure 플래그와 함께 설정되어야 합니다.

  • HTTPS로 보호되는 페이지에서 유래해야 합니다.

  • 도메인을 지정하는 것이 금지되어 하위 도메인으로의 전송을 방지합니다.

  • 이러한 쿠키의 경로는 /로 설정되어야 합니다.

__Host-로 접두사가 붙은 쿠키는 슈퍼도메인이나 하위 도메인으로 전송될 수 없다는 점에 유의해야 합니다. 이 제한은 애플리케이션 쿠키를 격리하는 데 도움이 됩니다. 따라서 모든 애플리케이션 쿠키에 대해 __Host- 접두사를 사용하는 것은 보안 및 격리를 강화하는 좋은 관행으로 간주될 수 있습니다.

Overwriting cookies

따라서 __Host- 접두사가 붙은 쿠키의 보호 중 하나는 하위 도메인에서 덮어쓰는 것을 방지하는 것입니다. 예를 들어 Cookie Tossing attacks를 방지합니다. Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities (paper)에서 하위 도메인에서 __HOST- 접두사가 붙은 쿠키를 설정할 수 있는 방법이 제시되었습니다. 예를 들어, 파서를 속이기 위해 시작 부분이나 끝 부분에 "="를 추가하는 것입니다:

또는 PHP에서는 쿠키 이름의 시작 부분에 다른 문자를 추가하여 밑줄 문자로 대체되도록 하여 __HOST- 쿠키를 덮어쓸 수 있었습니다:

Cookies Attacks

사용자 정의 쿠키에 민감한 데이터가 포함되어 있는 경우 이를 확인하세요 (특히 CTF를 진행 중인 경우), 취약할 수 있습니다.

Decoding and Manipulating Cookies

쿠키에 포함된 민감한 데이터는 항상 면밀히 검토해야 합니다. Base64 또는 유사한 형식으로 인코딩된 쿠키는 종종 디코딩할 수 있습니다. 이 취약점은 공격자가 쿠키의 내용을 변경하고 수정된 데이터를 쿠키에 다시 인코딩하여 다른 사용자를 가장할 수 있게 합니다.

Session Hijacking

이 공격은 사용자의 쿠키를 훔쳐 애플리케이션 내에서 해당 계정에 무단으로 접근하는 것입니다. 공격자는 훔친 쿠키를 사용하여 합법적인 사용자를 가장할 수 있습니다.

Session Fixation

이 시나리오에서 공격자는 피해자가 특정 쿠키를 사용하여 로그인하도록 속입니다. 애플리케이션이 로그인 시 새로운 쿠키를 할당하지 않으면, 원래 쿠키를 가진 공격자는 피해자를 가장할 수 있습니다. 이 기술은 피해자가 공격자가 제공한 쿠키로 로그인하는 데 의존합니다.

하위 도메인에서 XSS를 발견했거나 하위 도메인을 제어하는 경우, 읽어보세요:

Cookie Tossing

Session Donation

여기서 공격자는 피해자가 공격자의 세션 쿠키를 사용하도록 설득합니다. 피해자는 자신의 계정에 로그인했다고 믿고 공격자의 계정에서 행동을 수행하게 됩니다.

하위 도메인에서 XSS를 발견했거나 하위 도메인을 제어하는 경우, 읽어보세요:

Cookie Tossing

이전 링크를 클릭하여 JWT의 가능한 결함을 설명하는 페이지에 접근하세요.

쿠키에서 사용되는 JSON Web Tokens (JWT)도 취약점을 가질 수 있습니다. 잠재적인 결함과 이를 악용하는 방법에 대한 심층 정보를 얻으려면 JWT 해킹에 대한 링크된 문서를 참조하는 것이 좋습니다.

Cross-Site Request Forgery (CSRF)

이 공격은 로그인된 사용자가 현재 인증된 웹 애플리케이션에서 원하지 않는 작업을 수행하도록 강요합니다. 공격자는 취약한 사이트에 대해 자동으로 전송되는 쿠키를 악용할 수 있습니다.

Empty Cookies

(자세한 내용은 원본 연구를 참조하세요) 브라우저는 이름이 없는 쿠키를 생성하는 것을 허용하며, 이는 JavaScript를 통해 다음과 같이 시연할 수 있습니다:

document.cookie = "a=v1"
document.cookie = "=test value;" // Setting an empty named cookie
document.cookie = "b=v2"

전송된 쿠키 헤더의 결과는 a=v1; test value; b=v2;입니다. 흥미롭게도, 이는 빈 이름 쿠키가 설정된 경우 쿠키를 조작할 수 있게 하며, 빈 쿠키를 특정 값으로 설정함으로써 다른 쿠키를 제어할 수 있습니다:

function setCookie(name, value) {
document.cookie = `${name}=${value}`;
}

setCookie("", "a=b"); // Setting the empty cookie modifies another cookie's value

이로 인해 브라우저는 모든 웹 서버에서 a라는 이름과 b라는 값의 쿠키로 해석되는 쿠키 헤더를 전송하게 됩니다.

Chrome 버그: 유니코드 대리 코드 포인트 문제

Chrome에서 유니코드 대리 코드 포인트가 설정된 쿠키의 일부인 경우, document.cookie가 손상되어 이후에 빈 문자열을 반환합니다:

document.cookie = "\ud800=meep";

이로 인해 document.cookie가 빈 문자열을 출력하여 영구적인 손상을 나타냅니다.

파싱 문제로 인한 쿠키 스머글링

(자세한 내용은 원본 연구를 참조하십시오) Java(Jetty, TomCat, Undertow) 및 Python(Zope, cherrypy, web.py, aiohttp, bottle, webob)에서 제공하는 여러 웹 서버는 구식 RFC2965 지원으로 인해 쿠키 문자열을 잘못 처리합니다. 이들은 세미콜론이 포함되어 있어도 이중 인용된 쿠키 값을 단일 값으로 읽으며, 이는 일반적으로 키-값 쌍을 구분해야 합니다:

RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";

쿠키 주입 취약점

(자세한 내용은 원본 연구를 참조하세요) 서버가 쿠키를 잘못 파싱하는 경우, 특히 Undertow, Zope 및 Python의 http.cookie.SimpleCookiehttp.cookie.BaseCookie를 사용하는 경우 쿠키 주입 공격의 기회를 제공합니다. 이러한 서버는 새로운 쿠키의 시작을 제대로 구분하지 못하여 공격자가 쿠키를 스푸핑할 수 있게 합니다:

  • Undertow는 세미콜론 없이 인용된 값 바로 뒤에 새로운 쿠키가 올 것으로 기대합니다.

  • Zope는 다음 쿠키를 파싱하기 위해 쉼표를 찾습니다.

  • Python의 쿠키 클래스는 공백 문자에서 파싱을 시작합니다.

이 취약점은 쿠키 기반 CSRF 보호에 의존하는 웹 애플리케이션에서 특히 위험합니다. 공격자가 스푸핑된 CSRF 토큰 쿠키를 주입할 수 있어 보안 조치를 우회할 수 있습니다. 이 문제는 Python의 중복 쿠키 이름 처리로 인해 악화되며, 마지막 발생이 이전 것을 덮어씁니다. 또한 불안전한 컨텍스트에서 __Secure-__Host- 쿠키에 대한 우려를 불러일으키며, 쿠키가 스푸핑에 취약한 백엔드 서버로 전달될 때 권한 우회를 초래할 수 있습니다.

추가 취약한 쿠키 검사

기본 검사

  • 로그인할 때마다 쿠키같은지 확인합니다.

  • 로그아웃하고 같은 쿠키를 사용해 보세요.

  • 두 개의 장치(또는 브라우저)로 같은 계정에 같은 쿠키로 로그인해 보세요.

  • 쿠키에 정보가 있는지 확인하고 수정해 보세요.

  • 거의 같은 사용자 이름으로 여러 계정을 생성해 보고 유사성을 확인하세요.

  • "기억하기" 옵션이 있는지 확인하고 어떻게 작동하는지 살펴보세요. 존재하고 취약할 수 있다면, 다른 쿠키 없이 항상 기억하기 쿠키를 사용하세요.

  • 비밀번호를 변경한 후에도 이전 쿠키가 작동하는지 확인하세요.

고급 쿠키 공격

로그인할 때 쿠키가 동일(또는 거의 동일)하게 유지된다면, 이는 쿠키가 귀하의 계정의 일부 필드(아마도 사용자 이름)와 관련이 있음을 의미합니다. 그러면 다음을 시도할 수 있습니다:

  • 매우 유사한 사용자 이름으로 많은 계정을 생성하고 알고리즘이 어떻게 작동하는지 추측해 보세요.

  • 사용자 이름을 브루트포스해 보세요. 쿠키가 사용자 이름에 대한 인증 방법으로만 저장된다면, 사용자 이름 "Bmin"으로 계정을 생성하고 쿠키의 모든 비트브루트포스할 수 있습니다. 시도할 쿠키 중 하나는 "admin"에 속하는 쿠키가 될 것입니다.

  • 패딩 오라클을 시도해 보세요 (쿠키의 내용을 복호화할 수 있습니다). 패드버스터를 사용하세요.

패딩 오라클 - 패드버스터 예제

padbuster <URL/path/when/successfully/login/with/cookie> <COOKIE> <PAD[8-16]>
# When cookies and regular Base64
padbuster http://web.com/index.php u7bvLewln6PJPSAbMb5pFfnCHSEd6olf 8 -cookies auth=u7bvLewln6PJPSAbMb5pFfnCHSEd6olf

# If Base64 urlsafe or hex-lowercase or hex-uppercase --encoding parameter is needed, for example:
padBuster http://web.com/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2

Padbuster는 여러 번 시도하며 어떤 조건이 오류 조건인지(유효하지 않은 조건) 물어봅니다.

그런 다음 쿠키를 해독하기 시작합니다(몇 분이 걸릴 수 있습니다).

공격이 성공적으로 수행되면, 원하는 문자열을 암호화해 볼 수 있습니다. 예를 들어, encrypt user=administrator를 원한다면.

padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== 8 -cookies thecookie=1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== -plaintext user=administrator

이 실행은 문자열 user=administrator가 포함된 쿠키를 올바르게 암호화하고 인코딩합니다.

CBC-MAC

쿠키에 어떤 값이 있을 수 있고 CBC를 사용하여 서명될 수 있습니다. 그러면 값의 무결성은 동일한 값을 사용하여 CBC로 생성된 서명입니다. IV로 널 벡터를 사용하는 것이 권장되므로, 이러한 유형의 무결성 검사는 취약할 수 있습니다.

공격

  1. 사용자 이름 administ의 서명 가져오기 = t

  2. 사용자 이름 rator\x00\x00\x00 XOR t의 서명 가져오기 = t'

  3. 쿠키에 값 administrator+t' 설정하기 (**t'**는 (rator\x00\x00\x00 XOR t) XOR t의 유효한 서명이 됩니다 = rator\x00\x00\x00)

ECB

쿠키가 ECB를 사용하여 암호화된 경우 취약할 수 있습니다. 로그인할 때 수신하는 쿠키는 항상 동일해야 합니다.

탐지 및 공격 방법:

거의 동일한 데이터(사용자 이름, 비밀번호, 이메일 등)를 가진 2명의 사용자를 생성하고 주어진 쿠키 내에서 어떤 패턴을 발견하려고 시도합니다.

예를 들어 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"라는 사용자를 생성하고 쿠키에서 패턴이 있는지 확인합니다(ECB는 동일한 키로 모든 블록을 암호화하므로 사용자 이름이 암호화되면 동일한 암호화된 바이트가 나타날 수 있습니다).

사용된 블록의 크기로 패턴이 있어야 합니다. 따라서 "a"의 암호화된 묶음이 어떻게 되어 있는지 알면 사용자 이름을 생성할 수 있습니다: "a"*(블록의 크기)+"admin". 그런 다음 쿠키에서 "a"의 블록 암호화 패턴을 삭제할 수 있습니다. 그러면 사용자 이름 "admin"의 쿠키를 얻게 됩니다.

References

Support HackTricks

Last updated