내가 제공하는 사이트에서 다른 사이트를 크롤링하거나 API 요청하려고 할 때 Host나 Referer 같은 헤더 값이나, WMONID, JSESSIONID 같은 세션 쿠키를 가져오고싶을 때가 있다. 하지만 보안상 이유로 브라우저 엔진 차원에서 완전히 차단된다.
Forbidden Header Name
developer.mozilla.org
Forbidden request header - Glossary | MDN
A forbidden request header is an HTTP header name-value pair that cannot be set or modified programmatically in a request. For headers forbidden to be modified in responses, see forbidden response header name.
// 브라우저 자바스크립트 환경
fetch('https://api.example.com/data', {
headers: {
'Host': 'target.com',
'Referer': 'https://trusted-site.com',
'Cookie': 'JSESSIONID=abcdef123456',
},
})
fetch()나 XMLHttpRequest 에서 헤더를 임의로 지정해도 브라우저는 적용하지 않는다. 브라우저가 커널 레벨에서 요청을 조합할 때 이런 헤더들은 원래 페이지의 진짜 값으로 덮어쓴다. 이렇게 수정을 금지한 HTTP 요청 헤더들을 Forbidden Header Name 이라 한다.
Accept-Charset,Accept-EncodingConnection,Keep-AliveContent-Length,Transfer-EncodingCookieDate,Host,Origin,RefererSec-로 시작하는 모든 헤더Proxy-로 시작하는 모든 헤더
이는 웹 보안과 HTTP 통신 무결성을 유지하기 위한 보호 장치다. 중요 헤더를 자유롭게 바꿀 수 있게 되면, CSRF 공격이나 CORS 정책이 무의미해진다. 서버는 요청 헤더의 출처 정보를 신뢰하고 권한을 검증하는데, 클라이언트 스크립트가 변경하면 출처 기반 방어가 무력화된다.
Cookie 의 HttpOnly 플래그
developer.mozilla.org
Using HTTP cookies - HTTP | MDN
A cookie (also known as a web cookie or browser cookie) is a small piece of data a server sends to a user's web browser. The browser may store cookies, create new cookies, modify existing ones, and send them back to the same server with later requests. Cookies enable web applications to store limited amounts of data and remember state information; by default the HTTP protocol is stateless.
Cookie 역시 Forbidden Header Name 이어서 조작이 불가능한데, 서버가 HttpOnly 플래그를 설정하면, document.cookie 를 통해서도 해당 쿠키를 읽거나 쓸 수 없게 된다.
// HttpOnly 플래그가 설정된 JSESSIONID, WMONID 등은 출력되지 않는다
console.log(document.cookie)
이 제약은 XSS가 성공하더라도 사용자의 세션 토큰을 외부 서버로 전송하지 못하도록 차단하는 보안 설계다.
브라우저 확장 프로그램
브라우저 확장 프로그램은 더 높은 권한을 가진다. manifest.json에 cookies 권한과 해당 도메인의 host_permissions를 선언하면, 확장 프로그램의 백그라운드 서비스 워커에서 chrome.cookies API로 HttpOnly 쿠키 값을 읽을 수 있다.
// manifest.json
{
"permissions": ["cookies"],
"host_permissions": ["https://*.example.com/*"]
}
// 확장 프로그램 서비스 워커
chrome.cookies.get({ url: 'https://example.com', name: 'JSESSIONID' }, (cookie) => {
if (cookie) {
console.log('HttpOnly 쿠키 값:', cookie.value)
}
})
브라우저 밖 런타임 사용
Node, Python, Go 등의 런타임 환경은 브라우저 제약이 없으니 패킷을 마음대로 구성할 수 있다. 크롤링이나 자동화 작업에서는 브라우저 밖 런타임을 사용하는 것이 훨씬 수월하다.