[Webhacking.kr] old-07 (SQL injection 활용문제)

728x90
반응형

1. 서론

본 포스팅 시리즈는 webhacking.kr의 문제 풀이를 하면서 정리한 자료이다.
필자가 풀이한 방법들이기 때문에 완벽하지 않을 수도 있다는 점을 참고 바란다. (지적과 조언은 언제나 환영이다)

이번 문제는 old-7, SQL injection 활용이 필요한 문제이다.

2. 본론

이번 문제를 접속해보면 위와 같은 화면이 나타난다. 처음 접속시에 GET 파라미터 쪽에 "val"라는 항목에 1이 전달되어있다.

이건 이번 문제의 소스코드이다.

우선 코드 상단을 보면, 우리가 처음에 봤던 GET 파라미터 "val"를 $go에 대입하는 걸 확인할 수 있다. 그리고 이 값을 정규식 필터를 통해 특정 문자가 포함될 경우 바로 종료가 되도록 되어있다. 금지 문자는 다음과 같다.

금지문자 2, -, +, from, _, =, \s, *, /

그리고 위 if문을 통과한다면 그 다음은 SQL쿼리를 요청하는 부분이 나온다. 여기서 "mysqli_query()" 함수는 쿼리문이 실패할 경우 false를 리턴하는데, 이때 or die()로 인해 즉시 종료되게 된다.

그리고 이 쿼리문이 정상적으로 실행이 되었 경우, 맨 마지막 쪽에서 쿼리 결과의 첫번째(SELECT문으로 가져온 lv 값으로 추정됨)에 따라 여러 분기로 나귀게 된다. 이때 그 값이 2일 경우 이 문제를 해결할 수 있게 된다.

일단 먼저 생각해볼 수 있는건, lv의 값이 2가 되면 되니까 $go 안에 2를 넣어 실행해보는 것이다. 하지만 문제는 정규식 필터로 인해 직접적인 문자 "2"를 넣는 것은 불가능하다. 그래서 2를 사용하지 않고 2를 표현할 방법이 필요하다. 필자는 이를 "8%3"으로 해결하였다(8을 3으로 나눈 나머지).

그래서 "val"에 "8%3"을 대입하고 요청해보면, 아쉽게도 "query error"가 나타난다. 이 메세지가 나타났다는 건 다행히 현재 쿼리문이 실행이 불가능하진 않다라고 볼 수 있고, 아마 "chall7" 테이블 상에 lv의 값이 2인 행이 없는 것으로 추측된다.

그렇다면 방법은 임의로 lv의 값을 2로 만드는 수 밖에 없다.
이때 사용할 수 있는 방법으론 union이 있다. lv에는 "chall7" 테이블 상에 존재하지 않는 lv의 값을 대입하여 결과값이 없는 상태를 만든다음에 union을 이용하여 "select(8%3)"을 엮어주면 lv의 값으로 2가 넣어지게 될 것이다 (굳이 괄호를 쓰는 이유는 브라우저의 URL 입력창을 통해 SQL injection을 시도하기 때문에 스페이스문자는 URL인코딩으로 값이 바뀔 수 있어서 최대한 스페이스문자를 쓰지 않고 쿼리를 만들기 위함이다).

필자의 경우, 이미 정답을 맞춘 이력이 있기 때문에 "already solved" 메세지가 떳다.

SQL 쿼리를 실행하는 부분에서 랜덤 값 1~5를 통해 5가지 쿼리문을 통해 랜덤하게 실행하도록 되어있는데, 어차피 한번쯤은 1이 나올테니까 위 이미지처럼 injection을 시도하고 정답이 아니라고 하면 새로고침을 연타 하다보면 정답이라고 뜰 것이다.

728x90
반응형