최신 액세스 제어는 JSON 기반 토큰을 기반으로 작동합니다. OAuth 액세스 토큰, OpenID Connect ID 토큰 또는 서명된 API 세션을 검사할 때 일반적으로 다음과 같은 것을 보게 됩니다. JSON 웹 서명(JWS) 구조를 이해해야 합니다. 검색 엔진은 불투명한 문자열을 마술처럼 읽을 수 있는 JSON으로 바꿔주는 것처럼 보이는 'json 웹 서명 디코딩' 도구로 많은 사람들을 보냅니다.
공격 및 방어 보안 엔지니어에게 이는 첫 번째 단계에 불과합니다. JWS를 디코딩하면 토큰이 무엇인지 알 수 있습니다. 클레임해당 주장이 신뢰할 수 있는지, 서명이 올바르게 시행되었는지, 구현이 이미 CVE 데이터베이스에 있는지 여부는 알려주지 않습니다.
이 문서에서는 json 웹 서명 디코딩을 수행할 때 실제로 어떤 일이 발생하는지, JWS 검증과 관련된 미묘한 실수에서 실제 취약점이 어떻게 나타나는지, 자동화된 AI 증강 펜테스트 파이프라인에 맞는 반복 가능한 워크플로우를 구축하는 방법을 안내합니다.

