본문 바로가기

Wargame(hacking)/LOS

LORD OF SQLINJECTION : nightmare

Write-Up

 

  if(preg_match('/prob|_|\.|\(\)|#|-/i', $_GET[pw])) exit("No Hack ~_~"); 
  if(strlen($_GET[pw])>6) exit("No Hack ~_~"); 
  $query = "select id from prob_nightmare where pw=('{$_GET[pw]}') and id!='admin'"; 
  if($result['id']) solve("nightmare");

 

위의 필터링 조건에서 눈여겨 봐야할 부분은 strlen() 으로 길이를 제한 하고 있다는 점과 주석 기호가 필터링되고 있다는 것이다. 

 

주석 필터링에 대한 우회방법은 아래와 같다. 

 

--(공백) : -- 뒤에 공백이 있어야 주석 처리가 가능하다. 

 

# :  뒤에 공백이 없어도, 주석 처리가 가능하다.  

 

/* */ : /* 와 */ 사이 문자열 주석 처리가 가능하다. 

 

;%00 

 

?pw=%27)=0;%00

 

위 우회 방법 중 ;%00 을 사용하여, 위와 같은 payload 작성 시, 아래와 같은 query가 완성되며, 문제를 해결 할 수 있다.  

 

select id from prob_nightmare where pw=('')=0;') and id!='admin'

 

 

해당 문제를 혼자 힘으로는 풀지 못했는데, 그 이유는 ('')=0 과 같은 query를 생각해내지 못했기 때문이다. 그래서 아래와 같이 실습을 통해 ('')=0 및 auto type cast에 관해서도 알아본다. 

 

실습

 

그림 1

 

위 그림 1은 members 테이블의 속성 정보를 나타낸다. 

 

그림 2

 

select 구문을 통해 members 테이블을 조회해보았고, where 절을 통해 id=0이라는 조건을 추가해 query를 구성해 보았다. 위 그림 1에서 보았다싶이 id 필드(컬럼)의 속성은 varchar 였다. 즉 id 와 0 의 타입이 맞지 않기에 auto type cast가 발생해 0=0 꼴이 되어, members 테이블이 모두 조회된다. 

 

아래에서 관련 경우를 좀 더 살펴본다. 

 

그림 3

 

그림 4

 

그림 5

 

아래 그림 6을 통해 해당 Challenge( nightmare )가 왜 해결됬는지를 확인할 수 있다.

 

('') = 0 : 빈 문자열을 숫자 0으로 강제 변환하여 비교한다. 이는 결과적으로 빈 문자열이 0으로 해석되고, 0=0 으로 true가 반환되기에 해당 문제가 해결될 수 있었다. 

 

그림 6

 

그림 7

 

 

 

 

참고

 

 

https://dev.mysql.com/doc/refman/8.3/en/type-conversion.html

 


https://stackoverflow.com/questions/21762075/mysql-automatically-cast-convert-a-string-to-a-number


 

https://limjunyoung.tistory.com/121