암호 서명 검증 부적절 (JWT None 알고리즘)

Improper Verification of Cryptographic Signature

설명

JWT 검증 시 verify()의 두 번째 인자에 비밀키/공개키 대신 false, null, undefined, 빈 문자열 같은 false 값을 전달하면 사실상 서명 검증이 비활성화됩니다(일명 None 알고리즘 허용). 이 상태에서는 토큰의 서명이 확인되지 않아 공격자가 임의로 페이로드를 조작하고 서명을 붙이지 않더라도 유효한 토큰처럼 통과시킬 수 있습니다. 결과적으로 관리자 권한 필드를 임의로 넣거나 만료 시간을 제거하는 등으로 인증/인가를 우회할 수 있습니다.

잠재적 영향

  • 인증 우회: 서명이 검증되지 않아 위조 토큰으로 로그인 상태를 가장할 수 있습니다.

  • 권한 상승: 페이로드의 role/admin 값을 임의로 조작해 관리자 권한을 획득할 수 있습니다.

  • 데이터 유출: 보호된 API 엔드포인트에 접근하여 민감 정보를 조회할 수 있습니다.

  • 세션 하이재킹: 합법적 사용자로 가장해 지속적으로 서비스 자원에 접근할 수 있습니다.

해결 방법

  • 항상 유효한 비밀키(secret) 또는 공개키(public key)를 verify()에 전달하세요.

  • 알고리즘 허용 목록을 명시하고 'none'은 절대 허용하지 마세요. 예: { algorithms: ["HS256"] } 또는 { algorithms: ["RS256"] }.

  • 단순 파싱만 필요하면 decode()를 사용하고, 검증이 필요한 경우에는 반드시 verify() + 키를 사용하세요.

  • iss(issuer), aud(audience), exp 만료 등 클레임을 함께 검증하세요.

취약한 코드 및 안전한 코드 예시

취약한 코드

안전한 코드

설명:

  • 취약한 코드: verify()에 빈 문자열 같은 falsy 값을 전달하면 라이브러리가 서명 검증을 수행하지 않을 수 있습니다. 또한 algorithms에 'none'을 포함하면 서명 없는 토큰이 통과할 가능성이 생깁니다. 그 결과 공격자가 페이로드를 임의로 조작한 토큰으로 인증/인가를 우회할 수 있습니다.

  • 안전한 코드: verify() 호출 시 신뢰 가능한 비밀키를 제공하고, 허용할 알고리즘을 명시적으로 제한하여 none을 차단합니다. 추가로 iss, aud 등의 클레임도 검증하고, 검증 실패 시 예외를 처리해 요청을 거부함으로써 위조 토큰 사용을 방지합니다.

참조

Last updated