문자열이 브라우저 코드가 될 때
PrismCare Help Desk의 공개 지식베이스 검색을 블랙박스 방식으로 점검하세요. 브라우저 개발자 도구나 로컬 프록시로 검색 요청과 렌더링 결과를 관찰하고, 외부 통신이나 데이터 접근 없이 페이지 안에 무해한 검증 표식이 나타나도록 재현하세요. 성공 후에는 추가 동작을 시도하지 마세요.
의뢰 배경
프리즘케어는 고객센터 상담원이 사용하는 도움말 검색을 개편했습니다. 시범 운영 중 한 상담원이 협력사에서 받은 검색 링크를 열자 검색 결과 대신 낯선 화면 요소가 나타났고, 브라우저가 페이지 동작을 차단했다는 경고를 남겼습니다. 상담 화면은 고객 문의를 다루므로, 다음 주 전사 배포 전에 사용자가 전달한 검색어가 상담원 브라우저에서 의도치 않은 동작을 만들 수 있는지 확인해야 합니다.
이번 목표
사용자가 제어하는 검색어가 상담원 브라우저에서 무해한 검증 동작을 일으킬 수 있음을 재현하고 화면·콘솔 증거를 확보하세요.
- 사용자 입력이 놓이는 HTML 문맥에 따라 필요한 인코딩이 달라짐을 이해한다.
- HTML 파서가 문자열을 DOM과 실행 가능한 이벤트로 바꾸는 과정을 관찰한다.
- 출력 인코딩, 안전한 DOM API, CSP가 서로 보완하는 방어임을 설명한다.
학습 노트 · XSS는 서버에서 만들어진 문자열이 브라우저의 코드 문맥으로 들어가 피해자의 권한에서 실행되는 문제입니다.
HTML 본문, 속성, URL, JavaScript 문자열은 서로 다른 파싱 규칙을 사용합니다. 한 문맥에서 안전한 인코딩이 다른 문맥에서는 충분하지 않을 수 있으므로 데이터를 삽입하는 위치를 먼저 알아야 합니다.
innerHTML이나 템플릿 문자열로 입력을 합치면 브라우저는 꺾쇠괄호와 속성을 마크업으로 해석합니다. textContent처럼 텍스트 전용 API를 사용하면 같은 입력이 실행 가능한 DOM으로 바뀌지 않습니다.
XSS를 검증할 때는 외부 통신이나 저장 정보 접근 대신 현재 문서에 식별 가능한 표식을 남기는 무해한 증명을 사용합니다. 목표는 브라우저가 입력을 코드로 해석했다는 사실을 확인하는 것이지 추가 권한을 행사하는 것이 아닙니다.
| 출력 위치 | 취약한 예 | 권장 방식 |
|---|---|---|
| HTML 본문 | element.innerHTML = input | textContent 또는 HTML entity encoding |
| HTML 속성 | value="입력" 직접 결합 | 속성 API와 문맥별 encoding |
| URL | href에 임의 scheme 허용 | 허용 scheme 검사와 URL 파서 |
| JavaScript | script 문자열에 직접 삽입 | 데이터를 JSON으로 전달하고 코드와 분리 |
<!-- 취약한 렌더링 개념 -->
<div>검색 결과: <사용자 입력></div>
<!-- 안전한 렌더링 개념 -->
<script nonce="...">
result.textContent = userInput;
</script>더 깊이 읽기
실습 전후에 공식 문서와 보안 아카데미 자료로 개념을 교차 확인하세요.
막혔을 때만 열기
다음 단서가 필요할 때만 한 단계씩 확인하세요.
힌트 1 · 출력 문맥 확인
검색어에 단순한 HTML 태그를 넣고 결과가 텍스트인지 실제 요소인지 확인하세요.
힌트 2 · 자동으로 발생하는 이벤트
로드에 실패하는 이미지 요소는 브라우저 이벤트를 발생시킬 수 있습니다.
힌트 3 · 무해한 실행 증거
외부 요청이나 저장 정보 접근 없이 현재 페이지의 제목·속성처럼 로컬에서 확인 가능한 표식만 바꾸고, Elements 또는 Console에서 결과를 기록하세요.
선행 의뢰가 잠겨 있습니다
이전 단계를 완료하면 자동으로 의뢰 메일과 실습 환경이 열립니다.