SQL Injection (SQL 인젝션) 이란?

반응형

 

 

 

1. SQL injection (SQL 인젝션)

웹을 해킹하는 가장 보편적인 기술 중 하나이다.

웹 페이지의 입력을 통해 SQL 문에 악성 코드를 주입하여 데이터베이스에 접근하는 기법이다.

 

 

참고로 이러한 방식을 알고 있다하여 실제로 사용해서 데이터를 갈취하다간 철컹철컹 할 수 있으니 꼭 실습용 사이트를 이용하자.

 

■ 실습용 사이트

https://demo.testfire.net/index.jsp

 

2. 로그인 폼

로그인 폼에 ID, 비밀번호를 입력하면 입력한 값이 서버로 넘어가고 데이터베이스를 조회하여 맞는 데이터가 있다면 로그인에 성공한다.

로그인 폼

이때 데이터베이스에서 데이터를 조회하기 위해 사용되는 SQL문이 다음과 같다고 가정하자. 

SELECT * FROM member WHERE id='입력 아이디' AND password='입력 패스워드';

 

 

(1) 정상적인 로그인 패턴

아이디에 test1234, 비밀번호에 test1234 를 입력하는 경우 아래와같이 SQL문이 동작한다.

SELECT * FROM member WHERE id='test1234' AND password='test1234';

 

 

 

(2) 비정상적인 로그인 패턴

