$password = md5('red_dragon_bc36');공개
green_dragon이랑 이미지가 비슷하길래 문제해석도 비슷할 줄 알았지만 아니였음.
문제 이름이 비슷하다고 문제 풀이 방법도 비슷할거라는 틀에 박혀서 상당히 애먹었다.
거의 다 가르쳐준거 같지만 힌트를 받아서 문제를 해결했다.
소스 코드 분석
<?php |
id는 7자를 초과할 수 없다. 7자로 어떻게 변조할 수 있을지 생각해보아야 한다.
no는 is_numeric필터링을 하고 있다. is_numeric 취약점이 있는지 확인하자
addslashes를 통해 pw값을 검증한다 blind sql일 확률이 높다. 하지만 no엔 잘해봤자 문자열 밖에 안 들어간다. blind sql이 어떻게 가능할까?
풀이
7자리엔 무엇이 들어갈지 아직 감이 안잡히니 is_numeric 취약점이 있나 확인해보자. 구글링을 해서 나오겠지만
is_numberic은 단순 정수 외에도 234.23등의 실수 1e+3등의 지수 0x3444 같은 16진수를 허용한다.
그리고 헥스값은 mysql에서 알아서 문자열로 변환시켜준다.
query : select id from prob_red_dragon where id='' and no=0x0111
no 파라미터에 0x0111 요청했을 때 출력하는 쿼리의 no가 1이 아닌 0x0111로 나오는 것을 확인 할 수 있다.
no에 원하는 문자열을 삽입할 수 있다. 사실 green_dragon 때처럼 hex로 쿼리를 만들어 푸는 것인줄 알고 이런 저런 노력을 다 해봤지만
그 문제 처럼 쿼리를 두번 거쳐서 헥스를 알아서 decode 시켜주질 않아서 사실 상 불가능하다.
no는 정수형 컬럼인데 no에서 아무리 헥스로 문자열로 우회시켜봤자 소용이 없다. no에서 나가야한다.
LOS dragon 문제에서 사용한 우회 기술을 이용한다,
id 파라미터에 주석문자를 이용하여 주석 문자를 뒤로 한 라인을 전부 주석으로 처리해버린다.
query : select id from prob_red_dragon where id=''#' and no= 0x0111
글자 수 제한이 있으므로 '#' 주석문자를 사용했다. 주석문자를 사용하여 'and no가 주석처리가 되어진다.
no파라미터에는 %0a 를 이용해서 줄띄움을 함으로써 주석처리가 되지 않는다. is_numeric은 검증할 문자가 앞에 있는 공백과 그 대체 문자열(%09,%20,%0a 등)을 검증에 포함시키지 않는다.
그래서 no 파라미터에 %09를 넣어도 필터링에 걸리진 않는다. 해당 문제의 is_numeric 우회 포인트는 헥스값 등을 숫자로 인식한다는 점이 아닌 공백 문자를 인식하지 못하는 점을 알고 있어야 했다. 이 부분을 힌트로 받아내었다.
가져오고 싶은 값은 pw이므로 id 파라미터를 이용해서 pw blind sql injection을 시도한다.
query : select id from prob_red_dragon where id=''||pw=#' and no= 0x0111
id 파라미터의 길이를 7넘기지 않았다. 다만 "'||pw=#"만으로 이미 7자를 다 사용하여 length나 substr,mid 등 blind sql에 일반적으로 사용하던 함수를 이용할 수 없다. 이는 부등호를 이용해서 한자리 씩 값을 알아낼 수 있다.
만약 패스워드가 12345678 일 경우 비교값이 2이면 12345678보다 크고 1이면 12345678보다 값이 작고 할 수 있다.
이런식으로 13은 12345678보다 크고 12는 12345678보다 작다는 식의 blind sql을 계속 해 나가면 패스워드의 값을 알아낼 수 있다.
'wargame > Lord Of SQL Injection' 카테고리의 다른 글
[LOS] ouroboros (0) | 2018.08.09 |
---|---|
[LOS] phantom (0) | 2018.08.09 |
[LOS] frankenstein (0) | 2018.08.09 |
[LOS] blue_dragon (0) | 2018.07.24 |
[LOS] green_dragon (2) | 2018.07.22 |