문제 정보
https://webhacking.kr/challenge/bonus-6/
풀이
문제에 접속하면 가장 먼저 보이는 화면이다. Wrong이라고 잘못됐다고 알려준다. view-source를 눌러보자.
view-source를 눌렀을 때 보이는 소스 코드는 아래와 같다. 해석해보면 get이라는 파라미터에 hehe라고 요청이 들어오면 어딘가로 보내준다.
<hr>
Challenge 33-1<br>
<a href=index.txt>view-source</a>
<hr>
<?php
if($_GET['get']=="hehe") echo "<a href=???>Next</a>";
else echo("Wrong");
?>
다음과 같이 ?get=hehe 를 입력해주면 Next가 보인다.
lv2.php로 넘어온 듯 하다.
lv2.txt의 소스코드는 아래와 같다. 이번엔 post 요청을 통해서 post="hehe"를 입력해주고, AND 연산자를 통해post2="hehe2"를 두개 다 입력해 주어야 한다고 한다.
<hr>
Challenge 33-2<br>
<a href=lv2.txt>view-source</a>
<hr>
<?php
if($_POST['post']=="hehe" && $_POST['post2']=="hehe2") echo "<a href=???>Next</a>";
else echo "Wrong";
?>
이와 같이 보냈는데 해결되지 않았다.
인터넷을 통해 POST 요청을 보내는 방법에 대해서 조금 더 검색한 결과, 달할 데이터를 맨 아래쪽에 변수명=값 & 변수명 = 값 으로 전달하기 위해선 Content-Type 헤더를 추가해서 application/x-www-form-urlencoded 를 입력해주어야 인식이 된다고 한다.
33.php로 이동해보면 또 문제가 나온다.
33.txt의 문제 소스 코드는 아래와 같다. 문제를 분석해보면 $_SERVER['REMOTE_ADDR'] 의 값과 myip로 get 요청한 파라미터 값이 같으면 풀린다. 아이피의 경우 네이버에서 내 ip 주소 치면 나온다.
<hr>
Challenge 33-3<br>
<a href=33.txt>view-source</a>
<hr>
<?php
if($_GET['myip'] == $_SERVER['REMOTE_ADDR']) echo "<a href=???>Next</a>";
else echo "Wrong";
?>
l4.php는 다음과 같다. 이번엔 힌트가 주어졌다.
소스 코드는 아래와 같다. time 함수 값이 md5로 암호화 되어 있고 password 파라미터로 요청하면 되겠다.
<hr>
Challenge 33-4<br>
<a href=l4.txt>view-source</a>
<hr>
<?php
if($_GET['password'] == md5(time())) echo "<a href=???>Next</a>";
else echo "hint : ".time();
?>
힌트에 나온 값을 Burp Suite에서 암호화 하는데 복사하기 귀찮아서 MD5 암호화 사이트로 넣어서 암호화했다.
이를 password에 넣으니까 해결되지 않았다. 보니까 hint에 나오는 시간 값이 계속 바뀌었다. 흠 ...
일단 time 함수는 1970년 1월 1일 0시 0분 0초 부터 지금까지 지나온 초를 정수 형태로 나타내는 함수이다. hint 에서 나오는 time 함수의 값이 증가하는 규칙이 1씩 계속 증가하는 형태였던 것이다. 따라서 시간을 넉넉히 한 50정도 추가해서 빠르게 md5 암호화하고 password에 넣으니 해결되었다.
다음 md555.txt의 소스코드는 아래와 같다. imget라는 이름이 get 방식으로 요청되고, impost로 post 요청도 보내고 imcookie라는 쿠키도 추가해줘야 한다.
<hr>
Challenge 33-5<br>
<a href=md555.txt>view-source</a>
<hr>
<?php
if($_GET['imget'] && $_POST['impost'] && $_COOKIE['imcookie']) echo "<a href=???>Next</a>";
else echo "Wrong";
?>
위 세가지를 한 번에 추가해서 전송하기 위해 아래와 같이 작성했는데 잘 되지 않는 것 같다...
GET 요청으로 패킷을 보냈다 POST로 바꿔주니 해결됐다! 쿠키의 경우 쿠키 변수 하나당 ;문자를 통해서 구별하고 전처럼 POST로 아래에 있는 문자열을 보내기 위해서 Content-Type 헤더를 추가했다.
gpcc.php로 넘어가면 이번 hint는 user-agent 헤더 값인 것을 알 수 있다.
소스 코드는 아래와 같다. 분석해보면 test라는 쿠키 값과 공인IP를 md5 암호화한 값과 똑같아야 하고, User-Agent의 값을 md5 암호화한 값과 kk로 요청된 POST 값이 일치해야 한다. 힌트에 작성된 HTTP_USER_AGENT 값을 쓰면 되겠다.
<hr>
Challenge 33-6<br>
<a href=gpcc.txt>view-source</a>
<hr>
<?php
if($_COOKIE['test'] == md5($_SERVER['REMOTE_ADDR']) && $_POST['kk'] == md5($_SERVER['HTTP_USER_AGENT'])) echo "<a href=???>Next</a>";
else echo "hint : {$_SERVER['HTTP_USER_AGENT']}";
?>
아래와 같이 공인 IP 주소를 md5 암호화하고, hint에 적힌 user-agent 값을 md5 암호화해서 kk에 적용하면 해결된다.
다음 소스 코드는 다음과 같다. 이는 내 공인 IP 주소의 .이 공백으로 치환되고 GET 방식으로 두 개가 동일해야 하기 때문에 내 공인 IP 주소에서 .을 없애고 ?IP=IP 을 입력해주면 되겠다.
<hr>
Challenge 33-7<br>
<a href=wtff.txt>view-source</a>
<hr>
<?php
$_SERVER['REMOTE_ADDR'] = str_replace(".","",$_SERVER['REMOTE_ADDR']);
if($_GET[$_SERVER['REMOTE_ADDR']] == $_SERVER['REMOTE_ADDR']) echo "<a href=???>Next</a>";
else echo "Wrong<br>".$_GET[$_SERVER['REMOTE_ADDR']];
?>
33-8의 소스 코드는 아래와 같다. 분석해보면 extract 함수를 이용해서 배열 속에 있는 $_GET 값을 변수화 시켜준다. get 요청으로 addr 파라미터를 받지 못하면 $addr 변수는 나의 외부 공인 IP가 된다. 그리고 addr이 127.0.0.1이면 다음 스테이지로 넘어간다.
<hr>
Challenge 33-8<br>
<a href=ipt.txt>view-source</a>
<hr>
<?php
extract($_GET);
if(!$_GET['addr']) $addr = $_SERVER['REMOTE_ADDR'];
if($addr == "127.0.0.1") echo "<a href=???>Next</a>";
else echo "Wrong";
?>
위는 그냥 addr 파라미터 값을 127.0.0.1로 설정해서 요청해주면 해결된다.
다음은 33-9의 소스 코드이다. 아래에 나오는 for문의 answer 값을 ans 파라미터 값에 넣어주면 되는 것 같다. 근데 여기서 .=이라는 연산자는 처음 본다. PHP 에서는 .=을 접합한 값을 왼쪽 변수에 할당해주는 연산자라고 한다.
<hr>
Challenge 33-9<br>
<a href=nextt.txt>view-source</a>
<hr>
<?php
for($i=97;$i<=122;$i=$i+2){
$answer.=chr($i);
}
if($_GET['ans'] == $answer) echo "<a href=???.php>Next</a>";
else echo "Wrong";
?>
간단하게 파이썬으로 for 문을 돌리고 97부터 122까지니까 파이썬에서는 다음과 같이 97, 123, 2라고 범위를 정한 후 파이썬에도 chr 함수가 존재하기 때문에 쉽게 작성 가능하다.
이렇게 위에서 작성한 스크립트 결과 값을 ans 변수에 담아서 요청해주자.
10번 스테이지의 소스 코드이다. 이 스테이지는 몇 번까지 있는 것일까...
소스 코드를 분석하면
- ip 변수에 공인 IP 주소를 담고, strlen 함수로 이 길이만큼 각 문자를 ord 함수를 통해 변환해 주는 것 같다.
- ip 변수에서 .을 다 제거한다.
- substr 함수를 이용해 0의 위치부터 10개의 문자를 추출한다.
- answer 변수를 정의해 ip 변수의 값에 2를 곱한다.
- answer 변수를 다시 정의해 ip에 이를 나뉜다. (위에 있는 명령은 사라짐)
- answer에서 .을 제거한다.
- answerip/{answer}_{ip}.php 경로에 들어가 파일을 읽는다.
- 해결
<hr>
Challenge 33-10<br>
<a href=forfor.txt>view-source</a>
<hr>
<?php
$ip = $_SERVER['REMOTE_ADDR'];
for($i=0;$i<=strlen($ip);$i++) $ip=str_replace($i,ord($i),$ip);
$ip=str_replace(".","",$ip);
$ip=substr($ip,0,10);
$answer = $ip*2;
$answer = $ip/2;
$answer = str_replace(".","",$answer);
$f=fopen("answerip/{$answer}_{$ip}.php","w");
fwrite($f,"<?php include \"../../../config.php\"; solve(33); unlink(__FILE__); ?>");
fclose($f);
?>
이를 머리로 계산하려고 했으나 조금 복잡하여 그냥 php 코드 테스트 사이트에서 해결해보자.
위 사이트에서는 $_SERVER['REMOTE_ADDR'] 가 다른 값으로 되어 있을텐데 이를 자기의 IP로 바꾸고 똑같이 적어준 후 echo를 이용해 $ip와 $answer를 쉽게 알 수 있다.
다음으로 fopen으로 php 파일을 열어야 하는데 이는 forfor.php를 지우고 적어주어야 제대로 동작한다. 따라서 적어두면 solve(33) 함수가 실행되면서 풀리는 것을 볼 수 있다. 끝 ㅠㅠ
'Web Hacking > webhacking.kr 풀이' 카테고리의 다른 글
old-36 write-up (0) | 2024.01.11 |
---|---|
old-25 write-up (0) | 2024.01.11 |
old-47 write-up (0) | 2024.01.11 |
old-27 write-up (0) | 2024.01.11 |
old-19 write-up (0) | 2024.01.11 |