JSON 웹 서명이란 무엇인가요?
JWS 사양에 따르면 JSON 웹 서명은 JSON 기반 구조를 사용하여 디지털 서명 또는 MAC으로 보호되는 임의의 콘텐츠를 나타냅니다. 이는 바이트 시퀀스에 대해 무결성과 신뢰성을 제공하며, 해당 바이트가 무엇을 나타내는지와는 무관합니다. (IETF 데이터트래커)
실제로, 대부분의 경우 해당 바이트 시퀀스는 다음과 같은 JSON 객체입니다. 클레임 - JSON 웹 토큰(JWT)이라고 부르는 것입니다. JWS 자체는 [RFC 7515]에 정의되어 있으며, JWT는 이러한 클레임이 구조화되고 해석되는 방식에 초점을 맞춘 형제 표준에 포함되어 있습니다. (Medium)
익숙한 컴팩트한 형태는 다음과 같습니다:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0Iiwic2NvcGUiOlsicmVhZCIsIndyaXRlIl0sImV4cCI6MTczNDkxMjAwMH0.
ODU5Y...서명-바이트-여기...
개념적으로는 점으로 연결된 세 개의 Base64URL 인코딩된 부분입니다:
| Part | 이름 | 설명 |
|---|---|---|
| 첫 번째 청크 | 헤더 | 알고리즘, 주요 힌트를 설명하는 JSON(kid, jwk, x5u), 토큰 유형 |
| 두 번째 청크 | 페이로드 | 클레임: 주제, 범위, 발행자, 만료일 등 |
| 3번째 청크 | 서명 | 서명 출력 base64url(header) + "." + base64url(payload) |
온라인 도구에서 수행하든 자체 스크립트에서 수행하든 json 웹 서명 디코딩 작업은 처음 두 부분의 Base64URL 인코딩만 반전시키고 JSON을 예쁘게 인쇄합니다. 이 작업은 not 도구가 알려진 키와 제한된 알고리즘 세트로 명시적으로 검증을 수행하지 않는 한 서명이 유효하다는 것을 증명합니다. (developer.pingidentity.com)
json 웹 서명 디코딩 도구의 실제 작동 방식
브라우저나 웹 기반 놀이터에서 사용되는 일반적인 개발자 도구와 같은 대부분의 JWT / JWS 디코더는 동일한 최소한의 파이프라인을 구현합니다:
- 점을 세 개의 세그먼트로 분할합니다.
- 처음 두 세그먼트를 Base64URL로 디코딩합니다.
- 헤더와 페이로드를 JSON으로 구문 분석합니다.
- 인증 키가 제공된 경우 헤더에 광고된 알고리즘을 사용하여 서명을 다시 계산하고 세 번째 세그먼트와 비교합니다. (developer.pingidentity.com)
보안 엔지니어의 관점에서 1~3단계는 오프라인 분석에 충분히 안전한 단계이며, 4단계는 대부분의 취약점이 숨어 있는 단계입니다.
최소한의 파이썬 디코딩 스니펫
다음은 의도적으로 간단한 디코딩 전용 파이썬 스니펫으로, 펜테스트 중에 캡처한 토큰을 살펴볼 때 유용합니다:
base64 가져오기
json 가져오기
def b64url_decode(data: str) -> 바이트:
# JWT 패딩 처리
padding = '=' * (-len(data) % 4)
반환 base64.urlsafe_b64decode(데이터 + 패딩)
def decode_jws(token: str):
header_b64, payload_b64, signature_b64 = token.split('.')
header = json.loads(b64url_decode(header_b64))
payload = json.loads(b64url_decode(payload_b64))
반환 헤더, 페이로드, 서명_b64
jws = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...."
h, p, sig = DECODE_JWS(jws)
print("헤더:", h)
print("페이로드:", p)
이 기능은 절대 는 확인 루틴을 호출하지 않고 디코딩만 수행합니다. 이는 새로운 대상을 선별할 때 암호화 가정 없이 빠르게 검사할 수 있는 기능입니다.
확인이 포함된 Node.js 스니펫
디코딩을 넘어 검증 단계로 넘어가면 모든 세부 사항이 중요해집니다:
"jsonwebtoken"에서 jwt를 임포트합니다;
"fs"에서 fs를 가져옵니다;
const publicKey = fs.readFileSync("public.pem", "utf-8");
function verifyJws(token) {
// 중요: 지원되는 알고리즘을 명시적으로 잠급니다.
return jwt.verify(token, publicKey, {
알고리즘: ["RS256"],
});
}
생략하는 경우 알고리즘 화이트리스트에 추가하고 라이브러리가 신뢰할 수 없는 헤더에서 알고리즘을 추론하도록 하면 여러 JWT CVE가 발생한 조건을 정확히 재생하게 됩니다.
디코딩은 무해하며, 디코딩된 데이터를 신뢰하는 것은 무해하지 않습니다.
인시던트 보고서와 CVE에서 반복적으로 나타나는 패턴은 다음과 같습니다. 디코딩 마치 이미 있는 것처럼 JWT / JWS 데이터 확인됨. JWT 보안 문제에 대한 여러 최신 글에서는 Base64URL 디코딩은 사소한 일이며 토큰의 비밀은 "읽기 어렵다는 것"에서 오는 것이 아니라고 강조합니다. (포트스위거)
세 가지 종류의 반복되는 버그가 눈에 띕니다:
- 'alg' 필드는 진실의 출처로 취급됩니다. 인증 코드가 사용자가 제어하는 헤더에서 사용할 알고리즘을 가져오는 경우 알고리즘 혼동 공격이 발생할 수 있습니다.
- 그리고
없음알고리즘이 실수로 허용됩니다. JWT 표준은 역사적으로 다음을 지원해야 했습니다."none"를 "무결성 보호 없음"을 의미하는 알고리즘으로 사용했습니다. Auth0의 고전적인 분석은 여러 라이브러리가 이 선택을 순진하게 받아들여 서명되지 않은 토큰이 검사를 통과할 수 있도록 허용하는 방법을 보여주었습니다. (Auth0) - 주요 힌트(
kid임베디드jwk,x5u)는 유효성이 검사되지 않습니다. JWS RFC와 테스트 가이드에서는 엄격한 화이트리스트 없이 토큰이 자체 인증 키를 선택하도록 허용하면 공격자가 임의의 공개 키를 밀수하거나 공격자가 통제하는 위치에서 강제로 키를 조회할 수 있다고 강조합니다. (포트스위거)
즉, json 웹 서명 디코딩은 관찰 가능성을 제공합니다. 하지만 신뢰성을 제공하지는 않습니다. 이러한 차이점이 바로 안전한 디버깅 설정과 원격 코드 실행 헤드라인을 구분하는 것입니다.
디코딩과 CVE가 만나는 경우: 구체적인 JWS 장애 모드
디코딩과 검증이 혼용될 때 얼마나 심각한 문제가 발생할 수 있는지 이해하려면 JWS 검증 로직과 관련된 몇 가지 CVE를 살펴볼 필요가 있습니다.
CVE-2015-9235 - HS/RS의 키 혼동 제이슨웹토큰
Node.js에서 제이슨웹토큰 모듈 버전 4.2.2 이전 버전에서는 설계 오류로 인해 비대칭 알고리즘(RS256/ES256 제품군)에서 대칭 알고리즘(HS256)으로 전환하여 서명 확인을 우회할 수 있었습니다. 취약한 코드 경로는 공격자가 HMAC 비밀을 변경할 때 동일한 값(RSA 공개 키)을 재사용했습니다. alg 헤더를 HS256으로 설정합니다. (nvd.nist.gov)
공격자 입장에서는 워크플로우가 간단합니다:
- 원본 토큰을 디코딩하고 헤더를 검사합니다.
- 서버의 공개 키를 추출합니다(예: JWK 엔드포인트 또는 인증서에서).
- 공개 키를 HMAC 비밀로 사용하여 HS256 헤더로 새 토큰을 위조합니다.
- 위조된 토큰을 제시하면 서버가 이를 유효한 것으로 잘못 취급합니다.
여기서 디코딩은 공격자에게 원시 자료(헤더, 알고리즘, 키 위치)를 제공하고 나머지는 검증 로직이 처리합니다.
CVE-2018-1000531 - 수락하는 경우 없음 알고리즘
이 취약점은 라이브러리에서 서명된 토큰을 수락한 사례를 추적했습니다. 없음 알고리즘을 사용하여 서명이 없음에도 불구하고 유효한 것으로 처리합니다. 익스플로잇 패턴은 거의 우스꽝스러울 정도로 간단합니다. "alg": "RS256" 에 "alg": "none"를 클릭하고 서명 부분을 제거한 후 대상 API가 토큰을 수락하는지 확인합니다. (0xn3va.gitbook.io)
CVE-2023-48238 - 알고리즘 혼동으로 인한 json-웹-토큰
그리고 json-웹-토큰 라이브러리가 또 다른 알고리즘 혼동 공격에 취약한 것으로 밝혀졌습니다. 핵심 문제는 인증에 사용된 알고리즘이 토큰 헤더에서 직접 가져온 것이었는데, 당시에는 신뢰할 수 없었습니다. 이 때문에 공격자는 서버 운영자가 적용한다고 생각한 알고리즘보다 더 편리한 알고리즘을 선택할 수 있었습니다. (nvd.nist.gov)
CVE-2024-54150 - C JWT 구현의 혼란
최근에는 cjwt C 라이브러리에서 현재 CVE-2024-54150으로 추적되는 심각한 알고리즘 혼동 결함이 발견되었습니다. 코드 검토 결과, 토큰을 검증할 때 구현이 HMAC 기반 알고리즘과 RSA/EC 알고리즘을 제대로 구분하지 않아 다시 키 혼동의 가능성이 있는 것으로 밝혀졌습니다. (nvd.nist.gov)
이러한 사례는 역사적 호기심이 아니라 2023~2024년에도 JWS의 확인 경로에서 미묘한 실수가 심각한 취약점의 활성 소스로 남아 있음을 보여줍니다.
많은 팀에서 평가 중에 이를 유지하기 위해 다음과 같은 치트 시트를 작성합니다:
| CVE | 근본 원인 | 공격 테마 | 주요 레슨 |
|---|---|---|---|
| 2015-9235 | HS와 RS 키 혼동 | 알고리즘 혼동 | 알고리즘 화이트리스트 적용, 알고리즘별 키 분리 |
| 2018-1000531 | 없음 서명으로 승인됨 | 무효 서명 | 절대 허용하지 않습니다. 없음 프로덕션에서 |
| 2023-48238 | 신뢰할 수 없는 JWT의 알고리즘 | 알고리즘 혼동 | 헤더 무시 alg서버 측 구성만 사용 |
| 2024-54150 | HS와 RS/EC 구분 없음 | 알고리즘 혼동(C) | MAC과 서명을 근본적으로 다른 경로로 취급하기 |
json 웹 서명 디코딩 연습 중에 관찰된 토큰을 이 표에 명시적으로 매핑하면 어떤 플레이북을 시도해야 하는지 빠르게 파악할 수 있습니다.
펜테스터를 위한 실용적인 디코딩 우선 워크플로
JWS에 의존하는 API 또는 SSO 시스템을 평가할 때 체계적인 디코딩 우선 워크플로를 사용하면 사각지대와 잡음이 많은 추측을 모두 피할 수 있습니다.
- 토큰을 캡처하고 카탈로그화합니다. 프록시 또는 테스트 하네스를 사용하여 모든 토큰을 캡처합니다: 권한 부여 헤더, 쿠키, URL 매개변수. 발급자 및 대상별로 그룹화하세요.
- 헤더와 페이로드를 오프라인에서 디코딩합니다. 위의 파이썬 스니펫과 같은 스크립트를 사용하거나
jwt_tool를 사용하여 디코딩만 하시고, 실제 참여에서 민감한 토큰을 온라인 서비스에 의존하지 마세요. (GitHub) - 헤더 매트릭스를 작성합니다. 각 토큰 패밀리에 대해 다음을 기록합니다.
alg,kid의 존재jku/jwk/x5u및 모든 사용자 정의 헤더 필드. 여기에서 임베디드 JWK 및 공격자가 제공한 키에 대한 PortSwigger의 지침을 직접 실행할 수 있습니다. (포트스위거) - 키 관리 패턴을 추론합니다. 헤더 필드와 잘 알려진 엔드포인트(
/.well-known/jwks.json), 키가 어떻게 분배되고 회전되는지 스케치하세요. - 알려진 버그 클래스를 테스트합니다.
- 무효 서명 /
없음변형을 지원하는 경우 라이브러리 또는 스택에서 해당 변형을 지원했습니다. - 알고리즘이 잠겨 있지 않은 경우 HS/RS 키 혼동 시도를 수행합니다.
- 프로브
kid디렉터리 탐색 또는 파일 포함 동작에 대한 처리. - 사양에서 허용하지만 구현에 제약이 없는 경우 임베디드 JWK 삽입을 시도하세요.
- 무효 서명 /
- 그런 다음 전체 익스플로잇 시도로 이동합니다. 이 단계에서는 단순히 블랙박스에 페이로드를 던지는 것이 아니라 무엇을 증명하려는지 정확히 파악해야 합니다.
이 과정에서 json 웹 서명 디코딩은 나머지 공격 방법론에 대한 통합 가시성 계층입니다.

