본문 바로가기

WarGame/webhacking.kr

[webhacking.kr] Challenge 22 :: Blind SQL Injection ( Rainbow Table Attack )



Summary

  • 인증절차에 대해 파악합니다.
  • Password Salting과 MD5 Rainbow Table에 대해 이해합니다.
  • Injection Vector를 찾습니다.
  • Blind SQL Injection을 통해 pw값을 알아냅니다.


Challenge 22는 다음과 같습니다.



"Login" 과정과 "Join"과정으로 이루어져 있습니다. 먼저 인증 절차에 대해 파악해야 합니다. "Join"에서 ID : "guest", PW : "guest"라는 계정을 만들고 "Login"을 해보니 "user key"라는 값이 나옵니다. 딱 봐도 32자리로써, MD5로 암호화된 값이라는 것을 알 수 있습니다. 이미 인터넷에는 MD5 Rainbow Table을 이용하여 Decryption을 해주는 사이트가 많이 있습니다. 

이 값을 복호화를 해 보니 "guestzombie"라는 문자가 나옵니다. 즉 사용자가 입력한 PW에 추가적으로 "zombie"라는 문자열을 Salting하여 Brute Force Attack을 방어하고 있는 인증 체계입니다.


이번에는 같은 ID를 갖는 계정을 만들어 봅니다. "Username already exists"라는 문구가 뜹니다. ID가 Primary key로 되어 있다는 것을 추측할 수 있습니다. 이번에는 고의로 잘못된 PW를 입력해 봅니다. 그러면 "Wrong Password!"라는 문구를 확인할 수 있습니다. 가장 중요한 취약점을 찾아 냈습니다. ID의 인증 실패와 PW의 인증 실패에 따라 각기 다른 경고창을 띄우고 있습니다.


이것을 바탕으로 "Join"과 "Login"과정에서의 INSERT 구문과 SELECT 구문을 예측해 봅니다.


1
2
3
4
5
6
// JOIN 과정
INSERT INTO ch22 (id, pw) VALUES ('$id', md5(concat('$pw','zombie')));
 
// LOGIN 과정
SELECT id FROM ch22 WHERE id='$id';
SELECT pw FROM ch22 WHERE pw=md5(concat('$pw','zombie'));
cs


"Login" 과정에서 ID와 PW의 인증 절차가 다른 것을 보아, 각기 다른 SELECT 구문일 것으로 예측할 수 있습니다. 이것은 저의 예측으로 사실과 다를 수도 있습니다.


그 다음 과정으로 Injection Vector를 찾아야 하는데, 모든 입력 받는 Column이 Char 타입임으로 Vector를 찾는 것이 막막할 것입니다. "Join"과 "Login"과정에서 싱글쿼터를 입력할 수 없다면 문제는 풀 수 없을 것입니다. 그럼으로 어딘가 한 곳은 싱글쿼터를 입력할 수 있는 취약점이 존재할 것입니다.


"Join" 과정에서 "guest'(싱글쿼터)" 라는 계정을 만들어 봅니다. 아무 Error 없이 만들어 지는 것을 보니, 이 곳은 Magic_Quotes_Gpc가 설정되어 있는 것으로 예측됩니다. 그리고 "Login" 과정에서 "guest'(싱글쿼터)" 계정에 로그인해 봅니다. "Wrong!"이라는 경고창이 뜹니다. 잘 못된 ID라는 것을 암시합니다. 그럼 이번에는 "guest'(싱글쿼터)#"라는 계정으로 로그인해 봅니다. 그랬더니 "guest'(싱글쿼터)" 라는 계정이 아니라 처음에 만들었던 "guest"라는 계정으로 로그인이 되었습니다. 

즉 "Login" 과정에서는 Magic_Quotes_Gpc가 설정되어 있지 않으므로, 싱글쿼터를 입력할 수 있는 취약점이 존재 합니다. "guest'(싱글쿼터)"라는 계정은 "guest\'(싱글쿼터)"라고 입력하면 로그인할 수 있습니다.


이제 Login 과정에서의 ID 부분을 Injection Vector로 잡고, "admin"의 PW를 알아내야 합니다. ID 부분이 틀렸을 때와 PW 부분이 틀렸을 때 반응이 다르므로, 이 것을 이용하여 Blind SQL Injection을 시도하면 될 것 같습니다.


최종 Query는 다음과 같습니다.


1
admin' and substr(pw,1,1)=0x61#
cs


PW는 임의의 값을 입력하여서, "Wrong Password!"라는 문구가 뜨면 ID 부분이 True인 것으로 해당 Hex값이 "admin"의 PW 값이 됩니다. char(), ascii() 함수가 필터링되어 있지 않으므로 Hex 대신 이용하여도 됩니다.