DreamHack_Jukebox_Writeup

HoHk☔️🐁·2026년 2월 11일

Dreamhack

목록 보기
1/1

DreamHack CTF – Jukebox 취약점 분석

출처: DreamHack Wargame – Jukebox
유형: Web / PHP
공개 범위: 반(半) 풀이 + 취약점 로직 분석
플래그, 익스플로잇 코드 미포함


3줄 요약

  1. URL 검증이 허술한 file_get_contents() 사용으로 PHP Stream Wrapper 악용 가능했다
  2. 단순 문자열 필터를 우회할 수 있는 인코딩 계열 필터 체인이 핵심이었다
  3. 결과 포맷(JSON) 제약 조건이 오히려 공격 난이도를 올리는 장치였다

시작하며…

이 문제는 처음 봤을 때 되게 단순해 보였다.
URL 하나 받아서 노래 정보 가져오는 웹앱이다.
근데 이런 문제들, 경험상 절대 단순하지 않다.

회사 포트폴리오로 쓸 거라서,
“어떻게 뚫었냐” 보다는 왜 취약했고, 어떤 구조적 문제가 있었는지에 집중해서 정리했다.


서비스 구조 간단 정리

구성 요소설명
BackendPHP
핵심 함수file_get_contents()
입력값사용자 입력 URL
출력노래 정보(JSON) 파싱 후 렌더링

서버는 사용자가 입력한 URL을 그대로 가져와서,
그 응답이 JSON이면 각 필드를 화면에 출력하는 구조다.


취약점 개념: PHP Stream Wrapper

이게 왜 위험하냐?

PHP에는 Stream Wrapper라는 개념이 있다.
파일, 네트워크, 필터를 전부 URL처럼 다루는 기능이다.

대표적인 예시는 이거다.

Wrapper역할
file://로컬 파일 접근
php://filter스트림 데이터 변형
data://인라인 데이터
http://원격 리소스

문제는 이 서비스가
URL에 http:// 또는 https://만 포함되면 통과시키는 식으로 검증하고 있었다는 점이다.

이 말은 곧,
php://filter 같은 래퍼도 우회적으로 쓸 수 있다는 얘기다.


첫 시도와 막힌 지점

1차 접근

  • 로컬 파일을 읽을 수 있는지 테스트
  • 응답 자체는 서버에서 가져오는 게 맞아 보였다

그런데 문제 발생

  • 특정 문자열이 포함되면 응답이 차단됨
  • 결과가 JSON 형태가 아니면 화면에 출력도 안 됨

정리하면 제약이 이렇다.

제약 조건설명
문자열 필터특정 패턴 포함 시 차단
포맷 강제JSON + 필수 키 7개
출력 위치특정 필드만 렌더링

이때 좀 짜증났다.
단순 LFI 문제가 아니었다.


문제의 핵심 원인

1. 잘못된 URL 검증

  • scheme 전체를 파싱하지 않음
  • 단순 문자열 포함 여부로만 검사
  • Stream Wrapper 개념을 고려 안 함

2. 보안 필터의 한계

  • 문자열 기준 차단
  • 인코딩, 변형, 중간 표현에 취약
  • “의미”가 아니라 “표현”만 막고 있음

3. 출력 로직의 신뢰

  • 서버가 가져온 JSON을 그대로 신뢰
  • 값이 어떻게 만들어졌는지 검증 없음

이 세 개가 합쳐져서 문제가 커졌다.


공격 시나리오 개념 정리 (코드 없음)

전체 흐름은 이렇다.

[사용자 입력]
      |
      v
[file_get_contents()]
      |
      v
[Stream Filter Chain]
      |
      v
[JSON 형태로 재구성]
      |
      v
[프론트엔드 렌더링]

핵심은 데이터를 직접 보여주지 않아도 된다는 점이다.
서버가 “정상 데이터”라고 믿고 화면에 뿌리게 만들면 끝이다.


왜 필터 체인이 중요한가

단일 인코딩은 쉽게 막힌다.
하지만 여러 필터를 체인으로 연결하면 이야기가 달라진다.

필터 계열역할
base64바이너리 안전 인코딩
quoted-printableASCII 우회
iconv문자셋 변환
rot 계열단순 문자열 필터 우회

이 문제는
단순 문자열 차단 + 출력 구조 신뢰 조합의 전형적인 실패 사례다.


추가로 해본 생각

  • 이 구조, 실서비스에서도 종종 본다
  • “외부 API 가져오기” 기능에서 자주 터진다
  • JSON 검증한다고 안전해지는 거 절대 아니다

실무라면 최소한 이건 했어야 한다.

항목이유
scheme 화이트리스트wrapper 차단
allow_url_fopen 제한로컬 파일 접근 차단
응답 내용 검증의미 기반 검증
출력 전 escapeXSS/LFI 연계 차단

핵심 교훈

배운 점설명
문자열 필터는 믿을 게 못 됨인코딩 한 번이면 끝
출력 구조 신뢰는 위험데이터 출처가 중요
PHP Stream Wrapper는 필수 지식웹 보안 기본기

이 문제는 기교보다 개념 싸움이었다.
원리를 알면 풀리고, 모르고 있으면 계속 삽질하게 된다.


마치며

이 문제 풀면서 느낀 건 하나다.
“이거 옛날 기법 아니냐?” 싶어도,
지금도 그대로 죽는 서비스 많다.

포트폴리오용으로는

  • PHP 기본기
  • 웹 입력 검증
  • 필터 우회 사고력

이 세 개를 같이 보여주기 좋은 문제였다.

profile
nyo님 좋아합니다!

0개의 댓글