SQL 인젝션과 XSS 차이
내 블로그 검색창을 찔러보다가 둘을 자꾸 헷갈려서 정리한다. 이름이 다 “인젝션”이라 비슷해 보이지만, 입력이 어디서 명령으로 해석되느냐가 완전히 다르다. 한 줄로 줄이면 SQL 인젝션은 서버를 노리고, XSS는 다른 방문자의 브라우저를 노린다.
| SQL 인젝션 | XSS | |
|---|---|---|
| 표적 | 서버의 데이터베이스 | 방문자의 브라우저 |
| 끼어드는 곳 | SQL 쿼리 문자열 | 페이지 HTML / DOM |
| 대표 페이로드 | ' OR 1=1 -- | <script>alert(1)</script> |
| 노리는 것 | 데이터 열람·변조·삭제 | 세션 탈취·화면 변조·피싱 |
| 성립 조건 | 서버 + DB 필요 | 서버 없어도 됨 (정적 사이트도) |
| 1차 방어 | 파라미터 바인딩 | 출력 이스케이프 |
표적이 다르다
SQL 인젝션은 내 입력이 서버 쪽 SQL 문에 끼어드는 공격이다. SELECT * FROM users WHERE id = '입력' 에서 입력이 따옴표를 닫고 조건을 덧붙이면 쿼리 자체가 바뀐다. 그래서 서버와 DB가 있어야만 성립한다.
XSS는 내 입력이 응답 페이지의 HTML에 태그로 끼어드는 공격이다. 실행되는 곳은 서버가 아니라 그 페이지를 보는 다른 사람의 브라우저다. 서버가 없는 정적 사이트에서도 성립할 수 있는 이유가 여기 있다.
피해가 다르다
SQL 인젝션은 데이터가 털린다. 남의 계정 정보를 읽거나, 값을 바꾸거나, 테이블을 지운다. 피해가 서버에 저장된 데이터에 꽂힌다.
XSS는 사용자가 털린다. 피해자의 브라우저에서 스크립트가 돌면서 세션 쿠키를 훔치거나, 화면을 위조해 가짜 로그인을 유도하거나, 피해자 권한으로 요청을 날린다. 서버 데이터가 아니라 그 페이지를 연 사람이 표적이다.
막는 법이 다르다
표적이 다르니 방어도 다르다.
- SQL 인젝션: 입력을 쿼리 문자열에 이어붙이지 않고 파라미터 바인딩(프리페어드 스테이트먼트)으로 분리한다. 입력이 아무리 이상해도 “값”으로만 취급된다.
- XSS: 입력을 화면에 찍을 때 이스케이프하거나
textContent로 넣는다.<를<로 바꿔 태그가 아닌 글자로 만든다. 한 겹 더 두르려면 CSP로 인라인 스크립트 실행을 막는다.
공통점은 하나다. 입력을 절대 명령으로 해석되게 두지 않는다. 쿼리에서는 값으로, 화면에서는 글자로 가둔다.
내 사이트 검색창으로 반사형 XSS를 실제로 찔러본 실습은 반사형 XSS 노트에 따로 정리했다.