"폼에 입력한 텍스트가 다른 사람의 화면에서 스크립트로 실행된다" — 이것이 XSS입니다. 동작 원리와 확실하게 막는 방법을 설명합니다(공격 절차 없음).
세 가지 유형
XSS는 "악성 문자열이 실행에 이르는 방식"으로 나뉩니다.
| 유형 | 심어지는 방식 |
|---|---|
| 저장형(Stored) | 게시물/프로필에 저장되어 그것을 보는 모든 사람에게 실행됨 (가장 위험) |
| 반사형(Reflected) | URL 파라미터가 페이지에 곧장 반사되어 돌아옴. 링크를 클릭하는 누구에게나 실행됨 |
| DOM 기반 | 서버 왕복 없음 — 클라이언트 측 JS가 입력을 안전하지 않게 처리 |
왜 위험한가 (동작 원리)
브라우저는 페이지 안의 어떤 <script> 든 "정당한 코드"로 실행합니다. 공격자의 문자열이 페이지에 HTML로 들어가면, 브라우저는 그것을 진짜 코드와 구별하지 못합니다.
피해는 "그 페이지가 할 수 있는 모든 것"입니다. RCE 가 서버 측의 최악이라면, XSS는 클라이언트(사용자) 측의 최악입니다.
방어: 진짜 해결은 "출력 시 이스케이프"
XSS는 입력이 아니라 출력에서 예방됩니다. 값을 렌더링하는 순간, HTML로 해석될 수 없도록 변환하세요.
출력 시 이스케이프 (가장 중요)
사용자 제공 값을 렌더링할 때 < > & " ' 를 HTML 엔티티로 변환하세요 — 맥락(HTML 본문, 속성, JS, URL)에 맞는 방법으로.
프레임워크의 자동 이스케이프를 끄지 않기
React/Vue/템플릿은 기본으로 자동 이스케이프합니다. 날 HTML 주입(dangerouslySetInnerHTML, v-html)만 피하면 대부분의 XSS를 예방합니다.
CSP로 심층 방어
Content-Security-Policy는 브라우저가 허용하지 않은 스크립트를 차단하게 해, 무언가 빠져나가도 피해를 제한합니다.
쿠키 보호
세션 쿠키에 HttpOnly 를 표시해 JS가 읽지 못하게 하세요. 탈취되더라도 피해 범위가 작아집니다.
본 사이트의 견해: 최선의 방어는 스스로 구멍을 내지 않는 것
현대 프레임워크는 기본이 안전합니다. 대부분의 XSS는 개발자가 "날 HTML을 주입"하려고 일부러 자동 이스케이프를 끄는 순간에 나타납니다. HTML을 정말 허용해야 한다면, 직접 만든 문자열 처리가 아니라 충분히 검증된 정화기를 거치세요. "편의를 위해 안전을 끄는 것"이 가장 큰 위험입니다.
다음으로 읽기
FAQ
QXSS가 일어나면 무슨 일이 생기나요?
공격자의 스크립트가 실제 페이지의 일부로 피해자의 브라우저에서 실행됩니다. 그것은 세션 탈취(가장 로그인), 입력 읽기, 페이지 변조, 또는 다른 동작의 자동 실행을 뜻할 수 있습니다.
QXSS에 대한 가장 효과적인 방어법은 무엇인가요?
출력 시 이스케이프입니다. 사용자 제공 값을 렌더링할 때, HTML로 해석되지 않도록 변환하세요. React/Vue 템플릿은 기본으로 이를 수행하므로, 가장 큰 성과는 그 자동 이스케이프를 끄지 않는 것입니다(dangerouslySetInnerHTML 등을 피하기). 심층 방어로 CSP를 추가하세요.
Q입력 단계에서 정화하면 충분한가요?
대개 아닙니다. 진짜 해결은 출력 맥락별(HTML 본문, 속성, JS, URL) 이스케이프입니다. 입력 필터만으로는 맥락 불일치로 새어 나갑니다. HTML을 꼭 허용해야 할 때만, 신뢰할 수 있는 정화기를 거치세요.