교차 사이트 스크립팅

Cross-site scripting

신뢰하지 않는 문자열이 페이지에서 코드로 실행되는 경로를 끊습니다.

···
html
<div class="sd"><div class="sd-head"><strong>XSS</strong><span id="state">live check</span></div><div class="sd-stage"><div class="tile input mono">&lt;script&gt;...&lt;/script&gt;</div><div class="lanes"><div class="tile bad" id="unsafe">HTML → RUN</div><div class="tile good" id="safe">TEXT → SHOW</div></div></div><div class="sd-foot"><span id="caption">checking boundary</span><span>tap to step</span></div></div>
css
.sd{box-sizing:border-box;width:min(94vw,700px);height:min(86vh,318px);padding:clamp(9px,2.3vmin,18px);border:1px solid var(--line);border-radius:14px;background:var(--surface);color:var(--fg);display:flex;flex-direction:column;gap:clamp(6px,1.8vmin,12px);font:600 clamp(12px,2.6vmin,16px)/1.25 var(--font-sans, sans-serif)}.sd *{box-sizing:border-box}.sd-head,.sd-foot{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:1.25em}.sd-head strong{color:var(--accent);letter-spacing:.06em}.sd-head span,.sd-foot{color:var(--muted)}.sd-foot{font-size:clamp(12px,2.4vmin,14px)}.sd-stage{position:relative;flex:1;min-height:0;display:flex;align-items:center;justify-content:center;gap:clamp(6px,2vmin,18px);overflow:hidden}.sd .mono{font-family:ui-monospace,monospace}.sd .tile{border:1px solid var(--line);border-radius:8px;background:var(--bg);padding:clamp(5px,1.5vmin,10px);text-align:center}.sd .good{color:var(--accent);border-color:var(--accent)}.sd .bad{color:var(--accent-3);border-color:var(--accent-3)}.sd .arrow{color:var(--muted);font-size:clamp(15px,4vmin,28px)}.sd .active{background:color-mix(in srgb,var(--accent) 16%,var(--surface));border-color:var(--accent)}.sd .blocked{background:color-mix(in srgb,var(--accent-3) 13%,var(--surface));border-color:var(--accent-3)}.sd-stage{flex-direction:column}.input{max-width:88%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lanes{display:flex;width:min(95%,440px);gap:clamp(6px,2vmin,16px)}.lanes .tile{flex:1;transition:transform .25s,opacity .25s}.lanes .focus{transform:scale(1.06)}
js
let n=0;function advance(){n=1-n;document.getElementById('unsafe').classList.toggle('focus',n===0);document.getElementById('safe').classList.toggle('focus',n===1);document.getElementById('state').textContent=n?'textContent':'innerHTML';document.getElementById('caption').textContent=n?'input stays text':'untrusted markup executes'}advance();setInterval(advance,900);
document.querySelector('.sd').addEventListener('pointerdown',advance);

XSS는 외부 입력이 HTML이나 스크립트로 해석될 때 발생합니다. 댓글처럼 사용자가 넣은 내용을 HTML에 그대로 끼워 넣으면 브라우저가 태그나 이벤트 속성을 실행할 수 있습니다.

데모는 같은 입력을 원시 HTML 경로와 텍스트 경로로 흘려보냅니다. 출력 위치에 맞는 인코딩과 안전한 DOM API를 쓰고, CSP는 피해를 줄이는 추가 방어선으로 둡니다.

언제 쓰나

댓글, 검색어, 프로필처럼 외부 문자열을 웹 페이지에 보여줄 때 확인합니다.

페이지로 열기 ↗