power-girl0-0

SQL 인젝션(GET/Search) 본문

웹해킹/Bee-Box

SQL 인젝션(GET/Search)

power-girl0-0 2020. 12. 15. 15:56
728x90

SQL 인젝션이란?

사용자가 입력값을 서버에서 검증하지 않고 데이터베이스 쿼리 일부분으로 인식하여 데이터베이스의 정보가 노출되거나 인증이 우회되는 취약점

- 해당 공격은 사용자가 데이터를 입력할 수 있는 곳 어디에서든 발생가능하다.

- SQL쿼리를 변수에 입력하여 데이터베이스 정보를 획득하거나 시스템 내부를 파악하는 공격이다.

 

1. SQL Injection (GET/Search)를 선택합니다.

그림 1-1. 취약점 페이지 선택
그림 1-2. 취약한 페이지

2. 검색창에 작은따옴표(')를 입력하여 SQL 인젝션이 가능한지 알아본다.

('sqli_1.php' 페이지는 영화 제목을 검색하고 데이터베이스에서 조회한 결과를 보여주는 페이지이다.)

그림 2-1. SQL 에러 메시지 출력

입력결과 SQL 오류 메시지를 출력하는 것을 확인할 수 있다.

(SQL 인젝션 취약점이 존재할 경우 SQL 오류 메시지를 출력한다.)

 

 

작은따옴표는 데이터베이스에서 문자 데이터를 구분하는 것으로 입력창에 '를 입력시 다음과 같이 문법 오류가 발생하는 것을 알수 있다.

SELECT * FROM movies WHERE title LIKE  ' ' '

 

아래 표의 쿼리를 활용하여 어떤 주석문자를 사용하였는지 확인한다.

' or 1=1--  쿼리 결과를 항상 참으로 만들고 기존 코드의 뒷부분을 주석처리한다.
' or 1=1#

 

그림 2-2.  ' or 1=1--  결과
그림 2-3.  ' or 1=1#  결과

입력해본 결과 두번째 쿼리에서 영화자료가 출력됨을 보아 주석문자는 #을 사용하는 것을 알 수 있다.

 

3. 컬럼 수가 몇개인지 확인한다.

기존 쿼리가 있어서 SQL 인젝션으로 데이터베이스의 내용을 파악하려면 둘 이상의 SELECT 문을 결합하는 UNION 구문이 필요하다. 따라서, UNION SELECT 문을 사용하여 두 질의의 결과를 하나로 반환한다.

' UNION SELECT ALL 1#

UNION SELECT문을 사용하려면 이전 쿼리문과 컬럼 수가 일치해야 하는 조건이 있다. 해당 조건을 활용하면 컬럼 수의 개수를 확인할 수 있다.

그림 3-1. 컬럼 개수가 일치하지 않을 경우

컬럼을 하나씩 늘려 입력한 결과 'UNION SELECT ALL 1,2,3,4,5,6,7#쿼리문에서 영화목록이 출력된 것을 보아 컬럼 수가 7개 인 것을 확인할 수 있다. 

그림 3-2. 컬럼 수가 일치한 경우

 

4. MySQL버전을 확인한다.

MySQL버전이 5.0이상일 경우 이전 버전과 쿼리가 달라지므로 MySQL버전을 확인해야한다.

본 글은 확인을 위해 시스템 함수인 @@version 명령어를 활용하여 쿼리를 입력하였다.

'UNION SELECT ALL 1, @@version, 3,4,5,6,7#

그림 4-1. mysql버전확인

쿼리 입력 결과 MySQL버전이 5.0이상인 것을 확인할 수 있다.

 

5. 데이터 서버에 존재하는 테이블 명을 출력한다.

해당 서버는 MySQL버전이 5.0이상이므로 information_schema를 사용하여 테이블 명을 확인한다.

'UNION SELECT ALL 1, table_name, 3,4,5,6,7 from information_schema.tables;

그림 5-1. 모든 테이블명 출력

해당 명령어를 사용한 결과 데이터베이스에 속한 모든 테이블명을 출력할 수 있다.

 

6. users테이블의 컬럼이름을 확인해본다.

5번에 출력된 테이블 명 중 user테이블이 있는 것을 보아 사용자의 계정 정보가 들어있다고 추측할 수 있다.

따라서, where절을 활용하여 users테이블 정보만 출력하게 조건을 지정하여 쿼리를 이력해보았다.

' UNION SELECT ALL 1,column_name,3,4,5,6,7 from information_schema.columns where table_name='users'#

그림 6-1. users테이블의 컬럼

쿼리 결과 users테이블의 컬럼 명들이 출력된 것을 확인할 수 있다.

 

7. users테이블에 들은 계정을 확인할 수 있다.

6번에서 확인한 결과 컬럼 명에 id, login, password 등이 있는 것을 확인할 수 있다. 해당 컬럼 명은 계정정보와 관련이 있는 것으로 예상할 수 있다. 따라서, 컬럼의 내용을 확인해보았다.

UNION SELECT ALL 1, concat(id,login), password, email, secret, 6, 7 from users#

확인하고자 하는 컬럼 수 가 많을 경우 concat함수를 사용하여 여러 컬럼 내용을 확인할 수 있다.

 

그림 7-1. users테이블에 있는 계정

확인 결과, id컬럼은 회원 순서, login은 아이디, password컬럼은 비밀번호 해시값이 저장되어 있는 것을 확인할 수 있었다.

 

 

대응방안

작은따옴표(')를 입력하여도 오류 메시지가 출력되지 않으면 SQL인젝션은 불가능하다.

sqli_1.php 페이지의 소스코드를 확인해 보면 난이도 하와 달리 레벨에서는 sqli_check함수로 이동하는 것을 확인할 수 있다. 

 

[그림 8-1]은 security_level에 대한 설정소스이다.

그림 8-1. level을 알려주는 소스

 

[그림 8-2]는 레벨에 맞춰 data에 대해 우회하도록 설정해둔 소스이다.

그림 8-2. 난이도에 따라 우회하는 소스

가장 높은 high레벨이 우회하고 있는 sqli_check_2함수가 정의되있는 소스를 확인한다. (functions_external.php)

그림 8-3. sqli_check_2함수

정의된 함수를 확인해본 결과, mysql_real_escape_string함수를 사용하여 입력 데이터를 우회한다.

mysql_real_escape_string함수는 사용자의 입력값에 SQL문법에서 사용하는 특수문자가 있을 경우 백슬레시를 붙여 입력 데이터를 SQL문법으로 인식하지 않게 방어한다.

여기서 우회 문자는 'NULL, \n, \r, \, ', ", ^Z' 이므로 작은따옴표를 입력해도 백슬래시가 붙어 SQL쿼리로 인식되지 않는다.

 

 

728x90
Comments