power-girl0-0

SQL 인젝션(POST/Search) 본문

웹해킹/Bee-Box

SQL 인젝션(POST/Search)

power-girl0-0 2020. 12. 15. 23:49
728x90

GET방식과 달리 POST방식은 URL에 변수가 나타나지 않는다. 따라서, 이번에는 프락시 도구를 사용하여 변수를 확인하고 sql인젝션을 시도할 예정이다. 해당 글에서는 Burp suit 도구를 사용하였다.

 

1. burp suit를 사용하여 proxy를 켜준다.

(burp suit에 대한 설명은 다 아는 것으로 간주하고 본 글에서는 따로 기재하지 않기로 한다.) 

그림 1-1. burp suite설정
그림 1-2. 프록시 서버

 

2. SQL Injection (POST/Search)를 선택해줍니다.

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

 

 

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

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

그림 3-1. 작은따옴표 입력
그림 3-2. 에러 메시지 출력

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

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

 

 

4. 주석문자를 확인한다.

 

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

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

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

 

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

 

 

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

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

' UNION SELECT ALL 1#

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

 

그림 5-1. 컬럼 개수를 구하기 위한 쿼리문 입력

 

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

 

오류 메시지가 출력되지 않게 컬럼 수를 하나씩 늘려 웹 페이지에서 호출하는 기존 쿼리와 컬럼 수를 맞춘다.

 

그림 5-3. 컬럼 개수예측
그림 5-4. 컬럼 개수가 일치할 경우

 

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

또한 1,6,7번째 컬럼은 페이지에서 확인할 수 없는 것을 확인할 수 있다.

 

 

6. MySQL버전을 확인한다.

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

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

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

그림 6-1. mysql 버전 확인하는 쿼리 입력
그림 6-2. mysql버전확인

 

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

 

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

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

(툴 사용하는 사진은 삭제되었어요ㅠㅠㅠ)

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

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

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

 

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

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

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

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

그림 8-1. users테이블의 컬럼을 알기 위한 쿼리입력
그림 8-2. users테이블의 컬럼

 

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

 

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

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

UNION SELECT ALL 1, id,login, password, secret, 6, 7 from users#

그림 9-1. users테이블 계정 출력하기 위한 쿼리문
그림 9-2. users테이블에 있는 계정

 

 

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

 

10. 알아낸 계정정보를 활용하여 2차공격

해시값으로 변환된 비밀번호를 평문으로 변환하여 사용자 계저을 탈취할 수 있다.

평문으로 변환해주는 존 더 리퍼 라는 도구를 사용한다.

 

사용전, 해시값이 저장될 test.txt라는 텍스트를 만든 후, 비밀번호 해시값을 저장해준다.

그림 10-1. test텍스트파일 생성
그림 10-2. bee의 비밀번호 해시값 입력

 

존더 리퍼의 포맷 옵션을 'sha1' 해시 함수로 설정하고 인자 값에는 해시값이 저장된 텍스트 파일을 입력한다.

존 더 리퍼를 사용한 결과, 해시값의 평문은 'bug'인 것을 확인할 수 있다.

 

대응방안

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

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

 

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

그림 11-1. level을 알려주는 소스
그림 11-2. 데이터를 우회해주는 소스

 

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

그림 11-3. sqli_check_2함수

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

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

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

728x90
Comments