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

728x90
반응형

1. 서론

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

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

2. 본론

이번 문제를 처음 접속하면 이런 화면이 뜬다.
"1, 2, 3"이라는 앵커가 보이고, Password라는 항목으로 Form이 있다. 비밀번호를 입력하는 걸로 봐선 여기에 무언가를 입력해서 submit하면 문제를 해결 할 수 있는 듯 하다.

앵커 "1"을 클릭한 화면
앵커 "2"를 클릭한 화면
앵커 "3"을 클릭한 화면

앵커들을 클릭하면 각각의 화면을 볼 수 있다.
GET 파라미터 "no"의 값이 클릭한 앵커의 숫자로 변하면서 각가의 화면이 보이는데, 특별하게도 "no"가 3일때는 "Secret"과 "column: id,no", "no 3's id is password"라는 문자열이 출력된다.

일단 위 화면들로 우리의 목표는 "no"가 3인 row의 비밀번호를 알아내는 것이라는 걸 알 수 있다.
그리고 webhacking.kr의 이전 문제들과 다르게 소스코드를 제공해주지 않는것으로 봐선 Blind SQL injection을 수행해야할 듯하다.

"no"가 4일때 화면

"no"의 값에 4를 대입하여 보았더니 아무런 문자열이 나타나지 않고 비밀번호를 입력하는 항목만 나타났다. 아마 쿼리문의 실행 결과가 False일 경우 이러한 결과가 나오는 듯하다. Blind SQL injection을 위해 쿼리 실행 결과값을 True, False로 볼 수 있어야 하는데, "no"의 값을 변화시켜서 문자열이 출력되면 True로 판단하고 아니라면 False로 판단하는데 이용하면 될 듯하다.

"no"가 "(1)"일때 화면

"no"에 쿼리 삽입이 가능한지 확인하기 위해 "1"에다가 괄호를 감싸서 넣어봤는데 정상적으로 Apple이 출력됐다.
아마 SELECT id FROM blahblah WHERE no = {GET param "no"} 이러한 형태의 쿼리인 것일 텐데, "no"에 "(1)"을 넣어주었기 때문에 SELECT id FROM blahblah WHERE no = (1)인 형태가 되어  "no"가 "1"일때와 동일한 결과가 나온 것이다.

"no"가 "select"일때 화면

다른 SQL 키워드를 사용하기 위해 "no"의 값을 테스트하는데, 역시나 몇몇 키워드들은 필터링되는듯하다. 하지만 모든 문자가 다 필터링되는 것은 아니니 SQL injection은 충분히 진행 가능할듯하다. 필터링에 걸리지 않는 키워드중 하나로 "like"를 발견했다. "="는 필터링으로 걸러지기 때문에 "=" 대신 "like"를 사용해야 할 듯하다.

그럼 이제 "no"가 "3"인 row내의 id 값의 길이를 찾아보도록 하겠다.

확인해보니 "length"라는 키워드는 사용이 가능했다. "no"가 "3"인 값의 길이를 찾기 이전에 우선 "no"가 "1"인 값의 길이를 테스트삼아 찾아보려고 한다. 위 이미지에서 보면 "no"에 "if(length(id)like(1),1,4)"를 넣었는데 실행결과는 False가 나왔다. SQL에서 "if()" 함수는 첫번재 인자의 값이 True일 경우 두번째 인자의 값을 리턴하고 False일 경우 세번째 인자의 값을 리턴하는데, 쿼리 실행결과가 False가 나왔다는 것은 "no"에 "1"이 아닌 "4"가 들어갔다는 얘기이고 그렇다는건 "length(id)like(1)"는 False라는 것이니 "no"가 "1"인 row 내의 id값의 길이는 1이 아니라는 얘기이다.

이런 방법을 이용한다면 쉽게 "no"가 "3"인 row내의 id 값의 길이가 11이라는 것을 알아내었다.
그럼 이제 비슷한 방법으로 길이가 11인 문자열 각각의 자리의 문자를 찾아내면 된다.
이부분은 노가다가 필요하기 때문에 간단한 파이썬 스크립트를 제작하였다.

 URL 안에 따옴표를 넣을 수가 없기 때문에 문자열을 직접적으로 쿼리로 넣지 못한다. 그래서 우리가 검사를 하는 과정에서 문자는 16진수로 변환하여 넣어야한다.
  전체적인 스크립트 방식은 문자를 찾았을 경우의 html 텍스트를 샘플로 저장해두고 나머지 자리의 문자들을 검사할때 나온 결과값을 샘플과 비교하면서, 만약에 문자가 맞다면 결과값에 해당 문자를 추가하고 다음 문자 검색으로 넘어가는 방식이다.

아무튼 이렇게 코드를 실행하면 검사하는 과정이 뜨고 완료가 된다면 완성된 패스워드가 출력된다.
이 패스워드를 복사해서 문제에 붙여넣고 submit하면 문제가 해결된다.

728x90
반응형