2번 문제를 클릭하게 되면 다음과 같은 화면만 보이게 된다.
이것만 가지고는 힌트를 얻을 수 없기 때문에 개발자 모드로 진입하여 확인해보기로 한다.
개발자 모드에서 확인해보면 주석으로 '만약 admin.php에 접근한다면 엉덩이를 걷어차버릴 거야'라는 문구를 확인할 수 있다. 혹시 모르니 url 뒤에 admin.php를 붙여 이동해보도록 하자.
하지만 해당 화면에서 pw 부분에 SQL Injection을 시도해보았지만 wrong password alert만 뜨게 된다.
다시 원점으로 돌아가 주어진 힌트들에 대해서 검토해보기로 하자.
처음에 개발자 모드에서 확인했던 HTML 코드를 다시 확인해보면 현재 날짜 및 시간이 주석처리 되어 있는 것을 확인할 수 있다.
단서를 찾기 위해 Cookie Editor를 열어 확인해보면 time 쿠키 값이 들어 있는 것을 확인할 수 있다.
해당 time 쿠키 값 뒤에 인젝션을 시도해보자.
참인 조건을 입력했을 시 2070-01-01 09:00:01 값으로 주석처리가 변경되어 있고
거짓인 조건을 입력했을 시 2070-01-01 09:00:00 값으로 주석처리가 되어 있다.
이를 통해 우리는 참/거짓 조건을 이용한 Blind SQL Injection이 가능함을 짐작해 볼 수 있다.
그러나 문제해결을 위한 테이블명과 컬럼명을 모르니 우선 이것부터 알아내야 한다.
참, 거짓 반응을 통해 Blind SQL Injection을 수행할 것이지만 수동으로 진행하기에는 과정이 번거로우니 Python 자동화 소스를 통해 테이블명과 컬럼명을 구할 것이다.
아래는 해당 파이썬 코드는 ws1004(김규빈)님의 포스트를 참고하였습니다.
https://whitesnake1004.tistory.com/596
※ DB명, 테이블명, 컬럼명 파이썬 코드
DB명이 chall2임을 확인할 수 있다.
그 다음 테이블명을 INFORMATION_SCHEMA.TABLES 이용해서 추출해본다.
테이블명을 추출하는 파이썬 코드는 아래와 같다.
추출한 테이블명은 다음과 같고 이제 INFORMATION_SCHEMA.COLUMNS를 이용하여 컬럼명을 추출해 보겠다.
컬럼명을 추출할 파이썬 코드는 아래와 같다.
추출된 pw값을 admin.php 페이지에 입력해본다.
이렇게 webhacking 2번째 문제를 풀어보았다.
※ 추가 학습 내용
1) substr 함수
substr 함수는 정해진 문자를 특정 자릿수만큼 잘라내는 기능을 하는 함수이다. char 문자열에 대해서 position에 정해진 자릿수부터 substring_length 자리만큼 잘라내는 것이다.
형식 : substr("문자열","시작위치","길이")
2) ord 함수
ord(c)는 문자의 아스키 코드 값을 돌려주는 함수이다.
※ ord 함수는 chr 함수와 반대이다.
ex) ord('a') -> 97
3) ASCII
문자, 숫자, 특수문자에 수치(numberic Value)를 부여한 부호체계이다.
4) INFORMATION_SCHEMA
MySQL은 메타데이터들을 종류별로 묶어 테이블을 만들었고, 이 테이블을 모아 데이터베이스를 만들었는데, 그 데이터베이스가 바로 INFORMATION_SCHEMA이다. INFORMATION_SCHEMA는 MySQL서버가 운영하는 모든 다른 데이터베이스에 대한 정보를 저장하는 장소이고, 그 중에는 데이터베이스 이름, 테이블 이름, 컬럼의 자료형, 접근 권한처럼 SQL Injection공격에 이용될 정도로 민감한 정보도 포함되어 있다.
5) Python requests 모듈
참고링크 : https://dgkim5360.tistory.com/entry/python-requests
step1. 기본적인 사용 방법
import requests
URL = 'http://www.tistory.com'
response = requests.get(URL)
response.status_code
response.text
웹브라우져에서 티스토리를 접속한 것과 똑같은 이야기이다. www.tistory.com 이라는 주소로 GET 요청(request)를 보냈고 서버에서는 그 요청을 받아 뭔가를 처리한 후 요청자인 나에게 응답(response)를 줬다. 우선 그 응답은 200 상태코드와 함께 왔다. 이는 티스토리 서버에서 잘 처리되어서 정상적인 응답을 보내줬다는 OK 싸인을 의미한다. 그리고 응답의 내용은? 보시다시피 HTML 코드.
step2. GET 요청할 때 parameter 전달법
params = {'param1': 'value1', 'param2': 'value'}
res = requests.get(URL, params=params)
응답 객체인 res를 통해서 내가 실제로 던진 URL이 뭔지 확인해보았다. 내가 준 URL과 파라미터를 requests 모듈이 엮어서 적절한 새로운 요청을 만든 것이다. 내가 직접 URL을 저렇게 타이핑하는 것보다 파라미터를 딕셔너리 형식으로 정리하고 requests 모듈에 던져주는 것이 훨씬 좋다고 생각한다.
step3. POST 요청할 때 data 전달법
위의 내용과 같다, params 대신 data라는 이름으로 주면 된다.
data = {'param1': 'value1', 'param2': 'value'}
res = requests.post(URL, data=data)
조금 더 복잡한 구조로 POST 요청을 해야 할 때가 있다. 이럴 때는 위의 방법처럼 순진하게 주면 안된다. 우리가 인지하고 있는 그 딕셔너리의 구조를 유지하면서 문자열로 바꿔서 전달해줘야 하는데, python에서 이 노동을 해주는 친구가 json 모듈이다.
import requests, json
data = {'outer': {'inner': 'value'}}
res = requests.post(URL, data=json.dumps(data))
step4. 헤더 추가, 쿠키 추가
별도의 헤더 옵션을 추가하고자 할 때는 headers 옵션을, 쿠키를 심어서 요청을 보내고 싶으면 cookies 옵션을 사용하면 된다
headers = {'Content-Type': 'application/json; charset=utf-8'}
cookies = {'session_id': 'sorryidontcare'}
res = requests.get(URL, headers=headers, cookies=cookies)
step5. 응답(Response) 객체
요청(request)을 보내면 응답(response)을 받는다. 당연히 이 응답은 python 객체로 받는다. 그리고 이 응답 객체는 많은 정보와 기능을 가지고 있다. ipython이나 jupyter notebook에서 <탭> 기능을 이용해서 직접 체험해보면 금방 파악이 가능하지만 여기에 몇 가지만 기록하겠다.
ipython 환경에서 res.<탭>을 통해 어떤 요소 및 함수가 있는지 살펴볼 수 있다.
res.request # 내가 보낸 request 객체에 접근 가능
res.status_code # 응답 코드
res.raise_for_status() # 200 OK 코드가 아닌 경우 에러 발동
res.json() # json response일 경우 딕셔너리 타입으로 바로 변환
'CTF & WarGame > webhacking.kr' 카테고리의 다른 글
[webhacking.kr] 6번 문제 (0) | 2020.02.27 |
---|---|
[webhacking.kr] 5번 문제 (0) | 2020.02.27 |
[webhacking.kr] 4번 문제 (0) | 2020.02.25 |
[webhacking.kr] 3번 문제 (0) | 2020.02.25 |
[webhacking.kr] 1번 문제 (0) | 2020.02.21 |