일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- GIT
- 자바
- 뷰
- 써니나타스
- nodeJS
- node
- 워게임
- MongoDB
- gitbash
- 포렌식워게임
- bootstrap
- 그래프
- NavBar
- Express
- 포렌식
- 자바문제풀이
- node.js
- 웹기초
- 워게임추천
- materialize
- 자료구조
- 자바기초
- 웹해킹
- 웹개발
- wargame.kr
- 이진탐색트리
- CTF
- 웹해킹기초
- mongoose
- 이진트리
- Today
- Total
보안 전공생의 공부
Lord of SQL Injection#7 orge | Blind SQL Injection 본문
◆ Blind SQL Injection
서버에서 내부 오류 메시지를 외부에 공개되지 않도록 구성한 경우
Type 변환 오류 메시지를 사용한 Database구조 파악이 불가능
→ substring(문자열, 시작위치, 길이) 문자열의 특정 문자열을 한 글자씩 찾아가는 Blind SQL Injection 공격 시도
Query 결과에 따른 서버의 참/거짓 반응을 통해 공격을 수행한다.
(Target 사이트에서 참/거짓을 구분지을 수 있는 페이지가 존재해야함)
이를 통해 db명, 테이블명, 컬럼명 ID, PW 등을 알아낼 수 있다.
(출처 : https://peemangit.tistory.com/151 )
우선 눈에 보이는 것은
pw를 입력할 때 or이나 and를 사용하지 말라는 것이다.
||,%7c%7c 와 &&,%26%26로 필터링 하면 된다.
정답을 해결하기 위해서는
입력받은 pw값과 db에 있는 pw값이 일치해야한다 !
(입력받은 pw는 id가 admin일 때의 pw )
이는 전에 풀었던 #4 문제와 비슷한 유형이다.
Blind SQL Injection을 이용해 db에 있는 pw에 대해 아무 힌트가 없는 채로 추정해나가야한다.
우선 참/거짓을 확인할 수 있는 출력문이 있는지 확인해보아야한다.
?pw='||1=1%23 을 입력하면
이 쿼리문은 참이고
이때, Hello guest를 출력한다.
이와 비교하여
?pw='||1!=1%23 을 입력하면
이 쿼리문은 거짓이고
아무것도 출력되지 않는다 !
Hello {사용자 id} ! 문구 출력 유무에 따라 참/거짓을 판단할 수 있게 되었다.
Hello admin 이 출력되는 것이면 참,
Hello guest 이 출력되거나 아무것도 출력되지 않는다면 거짓이라고 판별한다.
내가 입력하는 pw는 id가 admin이므로, pw에 대해 입력한 조건이 맞다면 id는 admin으로 인식될 것이기 때문이다.
( id='guest' and pw=' '는 pw가 공백이기 때문에 거짓임)
pw에 대해 알아야할점은 우선적으로 문자열의 길이이다 !
이는 length함수를 이용하면 된다.
?pw='||length(pw)=1%23
1 자리에 2,3,4,… 를 바꿔 넣어보며 query문이 참이 되도록 만든다.
하다보면 길이가 8일 떄 문구가 출력되며 참임을 알 수 있다.
pw의 길이가 8자리인 것을 알았고, 각 글자가 무엇인지 찾아나가야한다.
ascii함수와 substr함수를 이용해 첫 글자부터 유추해나가야 한다
ascii()는 괄호 안에 입력하는 문자나 문자열에 대해 그에 해당하는 아스키코드 값을 반환한다. (0~9 : 48 - 57, A~Z : 65 - 91 , a~z : 97 - 172 )
substr( string, start [], length )는 문자열 string에 대해 start위치에서부터 length만큼 문자를 추출한다. length 값이 주어지지 않으면 문자열의 끝까지 추출한다.
<첫번째 글자>
첫번째 글자부터 추정해나간다.
문자인지 숫자인지부터 찾아내보려고 한다
ascii(substr(pw,1,1)) < 65
참이므로 숫자임을 알 수 있다.
이제 어떤 숫자인지 맞춰나갈 것이다.
ascii(substr(pw,1,1)) < 57 (57은 9이다) 부터
ascii(substr(pw,1,1)) < 48 (48은 0이다) 까지 줄여나가야한다.
도중에 거짓이 된다면 값을 찾아낼 수 있을 것이다.
ascii(substr(pw,1,1)) < 55부터 거짓이 되었다.
이로써 첫 번째 글자는 아스키코드 값이 55인 7임을 알 수 있다 !
이런 방식으로 마지막 글자까지 찾아내면 된다.
<두번째 글자>
아스키코드값 98 = b
<세번째 글자>
아스키코드값 55 = 7
<네번째 글자>
아스키코드값 53 = 5
<다섯번째 글자>
아스키코드값 49 =1
<여섯번째 글자>
아스키코드값 97 = a
<일곱번째 글자> 크기비교(<,>)로 추정하는데 계속 Hello guest가 출력되어서 한참 애를 먹었다. =으로 고쳐서 추정해나가니 Hello admin이 출력되었다. 크기비교를 했을 때 해당되는 pw가 id가 guest일 때의 pw에게도 참이어서 그런 것 같다. 여섯번째 글자까지는 운좋게 Hello admin만 출력된 것인것 같다. >,<보다 =이 더 정확하다는 걸 느꼈다.
아스키코드값 101 = e
<여덟번째 글자>
아스키코드값 99 = c
이렇게 해서 pw = 7b751aec 임을 알아내었다 !!
인증에 성공하였다 :)
#4와 문제유형이 비슷해서 내 손으로 직접 풀 수 있었다 !
다만 글자를 추정해가는데 문제가 생겨서 이는 구글링을 통해 해결하였다.