실습용 사이트(https://demo.testfire.net/index.jsp)에서 확인해보자.

아이디에 test001' , 비밀번호에 test1234 를 입력하면 다음과 같이 SQL문이 동작한다.

SELECT * FROM member WHERE id='test001'' AND password='test1234';

 

이경우, SQL문은 문법적인 오류(syntax error)가 발생한다. id 에 입력되는 값에 따옴표가 2개 들어가게 되어 발생하게 되는 것이다.

이런 에러메시지를 띄워주면, SQL 인젝션 공격에 취약하다고 알려주는 것이다.

SQL문에 쉽게 접근할 수 있다고 알려주는 것이다.

실무에서는 절대! 이렇게 에러메시지를 자세하게 표시해주면 안된다.

 

이를 이용하여 SQL문에 접근할 수 있게되면, 다음과 같은 일을 할 수 있게된다.

  • 강제로 로그인 할 수 있다.
  • 테이블 전체 데이터에 접근할 수 있다. (개인정보가 털린다!)
  • 데이터베이스의 삭제도 가능하다.
  • 어드민(admin)계정에 접근 할 수도 있다.
  • 데이터의 변조도 가능하다.

 

 

3. 방법

 

(1) 1=1 을 이용한 SQL 인젝션

"잘못된" 입력을 방지하는 것이 없는 입력창에서, 사용자는 다음과 같이 "똑똑한" 입력을 할 수 있다.

아이디 입력test001' or 1=1 -- 을 입력해준다.

패스워드는 아무거나 입력해도 된다.

이렇게 입력하면 SQL 문은 다음과 같이 작성될 것이다.

SELECT * FROM member WHERE id='test001' or 1=1 --' AND password='test1234';

 

여기서 or 1=1 은 항상 TRUE 이고 -- 를 이용함으로써 뒤에 따라붙게 될 나머지 부분은 주석으로 만들어버리는 것이다.

(즉, id='test001' 이거나 1=1 항상 true 인 조건으로 member 테이블에서 데이터를 취득한다.)

 

따라서, 위의 SQL 문은 항상 유효하고, member 테이블의 모든 데이터를 반환하게 된다.

 

패스워드도 노출될 수 있고 해당 테이블에 전화번호, 메일주소 등이 있다면 해당 정보도 노출된다.

 

위처럼 로그인을 하면 로그인이 성공된다.

로그인 성공

그런데 로그인 성공 화면을 보면 어드민 유저(Admin User) 로 로그인 된 것을 확인할 수 있다.

이는 위의 SQL문의 결과로 가장 위의 데이터를 취득한 것인데, 데이터베이스 상에서 그 데이터가 어드민 유저인 것이다.

(보통 데이터베이스의 가장 첫번째 데이터는 어드민 유저이거나 개발자가 테스트를 하기위한 테스트 유저일 가능성이 크다.)

 

 

(2) = 을 이용한 SQL 인젝션

"잘못된" 입력을 방지하는 것이 없는 입력창에서, 사용자는 다음과 같이 "똑똑한" 입력을 할 수 있다.

아이디와 비밀번호 입력 ' or ''=' 을 입력해준다.

아이디와 패스워드에 모두 ' or ''=' 입력해주었다.

이렇게 입력하면 SQL 문은 다음과 같이 작성될 것이다.

SELECT * FROM member WHERE id='' or ''='' AND password='' or ''='';

여기서 or ''='' 은 항상 TRUE 이고 패스워드도 같은 방식을 이용함으로써 SQL을 항상 TRUE로 만들어버리는 것이다.

 

따라서, OR 조건으로 인하여 위의 SQL 문은 항상 유효하고, member 테이블의 모든 데이터를 반환하게 된다.

 

위처럼 로그인을 하면 역시 어드민 계정으로 로그인이 성공한다.

 

 

(3) 이를 이용한 SQL 인젝션 공격

"잘못된" 입력을 방지하는 것이 없는 입력창에서, "똑똑한" 사용자들은 이를 이용해서 SQL을 주입할 수 있다.

만약, 검색 입력폼에 다음과 같이 입력하면 어떻게 될까?  

  • 1010; DROP TABLE 테이블이름;  

No를 검색하는 입력폼에 SQL 주입을 시도한다.

이렇게 입력하면 SQL 문은 다음과 같이 작성될 것이다.

SELECT * FROM suppliers WHERE no=1010; DROP TABLE 테이블이름;

 

이렇게하면 테이블이름에 해당하는 테이블이 삭제되어 버릴 위험성을 가진다.

이러한 SQL 인젝션(주입)은 UPDATE 문 실행으로 데이터를 변조시킬수도 있고, 갈취할 수도 있다.

 

 

4. 예방하기, 해결책

 

(1) SQL 쿼리를 작성할 때 매개변수를 사용하는 방식

// 다음과 같은 방식으로 작성하지 말자 (X)
String sql = "SELECT * FROM suppliers WHERE no = " + 유저가 입력한 값;

// 다음과 같이 파라미터를 이용한 쿼리 작성을 이용하자 (O)
String sql = "SELECT * FROM suppliers WHERE no = ? ";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setObject(1, 유저가 입력한 값);

 

 

(2) SQL Injection 으로 자주 쓰이는 코드들을 직접 모두 걸러주는 방식

 

SQL 인젝션으로 자주 사용되는 코드들이 존재한다. 치트시트(Cheat Sheet)라고 하는데, 이를 참고하여 직접 사용하지 못하도록 걸러주는 방식을 사용해도 된다.

 

■ 치트시트(Cheat Sheet) 참고 사이트

https://www.invicti.com/blog/web-security/sql-injection-cheat-sheet/

 

 

(3) ORM 을 이용하는 방식

 

Java 라면 JPA 가 대표적으로 존재한다. 개발자가 SQL을 직접 입력하기보다는 라이브러리가 작성해주는데, 대부분의 인젝션 공격을 예방하는 방식으로 작성해준다. 

 

 

 

5. 정리

 

(1) SQL Injection(인젝션) 이란?

웹 페이지의 입력을 통해 SQL 문에 악성 코드를 주입하여 데이터베이스에 접근하는 기법을 SQL Injection(인젝션) 이라 한다.

 

 

(2) SQL 인젝션의 위험

  • 강제로 로그인 할 수 있다.
  • 테이블 전체 데이터에 접근할 수 있다. (개인정보가 털린다!)
  • 데이터베이스의 삭제도 가능하다.
  • 어드민(admin)계정에 접근 할 수도 있다.
  • 데이터의 변조도 가능하다.

 

 

(3) SQL 인젝션 종류

  • 1=1 을 이용한 SQL 인젝션
  • = 를 이용한 SQL 인젝션

 

 

(4) 예방방법

  • SQL 쿼리를 작성할 때 직접 문자열에 더해주지말고 매개변수를 사용하는 방법
  • SQL Injection 으로 자주 쓰이는 코드들을 직접 모두 걸러주는 방법
  • ORM 을 이용하는 방법
반응형