[그림 1] 문제화면
1 2 3 각각 링크가 걸려있고, Password를 입력하는 칸이 있다.
[그림 2] 1 클릭
1을 클릭하면 no=1이 전달된 URL 주소로 바뀌며
Apple 문자열, Password 입력 칸이 나온다.
위와 같은 방식으로, 2를 클릭 시 no=2이 전달된 URL 주소로 바뀌며
Banana 문자열, Password 입력 칸이 나온다.
[그림 3] 3 클릭
3을 클릭하면
Secret
column : id, no
no 3's id is password
이라는 문자열이 나온다.
따라서, no=3일때의 id 값을 알아내야 한다는 소리인데,,
[그림 4] no=1일 때 페이지 소스코드 보기
일단 어느 페이지에서든 Password 칸에 값을 입력하면 원래 문제화면으로 돌아가며
webhacking.kr/challenge/web-09/index.php?pw=입력한 값
과 같이 입력한 값을 GET 방식으로 전달해주고 있다는 것을 알 수 있었다.
[그림 5] no = 0,1,2,3 이외의 값을 입력
전달해주는 no 값에 0,1,2,3 이외의 값을 입력하면
저렇게 Password 입력창만 뜬다.
간단하게 SQL Injection을 시도해본 결과
' , ", 공백, and, &, |, or, % 등 문자열이 필터링되면서
Access Denied가 뜬다.
이럴 때는 Blind SQL Injection을 사용해야 한다고 한다.
Blind SQL Injection이란, 쿼리 결과로 나오는 참, 거짓을 이용하여 DB 정보를 취득하고자 하는 기법이다.
※ 참고 ※
if (조건문,3,1)
맨 앞 조건문이 참이면 3을 반환, 거짓이면 1을 반환
블라인드 SQL 인젝션을 통해서 id의 길이를 먼저 알아내고자 했다.
no=if(length(id)like({id 문자열의 길이}),3,0)
→ id의 length와 입력한 값이 같다면
no=3이 되어 화면에 Secret이 출력되고,
만약 길이가 같지 않다면 no=0이 되어 초기화면이 보일 것이다.
pw 길이를 알기 위한 코드 작성
결과
no=3일 때의 id, 즉 pw의 길이가 11이라는 것을 알았다.
그리고 블라인드 SQL 인젝션에서 가장 많이 사용하는 함수인 substr 함수를 사용하여 11글자를 알아볼 것이다.
※ 참고 ※
substr (문자열, 시작위치, 개수)
문자열의 시작위치(1부터) 에서부터 개수만큼의 글자를 잘라 가져온다
no=if(substr(id,{문자인덱스},1)like({맞는지 확인할 문자의 헥스값}),3,0)
→ id 문자열의 문자인덱스(1부터) 한 자리 값이 확인할 문자의 헥스값과 같다면
no=3이 되어 화면에 Secret이 출력되고,
만약 그렇지 않다면 no=0이 되어 초기화면이 보일 것이다.
아까 작성한 코드에 이를 추가
그 결과
pw를 알아냈다!!
그러나 맞지 않다고 뜬다.
이유를 알아보니, MYSQL은 대소문자를 구분하지 않는다고 한다.
그래서 대문자 A의 아스키코드 0x41과 소문자 a의 아스키코드 0x61을 같은 문자로 인식하는 것이다.
따라서 이를 소문자로 적어줘봤다.