우선 NewAPI의 첫 화면입니다.
도커에서 실행 후 localhost 주소인 127.0.0.1에 5010 포트로 접속했다.
127.0.0.1:5010
피들러에서 HTTP Respones 헤더를 Raw 형식으로 읽으면 다음 화면이 표시됩니다.
HTTP/1.1 200 OK
date: Thu, 16 Mar 2023 15:15:44 GMT
server: uvicorn
content-length: 88
content-type: application/json{“msg”:”Hello stranger!
!
This is CTF Master Moon. Good Luck!
”,”id”:”guest”,”pw”:”guest”}
Chat GPT에게 물어보세요.
Q:
HTTP/1.1 200 OK
date: Thu, 16 Mar 2023 15:15:44 GMT
server:
uvicorn
content-length: 88
content-type: application/json
A:
성공적인 HTTP 요청을 나타내는 서버의 응답 헤더. 여기에는 응답이 전송된 날짜와 시간, 서버 소프트웨어(이 경우 “uvicorn”), 반환되는 콘텐츠의 길이와 유형이 포함됩니다.
그러나 이 응답에는 컨텐츠 본문이 없으므로 클라이언트는 빈 JSON 오브젝트를 수신합니다.
server가 uvicorn임을 알 수 있습니다.
특별한 것은 보이지 않으므로 uvicorn에 대해 배웁니다.
GPT: Uvicorn은 Python 웹 애플리케이션을 비동기 적으로 실행하도록 설계된 Asynchronous Server Gateway Interface (ASGI) 서버입니다.
Python의 asyncio 라이브러리를 사용하여 여러 요청을 동시에 처리하므로 고성능 웹 애플리케이션에 적합합니다.
Uvicorn은 FastAPI 웹 프레임워크와 매우 호환되며 프로덕션 환경에서 FastAPI 애플리케이션을 실행하는 데 자주 사용됩니다.
FastAPI 웹 프레임워크와 호환된다고 한다.
FastAPI 웹 프레임워크란 무엇입니까? 파이썬으로 API를 구축하기 위한 빠르고 고성능 프레임워크라고 한다.
FastAPI를 검색하여 공식 문서로 이동합니다.
https://fastapi.tiangolo.com/ko/
위 링크의 문서는 API 문서를 볼 수 있는 URL을 보여줍니다.
두 가지가 있습니다.
이것은 다음과 같습니다.
- 127.0.0.1:8000/docs
- 127.0.0.1:8000/redoc
Google 페이지에 적용하면 다음 URL을 확인할 수 있습니다.
- 127.0.0.1:5010/docs
- 127.0.0.1:5010/redoc
첫 페이지를 확인해 봅시다.
127.0.0.1:5010/docs
you have no Permission!
!
라는 메시지가 출력되었다.
권한이 없다는 뜻이다.
우선 다음 페이지도 확인해 봅시다.
127.0.0.1:5010/redoc
뭔가 많은 정보가 포함되어 있습니다.
페이지의 오른쪽을 보면, get 메소드로 무언가 주소가 나타난다.
여기에서 / 는 web root 디렉토리를, /docs 는 현재 연결된 주소의 URN을 포함합니다.
다른 모든 것을 확인합시다.
127.0.0.1:5010/
127.0.0.1:5010/docs
127.0.0.1:5010/loginAction
127.0.0.1:5010/s3cr3t/WDJ11wiao223wWJ24d41jnW5K1Ja7do98AO
위와 같이 4개의 주소를 활용해야 한다고 추측된다.
아마 권한이 없는 것을 보고, 그 후에는 /loginAction으로 로그인을 해야 한다.
/loginAction
요청한 자원에 대해 HTTP 메소드가 허용되지 않는다는 메시지가 표시됩니다.
redoc 문서를 자세히 보면 Condent type과 body로 보이는 부분을 볼 수 있습니다.
주소에는 POST 방식으로 되어 있다.
HTTP 메소드는 허가되지 않고, application/json 형식을 POST 방식으로 송신한다는 의미로 추측된다.
또한 콘텐츠 형식 아래에는 vod 부분으로 추측되는 형식이 포함되어 있습니다.
따라서 HTTP 메서드를 허용된 메서드로 바꿔야 한다고 추측할 수 있습니다.
Fiddler에는 사용자가 HTTP 요청을 변경하고 구성 및 제출할 수 있는 기능이 있습니다.
그것은 바로 composer라는 옵션이다.
피들러의 오른쪽 위에 메뉴를 보면 Composer라는 버튼을 확인할 수 있다.
이것을 클릭하면 아래와 같은 화면이 나옵니다.
여기서 GET/POST 방식을 설정할 수 있고, 주소를 입력할 수 있고, Request Body에 내용을 작성해 HTTP 리퀘스트를 송신할 수 있는 것처럼 보이는 화면이 나타났다.
user_id와 password는 main 페이지에서 본 “guest”를 사용합니다.
Composer
POST
127.0.0.1:5010/loginAction
{
"user_id": "guest",
"password": "guest"
}
다음을 입력한 후 오른쪽 상단 모서리에 있는 실행 버튼을 클릭합니다.
이렇게 하면 왼쪽 창에서 응답 값 페이지를 볼 수 있으며 이를 누르면 다음과 유사한 메시지가 표시됩니다.
{
“user_id”:”guest”,
“password”:”guest”,
“success”:true,
“msg”:”welcome guest!
This is our new service!
”,
“Token”:”eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZ3Vlc3QifQ.JFXLkhEJI6cwZYsIDW6smJjJ5qg18x4GeiFmH
}
토큰 값을 얻었다.
이 토큰은 무엇입니까? Token 부분만 복사하여 GPT에 물어보면 다음과 같은 대답을 얻었다.
GPT: 성공적인 로그인 요청에 응답하여 생성되었을 수 있는 JSON 웹 토큰(JWT). JWT는 당사자간에 JSON 객체로 정보를 전송하는 작고 안전한 방법입니다.
이 특별한 경우 토큰에는 사용자 ID에 대한 정보가 포함되어 인증을 보장하기 위해 개인 키로 서명됩니다.
이 토큰은 서버의 보호된 자원에 액세스하기 위한 후속 요청에서 사용할 수 있습니다.
JSON Web 토큰으로 (JWT)라고 부른다.
JWT 토큰 변경
JWT를 검색하면 공식 사이트에서 디버거를 제공하고 있었다.
디버그를 돌리면 온포인트를 기준으로 3개의 값으로 나뉘었다.
Header: JWT의 토큰 유형 및 서명에 사용되는 알고리즘
페이로드: 전송되는 정보를 포함합니다.
Verify Signature: 서명 확인, 토큰의 진위 확인용
: Header와 Payload는 Base64로 인코딩됩니다.
따라서 Base64로 디코딩하면 결과를 얻을 수 있습니다.
여기서 Payload의 ‘guest’를 ‘admin’으로 변경할 수 있습니다.
JWT 토큰을 확인하는 또 다른 방법은 Burp Suite Extention을 설치하는 것입니다.
버프 스위트가 설치되어 있다고 가정하여 진행합시다.
먼저 버프 스위트를 실행한 후 상단에 Extensions 메뉴에 들어간다.
여기에서 App Store에 들어가 Json Web Token을 검색합니다.
(JSON Web Tokens)라는 확장 프로그램을 설치하기만 하면 됩니다.
설치가 완료되면 상단에 JSON Web Tokens라는 메뉴가 생겼는지 확인할 수 있습니다.
클릭 후 Enter JWT에 위에서 얻은 토큰 값을 입력합니다.
해석된 것을 확인할 수 있다.
jwt.io에서 ‘guest’를 ‘admin’으로 바꾸고 여기에 삽입하면 다음과 같이 적용되었음을 알 수 있습니다.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYWRtaW4ifQ.eIoIhSYmcaKDgn5ADDldZIbE4444NkglSgPrZJAF68Y
이제 변경된 토큰을 다음 주소에 적용해 보겠습니다.
– POST: 127.0.0.1:5010/s3cr3t/WDJ11wiao223wWJ24d41jnW5K1Ja7do98AO
HTTP 요청 방법은 위의 Fiddler Composer 메뉴에서 설명한 것과 동일합니다.
Body 내용은 /redoc 문서에서 가져오고 admin으로 변환되었습니다.
cmd 명령은 어떤 파일이 있는지 확인하기 위해 dir을 사용합니다.
{
“Token”: “eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYWRtaW4ifQ.eIoIhSYmcaKDgn5ADDldZIbE4444NkglSgPrZJAF
“user_id”: “admin”,
“cmd”: “dir”
}
내부 서버 오류가 발생했습니다.
이것은 클라이언트 요청을 처리하는 동안 서버 측 오류를 나타내는 응답 코드입니다.
admin에서 수정하지 않은 Token도 같은 오류가 발생했습니다.
JWT 바이패스 기술
위에서 에러가 나오는 이유는 SIGNATURE(시그니처)값 때문이다.
시그니처 값은 비밀 키가 없으면 올바른 토큰 값을 생성합니다.
> pip install pyjwt
import jwt
# Replace this with your secret key
SECRET_KEY = 'your_secret_key_here'
# Define the payload
payload = {
'user_id': 'admin'
}
# Encode the JWT token
encoded_jwt = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
# Print the generated JWT token
print(f"Generated JWT token: {encoded_jwt}")
위의 코드에서 your_secret_key_here를 Docker main.py 파일의 SECRET 값으로 변경하면 올바른 토큰을 얻을 수 있습니다.
그러나 이를 확인하려면 서버에 액세스해야 합니다.
따라서 JWT 바이패스 기술을 사용해야 합니다.
다음은 Chat GPT가 가르친 JWT 우회 방법입니다.
- JWT 토큰 디코딩:
- JWT 토큰은 헤더, 페이로드, 서명의 세 부분으로 구성되며 마침표로 구분됩니다.
내용을 확인하기 위해 base64 디코딩을 사용하여 각 부분을 디코딩합니다.
- JWT 토큰은 헤더, 페이로드, 서명의 세 부분으로 구성되며 마침표로 구분됩니다.
- 헤더 및 페이로드 분석:
- 해독된 헤더와 페이로드를 검사하여 잠재적인 취약점을 식별합니다.
일반적인 취약점은 약한 서명 알고리즘(“없음”) 또는 잘못 구성된 토큰 처리 로직의 사용을 포함합니다.
- 해독된 헤더와 페이로드를 검사하여 잠재적인 취약점을 식별합니다.
- 헤더 및/또는 페이로드 변경:
- 발견된 취약점을 기반으로 헤더 또는 페이로드를 수정하여 이 취약점을 악용합니다.
예를 들어 토큰이 ‘none’ 알고리즘을 사용하는 경우 헤더의 ‘alg’ 필드를 ‘none’ 으로 설정하여 서명 유효성 검사를 무시할 수 있습니다.
- 발견된 취약점을 기반으로 헤더 또는 페이로드를 수정하여 이 취약점을 악용합니다.
- 변경된 헤더 및 페이로드 재인코딩:
- 변경된 헤더와 페이로드를 Base64로 인코딩하고 마침표 구분 기호로 연결합니다.
- 변경된 헤더와 페이로드를 Base64로 인코딩하고 마침표 구분 기호로 연결합니다.
- 새 서명 만들기(해당되는 경우):
- 새 서명이 필요한 방식으로 헤더 또는 페이로드를 변경한 경우 변경된 토큰에 적절한 서명을 생성합니다.
alg 필드를 none으로 설정하면 서명 부분을 공백으로 두거나 원래 서명을 사용할 수 있습니다.
- 새 서명이 필요한 방식으로 헤더 또는 페이로드를 변경한 경우 변경된 토큰에 적절한 서명을 생성합니다.
- 변경된 JWT 토큰 제출: API 요청에서 변경된 토큰을 사용하여 토큰 검증 프로세스를 성공적으로 우회하는지 확인하십시오.
none 알고리즘이라는 단어가 눈에 띈다.
none 알고리즘은 원래 “HS256″이었던 “alg”를 “none”으로 만드는 알고리즘입니다.
처음
“alg”: “HS256”
none 알고리즘 적용
“alg”: “none”
우회 방법을 배우자. 버프 스위트를 다시 열고 Extension을 설치합니다.
이번에도 json web token으로 검색하여 JSON Web Token Attacker를 Install해준다.
인스톨을 하면, 상부 메뉴 바에 JOSEPH라는 윈도우가 생겼을 것이다.
들어가서 수동을 클릭합니다.
그 후는 전에 「admin」으로 변조한 토큰을 넣어 준다.
Load를 눌러 Signature Exclusion을 선택한 다음 Load를 클릭합니다.
이렇게 하면 다음 Choose Payload라는 이름이 표시되며 여기에서 none 알고리즘을 적용할 수 있습니다.
Update를 누르면 변조된 값을 확인할 수 있습니다.
“Alg”를 네 가지 방법으로 변조하지만 모든 경우를 시도해 보겠습니다.
{
“Token”: “token_value”,
“user_id”: “admin”,
“cmd”: “dir”
}
0x00 none
내부 서버 오류
0x01 None
“__pycache__ docker-entrypoint.sh flag main.py require\n”
0x02 nOne
내부 서버 오류
0x03 NONE
내부 서버 오류
0x01 None으로 성공했다.
dir 명령으로 다음 값을 얻었습니다.
“__pycache__ docker-entrypoint.sh flag main.py require\n”
이제 flag를 실행하기 위해 cmd=”head flag” 명령을 작성해 보겠습니다.
HTTP/1.1 200 OK
date: Thu, 16 Mar 2023 17:49:44 GMT
server: uvicorn
content-length: 35
content-type: application/json“seKUCTF{H3!
L0_@dm1n_!
Ts_M3_MARIo}”
절대로 실제 사이트에서 허가 없이 시험하지 말라!
!
!
!
출처
none 알고리즘으로 우회하는 방법을 찾는데 아래 영상이 큰 도움이 되었습니다.