SQL 인젝션 공격이란 무엇인가?
사용자 입력이 어떻게 SQL 명령어가 될까?
본 블로그 작성 글들은, 강의를 목표로 하고 제작되었습니다. 또한 작성된 글의 정보도 틀렸을 수 있으니, 주의해주세요.
웹 사이트가 사용자 입력을 SQL 문장에 그대로 붙이면, 사용자가 데이터가 아니라 SQL 문법을 집어넣을 수 있다. 이 취약점을 SQL Injection(SQL 인젝션)이라고 부른다.
보통 말하는 SQL 공격은 SQL 인젝션을 뜻하는 경우가 많다. 정확히 말하면 SQL을 사용하는 시스템에 대한 공격은 더 넓은 표현이고, 그중 대표적인 입력값 공격이 SQL 인젝션이다.
문자열을 그대로 합치면 생기는 문제
로그인 코드를 다음처럼 만들었다고 해보자.
const sql =
"SELECT * FROM users WHERE name = '" + userName +
"' AND password = '" + password + "'";
정상적인 입력이 들어오면 아래와 같은 SQL이 만들어진다.
SELECT * FROM users
WHERE name = 'rose' AND password = '1234';
하지만 사용자 입력에 따옴표와 SQL 연산자가 들어오면 개발자가 의도한 문장의 구조가 바뀔 수 있다.
' OR 1=1 --
SELECT * FROM users
WHERE name = '' OR 1=1 -- ' AND password = '';
1=1은 항상 참이고, -- 뒤쪽은 주석으로 처리될 수 있다. 데이터로만 취급했어야 할 문자열이 SQL 명령어의 일부가 되어버린 것이다.
어떤 피해가 생기는가?
SQL 인젝션이 가능하다고 해서 항상 같은 피해가 발생하는 것은 아니다. 실행 중인 데이터베이스 종류, 계정 권한, 한 번에 실행할 수 있는 문장의 범위에 따라 결과가 달라진다.
그래도 일반적으로 다음과 같은 문제가 생길 수 있다.
- 로그인 검사를 우회한다.
- 다른 사용자의 개인정보를 읽는다.
- 게시글이나 계정 정보를 변경하거나 삭제한다.
- 오류 메시지를 이용해 데이터베이스 구조를 알아낸다.
- 데이터베이스 계정 권한이 너무 크면 피해 범위가 더 넓어진다.
프론트엔드 검사만으로는 막을 수 없다
브라우저에서 따옴표 입력을 막았으니 안전하다고 생각할 수 있다. 하지만 공격자는 브라우저 화면을 거치지 않고 서버로 HTTP 요청을 직접 보낼 수 있다.
따라서 입력 길이 제한과 화면 검사는 사용성을 위한 보조 수단일 뿐이다. 실제 방어는 SQL을 실행하는 서버에서 해야 한다.
SQL 인젝션의 핵심 원인은 특수문자 하나가 아니다. 사용자 데이터와 SQL 명령어를 문자열 하나로 섞은 것이 근본적인 문제다.