TornadoService

이강현·2026년 4월 19일

HTB Challenge

목록 보기
3/6

Project Structure

웹 GUI 상으로 봤을 때, 각종 Machine Lish가 있고 해당 Machine의 상태를 수정하는 기능과 Report 하는 기능이 있다.
여기서 수정 기능은 localhost에서 보낸 요청만 가능하게 하였고, Report는 제한이 없다.

Code Analysis

Dockerfile

python 3.11 이미지를 기반으로 한다. chromium을 사용하여 봇을 구동시킨다는 것을 유추할 수 있다. flag는 /flag.txt에 있다.

여기서 재밌는 점은 익숙치 않은 파이썬 기반 웹 프레임워크인 Tornado를 사용하여 프로그램을 구동한다.

requirements.txt

tornado 6.4.1 버전에서 CVE-2024-52804같이 DoS를 유발하는 취약점이 있다. 이 문제에서는 사용하지는 않을 거 같다.

main.py

APP은 make_app함수로 생성된다. make_app 함수는 애플리케이션의 기본 설정을 한다. cookie_secret이 랜덤값으로 설정하여 쿠키값 보호를 하는 것을 확인할 수 있다. 또한 여기서 라우팅 설정도 하는 걸 확인할 수 있다.

라우팅핸들러기능
/IndexHandler기본 페이지
/get_tornadosGetTornadosHandler
/update_tornadoUpdateTornadoHandler
/report_tornadoReportTornadoHandler
/loginLoginHandler
/statsProtectedContentHandler
.*NotFoundHandler

여기서 핸들러에 전달되는 인자가 설정될 수 있다. (dict(tornados=TORNADOS)) 이 인자는 해당 핸들러의 initialize 메서드로 전달된다.

ProtectedContentHandler에서 current_user로 쿠키를 확인하는데 쿠키가 없으면 401을 반환한다. 있다면 flag값을 보여준다.

각종 핸들러는 BaseHandler를 상속받고 있다.

BaseHandler

BaseHandler는 CORS 설정을 위해 set_default_headers 메서드를 재정의 하였다. 또한 에러 발생 시 JSON 형태로 반환하도록 설정하였다.

UpdateTornadoHandler

UpdateTornadoHandler는 머신 아이디와 기계 상태를 인자로 받아서 /update_tornado 엔드포인트로 POST 요청을 보낸다.

ReportTornadoHandler

ReportTornadoHandler는 ip 주소를 인자로 받아서 /report_tornado 엔드포인트로 POST 요청을 보낸다.

LoginHandler

LoginHandler는 아이디와 비밀번호를 인자로 받아서 /login 엔드포인트로 POST 요청을 보낸다.

ProtectedContentHandler

ProtectedContentHandler는 쿠키를 확인한다. 쿠키가 없으면 401을 반환한다. 있다면 flag값을 보여준다.

Attack Point

여기서 핵심은 /stats 엔드포인트에 도달하는 것이고, 거기에 필요한 쿠키값 즉 로그인을 성공해야하는 것이다. 이 로그인을 성공하기 위해서는 계정 정보를 알아야하는데, 현재 USERS는 글로벌 변수로 계정은 하드코딩돼있지만, 비밀번호는 랜덤값 32자로 돼있어 유추하기 어렵다.

하지만 여기서 /update_tornado 엔드포인트는 값을 수정하는 기능을 하는데, 여기서 python class pollution을 활용해 USERS에 정의된 비밀번호 값을 우리가 원하는 값으로 바꿀 수 있다. 하지만 여기서 이 엔드포인트는 로컬 호스트로만 요청을 보낼 수 있다.

그래서 우리는 /report_tornado 엔드포인트에서 해커의 ip를 전송하여, /update_tornado 엔드포인트로 우리가 원하는 값을 POST 요청을 보내는 script를 실행시킨다. (CSRF 공격)

여기서 나는 PNA 개념을 몰랐던 상태에서 그저 AI가 추천해준 페이로드인 fetch 함수를 통해 요청을 보내게 했지만 공격 수행이 되지 않았다. 이는 최신 chrome의 강력한 보안 정책인 PNA 떄문이었다.

PNA (Private Network Access)

  • 최신 크롬의 강력한 보안 정책
  • 외부 도메인의 웹페이지에서 로컬 네트워크로 백그라운드 요청 (fetch, axios 등)을 보내면 크롬이 이를 해킹시도로 간주하고 차단
  • form 전송을 통해 PNA를 우회할 수 있다.
  • form 전송은 페이지 전체가 이동하는 Top-level navigation은 PNA의 영향을 받지 않는다.
profile
저는 정보보안전문가가 될 것입니다.

0개의 댓글