눈사람의 해킹공부

[인증 우회] SQL 인젝션 공격 방법에 대하여 본문

웹/웹 해킹

[인증 우회] SQL 인젝션 공격 방법에 대하여

5n0wman 2023. 11. 27. 23:30

웹 애플리케이션에 대한 보안 공격은 다양한 형태로 나타납니다. 그 중에서도 SQL 인젝션은 데이터베이스에 직접적인 명령을 주입하여 인증을 우회하거나 데이터를 무단으로 조회하는 공격 기법입니다. 이 포스트에서는 SQL 인젝션의 여러 사례와 함께 이를 방지하기 위한 기본적인 전략을 살펴보겠습니다.

SQL 인젝션의 개념

SQL 인젝션은 공격자가 애플리케이션의 입력 필드를 통해 악의적인 SQL 코드를 데이터베이스 시스템에 주입하는 행위입니다. 이 공격은 주로 데이터베이스와 상호 작용하는 웹 폼을 통해 이루어집니다. 공격자는 데이터베이스 쿼리의 일부로 실행될 수 있는 코드를 입력함으로써, 애플리케이션을 속여 원래의 쿼리 구조를 변경하게 만듭니다.

공격 방법 

예를 들어, 서버 측에 준비된 쿼리가 다음과 같다고 설정해봅니다.

select * from member where id='__' and pw='__';

이에 ID 입력란에 1' or '1'='1' # 이렇게 입력해보겠습니다. 완성된 쿼리는 다음과 같을 것입니다.

select * 
from member 
where id='1' OR '1'='1' #'~~;

 

이는 서버 측에 준비된 쿼리에 항상 참인 조건인 '1'='1'을 주입함으로써, 추가 조건문 없이 모든 사용자 정보를 조회할 수 있습니다.

이러한 방식에는 다음과 같은 다른 구문으로도 가능합니다.

  - 1' OR 1=true #
  - id' OR true

SQL 인젝션 체크

SQL 인젝션이 가능한지 여부를 체크하는 것은 보안 감사의 중요한 부분입니다. 이를 위해, 알고있는 계정이 존재하고 아이디와 패스워드가 id/pw라면, 입력 폼에 ' and '1'='1과 같은 구문을 입력하여 애플리케이션이 예상치 못한 방식으로 반응하는지 확인할 수 있습니다. 만약 시스템이 이러한 입력에 취약하다면, SQL 인젝션 공격에 대응하기 위한 보안 조치가 필요합니다.

ID : id' and '1'='1
PW : pw

공격 방법 2

만약 특정 사이트의 로그인 인증 쿼리가 다음과 같다고 설정해보겠습니다.

$sql = "select passwd from member where id='$user_id'"

이런 상황에서는, 위의 방법과 달리 출력되는 passwd 컬럼의 값을 공격자가 로그인 폼에서 입력한 값으로 변조하는 방법이 있습니다.

예를 들어, union 연산자를 이용해 ID 입력폼에 다음과 같이 입력합니다.

x' union select 'admin', '1234

그리고 PW 입력폼에 1234라고 입력하게 되면 쿼리가 실행되어 이러한 결과가 출력됩니다.

 

쿼리에 출력된 비밀번호와 공격자가 입력한 비밀번호가 일치하기 때문에 로그인에 성공합니다.

위 같은 결과가 나오는 까닭은 id가 x인 사용자가 존재하지 않기 때문에 원래 아무 데이터도 출력되지 않아야 하지만 select를 사용할 때 컬럼 부분에 문자열을 넣으면 입력한 문자열이 그대로 출력된다는 점을 이용하여 union select를 삽입해서 'admin', '1234' 라는 결과를 출도출해냅니다.

 

해당 서버 데이터베이스 테이블에 컬럼이 id와 passwd 2개 밖에 없었기 때문에 원하는 결과를 출력할 수 있었지만, 원래 union select 구문을 사용한 sql 인젝션을 사용하려면 서버 데이터베이스와 컬럼의 개수를 맞춰줘야합니다.

컬럼 개수는 order by절을 이용해 알아낼 수 있습니다.

order by 를 이용한 컬럼 수 알아내기

ORDER BY 구문은 숫자를 넣어서 정렬 할 수 있습니다.

숫자는 해당 순서의 컬럼을 뜻하며 그 순서의 컬럼으로 정렬합니다. 그래서 컬럼의 개수보다 높은 숫자를 넣으면 오류가 발생합니다.

예를 들어, 컬럼의 수가 7 개일 경우 (경우의 수를 줄여가며 탐색해보겠습니다.)

  • order by 3 # (에러 X, 컬럼의 수가 3 이거나 3 보다 큼을 의미합니다.)
  • order by 10 # (에러 발생, 컬럼의 수가 10보다 작습니다.)
  • order by 5 # (에러 X, 컬럼의 수가 5 이거나 5 보다는 크지만 15 보단 작습니다.)
  • order by 7 # (에러 X, 컬럼의 수가 7 이거나 7 보다는 크지만 10 보단 작습니다.)
  • order by 8 # (에러 발생, 컬럼의 수는 7개 입니다.)

방어 전략

SQL 인젝션으로부터 웹 애플리케이션을 보호하기 위한 방법은 여러 가지가 있습니다.

1. 입력값 검증

사용자로부터 받은 모든 입력값에 대한 검증은 기본적이면서도 중요한 방어 수단입니다. 특수 문자, SQL 키워드 등을 필터링하여 SQL 인젝션 공격을 차단할 수 있습니다.

2. 파라미터화된 쿼리 사용

쿼리에 사용자 입력을 직접 삽입하는 대신, 파라미터화된 쿼리(prepared statements)를 사용하면 데이터베이스가 쿼리의 코드와 사용자 데이터를 명확하게 구분합니다.

3. ORM 사용

객체 관계 매핑(Object-Relational Mapping, ORM) 프레임워크는 SQL 인젝션 공격에 대한 내장된 방어 기능을 제공합니다. ORM을 사용하면 개발자는 SQL 코드를 직접 작성하는 대신, 객체의 속성과 메서드를 통해 데이터베이스와 상호작용하게 됩니다.

4. 데이터베이스 사용자 권한 제한

데이터베이스의 사용자 권한을 최소화하면, SQL 인젝션 공격을 통해 획득할 수 있는 권한도 제한됩니다. 예를 들어, 웹 애플리케이션의 데이터베이스 계정은 데이터 조회에 필요한 최소한의 권한만 가져야 합니다.

5. 오류 메시지 관리

애플리케이션의 오류 메시지가 데이터베이스 구조나 내부 정보를 노출하지 않도록 관리하는 것도 중요합니다. 자세한 오류 메시지는 공격자에게 유용한 힌트를 제공할 수 있습니다.


 

 

SQL 인젝션은 웹 애플리케이션의 보안을 위협하는 심각한 공격 방법입니다. 개발자와 보안 전문가는 항상 입력값 검증, 파라미터화된 쿼리, ORM 사용, 데이터베이스 사용자 권한 제한, 그리고 오류 메시지의 관리를 통해 이러한 위협으로부터 시스템을 방어해야 합니다. 보안은 결코 등한시될 수 없는 웹 개발의 핵심 요소입니다.

Happy coding! 🚀