이 장을 읽기 전에
정규화와 인덱스의 SQL, HTTP와 HTTPS의 요청·응답 구조, 인증과 인가의 세션·쿠키 개념을 안다고 가정한다. 이 챕터는 그 지식을 실제로 어떻게 악용할 수 있는지, 그리고 어떻게 막는지를 다룬다.
SQL 인젝션: 사용자 입력이 쿼리의 일부가 될 때
정규화와 인덱스에서 SQL을 문자열로 조합해 실행하는 예를 다뤘다. 만약 이 문자열에 사용자 입력을 그대로 이어 붙이면, 사용자가 SQL 문법 자체를 주입해 원래 의도하지 않은 쿼리를 실행시킬 수 있다.
| |
이 문제를 막는 표준 해법은 **파라미터화 쿼리(Parameterized Query)**다. 사용자 입력을 쿼리 문자열에 직접 끼워 넣지 않고, 데이터베이스 드라이버에 값으로 별도 전달한다 — 드라이버는 이 값을 절대 SQL 문법으로 해석하지 않는다.
| |
XSS: 사용자 입력이 다른 사용자의 페이지에서 실행될 때
**XSS(Cross-Site Scripting)**는 SQL 인젝션과 원리는 비슷하지만 대상이 다르다 — 사용자 입력이 SQL이 아니라 다른 사용자에게 보여지는 HTML/JavaScript의 일부가 될 때 발생한다. 게시판 댓글에 <script> 태그를 입력했는데 이를 그대로 다른 사용자의 브라우저에 렌더링하면, 그 스크립트가 다른 사용자의 브라우저에서 실행된다 — 이 스크립트는 인증과 인가에서 다룬 세션 쿠키를 읽어 공격자 서버로 전송하는 등의 공격을 할 수 있다.
| |
방어책은 사용자 입력을 HTML로 렌더링하기 전에 **이스케이핑(Escaping)**하는 것이다 — <를 <로, >를 >로 바꾸면 브라우저가 이를 태그가 아니라 텍스트 그대로 표시한다. React·Vue 같은 최신 프레임워크는 기본적으로 텍스트 삽입 시 자동 이스케이핑을 적용하지만, dangerouslySetInnerHTML(React)처럼 이 보호를 의도적으로 우회하는 API를 쓸 때는 개발자가 직접 이스케이핑 여부를 책임져야 한다.
언제 자동 이스케이핑을 우회해도 되는가는 그 입력이 사용자가 직접 작성한 텍스트인지, 서비스가 스스로 생성·통제하는 마크업인지로 갈린다. 사용자가 입력한 댓글·프로필 소개처럼 외부에서 온 문자열은 항상 이스케이핑을 거쳐야 한다. 반면 서버가 신뢰할 수 있는 소스(예: 관리자가 CMS에서 작성한 공지사항 HTML, 마크다운을 서버에서 안전하게 변환한 결과)를 렌더링하는 경우에 한해 dangerouslySetInnerHTML 같은 API로 이스케이핑을 우회하는 것이 허용된다 — 판단 기준은 “이 문자열의 출처를 서비스가 통제하는가"이지, 편의성이 아니다.
CSRF: 로그인된 브라우저의 신뢰를 악용할 때
**CSRF(Cross-Site Request Forgery)**는 SQL 인젝션·XSS와 전혀 다른 원리로 작동한다. 공격자는 취약점을 이용해 코드를 주입하는 것이 아니라, 인증과 인가에서 다룬 “쿠키는 요청마다 자동으로 함께 전송된다"는 브라우저의 정상 동작 자체를 악용한다. 사용자가 은행 사이트에 로그인한 상태로 공격자의 악성 페이지를 열면, 그 페이지가 은행 사이트로 몰래 요청을 보낸다 — 브라우저는 이 요청에도 은행 사이트의 쿠키를 자동으로 실어 보내므로, 은행 서버는 이 요청을 실제 로그인한 사용자의 정상 요청으로 착각한다.
| |
sequenceDiagram
participant U as "사용자 브라우저"
participant Evil as "공격자 페이지"
participant Bank as "은행 서버"
U->>Bank: "정상 로그인 (세션 쿠키 발급)"
U->>Evil: "공격자 페이지 열람"
Evil->>U: "숨겨진 송금 폼 자동 제출 스크립트"
U->>Bank: "POST /transfer (은행 쿠키 자동 첨부)"
Bank->>Bank: "쿠키 유효 → 정상 요청으로 오인"
Bank->>U: "송금 처리 완료"
방어책은 CSRF 토큰이다. 서버가 폼을 렌더링할 때 예측 불가능한 무작위 토큰을 함께 내려주고, 실제 요청 제출 시 이 토큰이 함께 오는지 검증한다. 공격자의 페이지는 이 토큰 값을 알 수 없으므로(같은 출처 정책 때문에 은행 사이트의 폼을 직접 읽을 수 없다), 위조된 요청에는 올바른 토큰이 없어 서버가 거부한다.
비교: 세 취약점
| 취약점 | 악용 대상 | 방어책 |
|---|---|---|
| SQL 인젝션 | 데이터베이스 쿼리 | 파라미터화 쿼리 |
| XSS | 다른 사용자의 브라우저 렌더링 | 입력 이스케이핑 |
| CSRF | 브라우저의 자동 쿠키 전송 | CSRF 토큰 |
흔한 오개념
“프런트엔드에서 입력을 검증하면 안전하다” — 프런트엔드 검증은 사용자 경험을 위한 것일 뿐, 공격자는 브라우저를 거치지 않고 서버에 직접 요청을 보낼 수 있다(curl, Postman 등). SQL 인젝션·XSS 방어는 반드시 서버 측(파라미터화 쿼리, 서버 측 이스케이핑)에서 이뤄져야 한다.
“HTTPS를 쓰면 이 세 취약점이 다 막힌다” — HTTP와 HTTPS에서 다룬 HTTPS는 통신 구간의 도청·변조만 막을 뿐, 애플리케이션 코드 자체의 결함(입력을 검증 없이 쿼리나 HTML에 끼워 넣는 것)은 전혀 막지 못한다. 전송 계층 보안과 애플리케이션 계층 취약점은 완전히 다른 문제다.
다른 개념과의 연결
이 세 취약점은 각각 정규화와 인덱스(SQL), HTTP와 HTTPS(렌더링·요청), 인증과 인가(쿠키·세션)에서 다룬 정상 메커니즘이 검증 없이 쓰일 때 무기가 된다는 공통점을 보여준다. 다음 챕터에서는 이 취약점들을 막는 코드 자체를 어떤 구조로 짜야 하는지, 소프트웨어 설계 갈래의 디자인 패턴으로 이어간다.
평가 기준
이 챕터를 읽은 후에는 다음을 할 수 있어야 한다. SQL 인젝션·XSS·CSRF 각각이 어떤 정상 메커니즘을 악용하는지 구분해 설명할 수 있다. 파라미터화 쿼리, 이스케이핑, CSRF 토큰이 각각 어떤 원리로 해당 공격을 막는지 설명할 수 있다. 프런트엔드 검증만으로는 충분하지 않은 이유를 설명할 수 있다.
참고 자료
OWASP Foundation. (2021). OWASP Top 10:2021.
- OWASP: SQL Injection — SQL 인젝션 공격 패턴과 방어 기법 상세
- OWASP: Cross-Site Request Forgery Prevention Cheat Sheet — CSRF 토큰 구현 실무 가이드
![Featured image of post [Computer Terms] 웹 취약점: SQL 인젝션, XSS, CSRF](/post/computerterms/web-vulnerabilities/wordcloud_hu_338884195502b36b.webp)
![[Computer Terms] 샤딩과 복제 (Sharding, Replication)](/post/computerterms/sharding-and-replication/wordcloud_hu_5bdd44ecbdf63dcd.webp)
![[Computer Terms] CAP 정리와 합의 알고리즘 (CAP Theorem, Consensus)](/post/computerterms/cap-theorem-and-consensus/wordcloud_hu_790afda0e1c08607.webp)
![[Computer Terms] 웹 취약점: SQL 인젝션, XSS, CSRF](/post/computerterms/web-vulnerabilities/wordcloud_hu_81b103705ed468c8.webp)
![[Computer Terms] 디자인 패턴 개요 (Design Patterns)](/post/computerterms/design-patterns-overview/wordcloud_hu_24f0125600c9cc49.webp)
![[Computer Terms] 리팩토링과 코드 스멜 (Refactoring, Code Smell)](/post/computerterms/refactoring-and-code-smells/wordcloud_hu_893b2b850bf2415e.webp)
![[Computer Terms] 웹 방화벽 (WAF, Web Application Firewall)](/post/computerterms/web-application-firewalls/wordcloud_hu_8b74d4810f7f3cb2.webp)
![[Computer Terms] 레이트 리미팅 (Rate Limiting)](/post/computerterms/rate-limiting/wordcloud_hu_8a40d34225849cd4.webp)
![[Computer Terms] REST와 GraphQL](/post/computerterms/rest-and-graphql/wordcloud_hu_e0075ba37c402dfa.webp)
![[Computer Terms] 웹소켓과 CORS (WebSocket, CORS)](/post/computerterms/websockets-and-cors/wordcloud_hu_961dca3ff221db15.webp)
![[Computer Terms] 인증과 인가 (Authentication, Authorization)](/post/computerterms/authentication-and-authorization/wordcloud_hu_b34b34781fc1ffcc.webp)