본문 바로가기

web/Lord of SQLInjection

Lord of SQLInjection - 18번 : nightmare

sql의 implicit type conversion을 이용한 문제이다.

자세한 내용은 아래 두 링크를 참고하길 바란다.

https://learn.microsoft.com/ko-kr/sql/t-sql/data-types/data-type-conversion-database-engine?view=sql-server-ver16

https://learn.microsoft.com/ko-kr/sql/t-sql/data-types/data-type-precedence-transact-sql?view=sql-server-ver16

 

문제 살펴보기

los nightmare 문제

 

문제의 전체 코드는 위와 같다.

필요한 부분만 추출하여 보도록 하자.

 

 

 

 

 

                                           if(preg_match('/prob|_|\.|\(\)|#|-/i'$_GET[pw])) exit("No Hack ~_~");

                                           if(strlen($_GET[pw])>6) exit("No Hack ~_~");

 

pw 파라미터를 통해 값을 전달할 수 있다.

그런데 'prob', '_', '.', '\', '#', '-' 를 모두 사용할 수 없다.

지금까지 사용했던 %23(#)을 사용할 수 없게 되었다.

또한 pw 파라미터로 전달한 값의 길이가 6바이트를 넘으면 안된다.

 

 

 

 

 

                             $query "select id from prob_nightmare where pw=('{$_GET[pw]}') and id!='admin'";

                             ...
                             
$result = @mysqli_fetch_array(mysqli_query($db,$query)); 
                             if(
$result['id']) solve("nightmare");

 

where 문을 참으로 만들면 풀리는 문제라고 한다.

 

 

 

 

 

문제 풀이 과정

# 대신 사용할 수 있는 주석은 다양하게 있다.

한 줄만 주석처리하는 주석 중 # 다음으로 길이가 짧은 ;%00을 사용하면 될 것 같다.

바이트 길이 제한 때문에 문제 풀기가 상당히 까다로웠다.

구글링을 해본 결과 implicit data conversion을 이용하여 문제를 풀 수 있다고 한다.

 

우선 pw=('')을 사용하여 single quote(')와 괄호를 닫아준다. → 2byte 사용

pw=('')는 false 가 되는데, pw=('')=0과 같이 값을 넣어주면 논리자료형과 정수를 비교하게 된다.

이 때, 논리자료형의 우선순위가 더 낮아 정수(0)으로 바뀌게 된다. 0=0은 참이기 때문에,

where 문이 참이 된다. 그 후, ;%00을 통해 뒷 부분을 주석처리하면 된다.

 

만약 설명에서 틀린 부분이 있다면 지적 부탁드립니다.

 

 

 

 

 

nightmare clear

 

페이로드 : ?pw=')=0;%00

 

 

 

 

 

상당히 이름값을 하는 문제였다.

다음 문제를 풀도록 합시다.