json 웹 서명 디코딩을 AI 기반 펜테스트 파이프라인에 통합(Penligent.ai)
수동 분석은 단일 참여에 적합하지만, 규모에 따라 팀에는 파이프라인에 가까운 무언가가 필요합니다. 다음과 같은 AI 지원 플랫폼은 Penligent.ai 는 정찰 및 익스플로잇 단계에 직접 JSON 웹 서명 디코딩을 포함할 수 있습니다.
일반적인 설정에서는 플랫폼이 브라우저 샌드박스 또는 프록시에서 HTTP 트래픽을 수집하고 후보 토큰을 자동으로 추출한 다음 헤더와 페이로드에서 일괄 JWS 디코딩을 수행합니다. 그런 다음 AI 에이전트는 발행자, 알고리즘, 주요 힌트별로 토큰을 클러스터링하여 예상치 못한 알고리즘 다양성, 이상한 토큰, 이상한 kid 인코딩 또는 비정상적인 클레임 조합을 사용할 수 없습니다.
이 기준선이 구축되면 펜리전트의 공격 엔진은 무효 서명 시도, 알고리즘 혼동 시나리오, 임베디드 JWK 또는 jku 남용 및 알려진 CVE에서 영감을 받은 프로브. 이러한 검사를 사람의 기억에 맡기는 대신, 시스템은 모든 대상에서 반복 가능한 테스트 케이스로 처리하여 결과를 증거 우선 위험 목록과 기계가 읽을 수 있는 보고서로 다시 제공합니다.
내부 'AI 레드팀' 역량을 구축하는 보안 엔지니어의 경우, 이러한 자동화된 파이프라인에 json 웹 서명 디코딩을 연결하는 것은 로우레벨 배관 중 가장 활용도가 높은 부분 중 하나입니다.
강화 체크리스트 및 추가 자료
일상 업무에 JWS / JWT 토큰 발급 또는 확인이 포함되는 경우, 이를 최소한의 기준으로 삼을 수 있습니다:
- 허용되는 알고리즘의 엄격한 서버 측 목록을 적용합니다.
alg정책으로 신뢰할 수 없는 토큰의 사용을 금지합니다. - 비대칭 서명과 HMAC 비밀 사이에는 키를 분리하고, RSA 공개 키를 HMAC 키로 재사용하지 마세요.
- 영구적으로 비활성화
없음를 프로덕션 라이브러리에 추가하고 이를 광고하는 모든 토큰을 거부합니다. - 모든 헤더 필드(
kid,jku,jwk,x5u)를 신뢰할 수 없는 입력으로 간주하고 고정된 키 세트 또는 화이트리스트와 비교하여 유효성을 검사합니다. - JWT 라이브러리를 패치하고, 주기적으로 CVE-2015-9235, CVE-2018-1000531, CVE-2023-48238, CVE-2024-54150과 같은 CVE를 검토하여 스택에 영향을 받는지 확인하세요. (스위스키의 실험실)
- 없음/알고리즘 혼동 시나리오를 명시적으로 실행하는 회귀 테스트를 추가합니다.
더 자세히 알아보려면 이러한 영문 참고자료를 북마크에 추가하고 내부 런북에서 링크해 두는 것이 좋습니다:
- IETF의 핵심 [JSON 웹 서명(JWS) RFC 7515]. (IETF 데이터트래커)
- 웹 보안 테스트 가이드의 [JSON 웹 토큰 테스트] 섹션을 참조하세요. (OWASP 재단)
- 포트스위거의 웹 보안 아카데미에서는 [JWT 공격] 및 [알고리즘 혼동]에 대한 실습을 진행합니다. (포트스위거)
- JSON 웹 토큰 라이브러리의 치명적인 취약점]에 대한 팀 맥린의 고전적인 Auth0 글입니다. (Auth0)
- IETF OAuth 워킹 그룹에서 진화 중인 [JWT 모범 사례] 초안입니다. (IETF)
올바르게 사용하면 json 웹 서명 디코딩은 디버깅 편의성뿐만 아니라 애플리케이션의 인증 패브릭을 체계적으로 이해하고 공격하며 강화하는 방법의 정문과도 같습니다.

