문제를 보자.
sleep과 benchmark를 차단하고 있다. 이 의미는 time based sql injection을 하라는 것 아닐까?
?pw=' or 1#
으로 넣어서 무조건 결과가 True일 때에도 아무런 반응이 없다.
따라서 time based를 이용하는 것이 맞아보인다.
이 문제를 알아보기 위해 Time Based SQL Injection에 대해 공부한 것을 간단히 정리해보자.
* Time Based SQL Injection
- Mysql에서 사용가능한 함수 : sleep(duration), benchmark(횟수, 쿼리)
ex) sleep(5) : 5초동안 지연
benchmark(20000,MD5('rootable')) : MD5('rootable') 을 20000번 실행
- 정상적으로 지연됐다면 반환 값은 0
- 반환된 결과 레코드에 따라 (레코드 수 X duration) 만큼 지연된다.
ex) 쿼리 결과 레코드가 2개라면 sleep(2)했을 때 총 지연시간은 4초
* SQL Injection에 적용
- ?pw=aaa" and sleep(1)-- 일 경우 만약 pw가 aaa라면 1초 지연될 것이고 아니라면 지연이 되지 않을 것이다. 왜냐하면 지연은 결과 레코드에 따라 정해지기 때문
- and 대신 or을 사용하면 항상 지연되기 때문에 pw를 알 수 없다.
음........ 생각을 해봤는데 time based sql injection은 Sleep(), benchmark(), 데이터가 많은 information_schema같은 컬럼을 이용하는 방법이 있는데 문제에서 _를 막기 때문에 사용할 수 없다.
* 참고 - information_schema를 이용한 time based sql injection
그렇다면 다른 방법을 찾아봐야지!
?pw='을 했을 때 에러가 발생하는 것을 알 수 있다.
이는 if(mysql_error()) exit(mysql_error()); 때문인데 이를 이용하여 Error based sql injection으로 방향을 잡아보았다.
결국 풀이를 봤다....ㅠㅠ
일단 방향은 Error based인데 Error를 통해 데이터를 추출하는 것이 아니라 blind처럼 참일 때는 에러가 안뜨고, 거짓이면 에러가 뜨는 방식으로 진행해야한다.
그러기 위해 코드는 아래와 같다.
query : select id from prob_iron_golem where id='admin' and pw='' or id='admin' and if(length(pw)>10,2,(select 1 union select 2))#'
먼저 싱글쿼터로 이전 쿼리를 닫아준 뒤 or로 이어주면서 admin의 패스워드 길이를 확인할 수 있는 쿼리이다.
만약, pw가 10보다 크다면 2가 선택되어 에러가 발생하지 않지만 10보다 크지 않다면 select 1 union select 1가 되어 result가 2개가 되어 아래와 같은 에러가 뜬다.
Subquery returns more than 1 row
이제 이것을 이용하여 pw를 찾아보자.
length(pw)>15에서는 에러가 발생되지 않고 length(pw)>16 에서 에러가 발생하였으므로 pw의 길이는 총 16자.
ord(substr(pw,1,1))=33를 통해 pw의 첫번째 자리의 ascii값은 33임을 확인하였다.
그 값은 '!'이다.
반복한 결과 pw의 4번쨰 자리까지 !이고 그 뒤는 null인 것을 확인할 수 있다.
'Solve Problem > LOS' 카테고리의 다른 글
[LOS] 문제풀이 1번 - 10번 (0) | 2019.05.10 |
---|---|
[LOS] 22번 문제 (0) | 2018.03.02 |
[LOS] 20번 문제 (0) | 2018.02.14 |
[LOS] 19번 문제 (0) | 2018.02.11 |
[LOS] 18번 문제 (0) | 2018.02.10 |