상세 컨텐츠

본문 제목

CTF - Cascading the Seven Seas: 브라우저 DevTools로 숨겨진 플래그 찾기

보안

by 코드스키 2026. 7. 25. 13:59

본문

웹 CTF에서 화면만 보고 버튼을 누르다 보면 정작 단서는 CSS에 숨어 있는 경우가 있다. “Cascading the Seven Seas”를 보자마자 CSS(Cascading Style Sheets)를 의심했고, Chrome DevTools의 Sources 전체 검색으로 범위를 줄였다. 이 글은 현재 문제의 플래그나 정답을 공개하지 않고, 다른 웹 문제에도 그대로 쓸 수 있는 조사 순서만 정리한다.

웹 CTF에서 CSS 단서를 찾는 Chrome DevTools 조사 흐름
웹 CTF에서 CSS 단서를 찾는 Chrome DevTools 조사 흐름

Elements만 보지 말고 로드된 리소스 전체를 본다

첫 화면의 DOM만 펼쳐보다가 단서가 없으면 “소스에 아무것도 없다”고 착각하기 쉽다. 실제로는 인라인 <style>, 동적으로 추가된 스타일시트, @import로 연결된 파일, 가상 요소의 content 등 여러 층에 문자열이 나뉘어 있을 수 있다.

Chrome DevTools 공식 Search 문서의 전체 리소스 검색 기능
Chrome DevTools 공식 Search 문서의 전체 리소스 검색 기능

Chrome DevTools에서 Ctrl+Shift+F(macOS는 Cmd+Option+F)를 누르면 현재 페이지가 불러온 리소스 전체를 검색한다. 파일 트리를 한 개씩 여는 것보다 빠르다. 처음에는 플래그 접두사 하나만 찾기보다 아래처럼 구조를 드러내는 키워드를 번갈아 본다.

@import
content:
::before
::after
--flag
part
hidden
display: none

문자열이 여러 조각이면 검색 결과의 파일 경로와 줄 번호를 먼저 기록한다. 발견 순서대로 붙이는 게 정답 순서라는 보장은 없기 때문이다.

Sources와 Network의 역할을 나눠 쓴다

Chrome DevTools Sources 패널 공식 안내
Chrome DevTools Sources 패널 공식 안내

Sources는 로드된 파일 내용과 인라인 스크립트·스타일을 읽기 좋다. Network는 어떤 요청이 실제로 나갔는지, 리다이렉트가 있었는지, CSS가 캐시에서 왔는지 확인하는 데 낫다. 스타일 파일이 목록에 없다고 느껴지면 Network에서 CSS 필터를 걸고 새로고침한다. 응답 본문과 Initiator를 함께 보면 어느 문서가 그 파일을 불렀는지 알 수 있다.

가상 요소는 DOM 텍스트와 다르게 보인다

MDN의 ::before 가상 요소 문서
MDN의 ::before 가상 요소 문서

::before::after는 HTML에 텍스트 노드가 없어도 화면에 내용을 그릴 수 있다. Elements에서 선택한 요소의 Styles 또는 Computed를 보면 가상 요소 규칙이 따로 나타난다. JavaScript의 element.textContent만 출력해서는 이 문자열을 놓칠 수 있다.

.ocean::after {
  content: var(--fragment);
  opacity: 0;
  position: absolute;
  left: -9999px;
}
MDN content 속성 문서 — 가상 요소에 생성 콘텐츠를 넣는 방식
MDN content 속성 문서 — 가상 요소에 생성 콘텐츠를 넣는 방식

content는 일반적으로 가상 요소와 함께 쓰인다. 화면에서 투명하거나 뷰포트 밖으로 밀려 있어도 CSS 원문에는 값이 남는다. CSS 변수(--fragment)를 거쳐 값이 들어간다면 변수 정의 위치까지 따라가야 한다.

@import 체인은 Network로 순서를 확인한다

스타일시트 안의 @import가 다른 도메인이나 다음 단계 파일을 부르면 “cascading”이라는 제목 자체가 파일 연결 구조를 암시할 수 있다. 이때 무작정 URL을 추측하지 않고, Network의 요청 순서와 Initiator를 따라간다. 같은 파일이 중복 로드되거나 캐시 때문에 보이지 않으면 Disable cache를 켠 상태로 새로고침하는 것도 도움이 된다.

내가 쓰는 최소 체크리스트

  1. 페이지 소스와 Elements에서 인라인 style/script 확인
  2. 전체 검색으로 접두사·content·@import 검색
  3. Network의 CSS/JS 응답과 Initiator 확인
  4. ::before, ::after, CSS 변수, 숨김 속성 확인
  5. 발견한 조각은 파일·줄·의존 관계와 함께 기록
  6. 문제 답과 플래그는 대회 정책을 확인한 뒤 공개

이 문제에서 가장 크게 남은 건 특정 문자열이 아니라 검색 습관이었다. 파일 하나씩 눈으로 훑기보다 브라우저가 이미 로드한 범위를 먼저 검색하면, CSS와 DOM의 경계를 이용한 문제를 훨씬 빠르게 구조화할 수 있다.

같이 읽기

입력에 따라 응답이 달라지는 웹 문제를 분석한 과정은 Boolean Blind SQLi로 한 글자씩 데이터 뽑아내기에 따로 정리했다.

공식 자료

관련글 더보기