SQL Injection은 어떻게 발생하는가?

SQL Injection은 어떻게 발생하는가?

웹 서비스를 운영하다 보면 반드시 고려해야 할 보안 위협 중 하나가 바로 SQL Injection입니다. 이는 데이터베이스를 사용하는 거의 모든 웹 애플리케이션에서 발생할 수 있는 대표적인 해킹 기법입니다. SQL Injection은 말 그대로 SQL 쿼리에 악의적인 코드를 “주입(Injection)”하는 공격 방식입니다.

먼저 기본 원리부터 이해해보겠습니다. 웹 애플리케이션은 사용자의 입력값을 받아 데이터베이스에 질의를 보냅니다. 예를 들어 로그인 기능을 구현했다고 가정해봅시다. 사용자가 아이디와 비밀번호를 입력하면 서버는 다음과 같은 SQL 쿼리를 실행할 수 있습니다.

SELECT * FROM users WHERE id = ‘입력값’ AND password = ‘입력값’;

이때 서버가 사용자의 입력값을 그대로 문자열로 이어붙여 쿼리를 만든다면 문제가 발생할 수 있습니다. 공격자가 입력값에 SQL 문법을 포함시키면, 원래 의도하지 않은 쿼리가 실행될 수 있기 때문입니다.

예를 들어 공격자가 아이디 입력란에 다음과 같이 입력한다고 가정해봅시다.

‘ OR ‘1’=’1

그러면 실제 실행되는 쿼리는 다음과 같이 됩니다.

SELECT * FROM users WHERE id = ” OR ‘1’=’1′ AND password = ”;

여기서 ‘1’=’1’은 항상 참(true)이기 때문에 조건이 무조건 성립합니다. 그 결과 인증이 우회될 수 있습니다. 이것이 가장 기본적인 SQL Injection 예시입니다.

SQL Injection이 발생하는 근본적인 원인은 사용자 입력값을 검증하지 않고 그대로 SQL 쿼리에 포함시키는 것에 있습니다. 즉, 입력값과 SQL 코드가 구분되지 않는 구조가 문제입니다.

SQL Injection 공격은 단순히 로그인 우회에 그치지 않습니다. 공격자는 데이터베이스에 저장된 민감한 정보를 조회하거나, 데이터를 수정하거나, 삭제할 수도 있습니다. 심지어 데이터베이스 구조 자체를 파괴할 수도 있습니다.

대표적인 공격 유형은 다음과 같습니다.

첫째, 인증 우회 공격입니다. 로그인 기능을 우회해 관리자 권한을 획득하는 방식입니다.

둘째, 데이터 추출 공격입니다. UNION SELECT 같은 구문을 이용해 다른 테이블의 데이터를 조회합니다.

셋째, 블라인드 SQL Injection입니다. 응답에 직접적인 결과가 표시되지 않더라도 참/거짓 조건을 이용해 데이터를 추측하는 방식입니다.

넷째, 에러 기반 공격입니다. 데이터베이스 에러 메시지를 활용해 구조 정보를 파악합니다.

이러한 공격이 가능한 이유는 SQL 문이 문자열로 동적으로 생성되기 때문입니다. 사용자의 입력이 곧 SQL 문장의 일부가 되어버리는 구조가 취약점입니다.

그렇다면 어떻게 방어할 수 있을까요?

가장 중요한 방법은 Prepared Statement(준비된 문장) 또는 Parameterized Query를 사용하는 것입니다. 이는 SQL 문과 입력값을 분리하는 방식입니다. 예를 들어 다음과 같은 구조를 사용합니다.

SELECT * FROM users WHERE id = ? AND password = ?

이 방식에서는 입력값이 SQL 문법으로 해석되지 않고 단순한 데이터로 처리됩니다. 따라서 악성 코드가 주입되어도 실행되지 않습니다.

또한 ORM(Object Relational Mapping) 도구를 사용하는 것도 도움이 됩니다. 대부분의 ORM은 내부적으로 안전한 쿼리 방식을 사용합니다.

추가적으로 입력값 검증(Input Validation)도 중요합니다. 숫자만 입력되어야 하는 곳에는 숫자만 허용하고, 특수문자를 제한하는 방식입니다. 하지만 이는 보조 수단일 뿐, 근본적인 해결책은 아닙니다.

최소 권한 원칙도 중요합니다. 데이터베이스 계정에 불필요한 권한을 주지 않으면 피해를 줄일 수 있습니다. 예를 들어 SELECT만 필요한 계정에 DROP 권한을 주면 안 됩니다.

비유를 들어보면 SQL Injection은 건물 출입구에 방문자 명단을 적는 칸이 있는데, 그 칸에 문 전체를 바꿀 수 있는 열쇠를 넣어버리는 것과 같습니다. 입력값이 단순한 데이터가 아니라 명령어로 실행되기 때문에 위험합니다.

정리하자면 SQL Injection은 사용자 입력값을 이용해 악의적인 SQL 코드를 실행시키는 공격입니다. 입력값과 SQL 문이 분리되지 않았을 때 발생하며, 인증 우회, 데이터 유출, 데이터 삭제 등 심각한 피해를 초래할 수 있습니다. 이를 방지하기 위해서는 반드시 Prepared Statement와 같은 안전한 쿼리 방식을 사용해야 합니다.

웹과 서버를 공부하는 사람이라면 SQL Injection은 반드시 이해해야 할 핵심 보안 개념입니다. 보안은 선택이 아니라 기본입니다.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *