CyberJutsu UploadFile
Level 1
Source code của level 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
error_reporting(0);
// Create folder for each user
session_start();
$dir = 'upload/' . session_id();
if ( !file_exists($dir) )
mkdir($dir);
if(isset($_GET["debug"])) die(highlight_file(__FILE__));
if(isset($_FILES["file"])) {
$error = '';
$success = '';
try {
$file = $dir . "/" . $_FILES["file"]["name"];
move_uploaded_file($_FILES["file"]["tmp_name"], $file);
$success = 'Successfully uploaded file at: <a href="/' . $file . '">/' . $file . ' </a>';
} catch(Exception $e) {
$error = $e->getMessage();
}
}
?>
Đoạn code trên sẽ thực hiện tạo một đường dẫn tạm thời bằng cách nối chuỗi “upload” với session id của người dùng. Biến $_FILES là một biến mảng toàn cục của PHP, lưu toàn bộ thông tin về file upload. Sau khi check xem $_FILES["file"]
đã được khởi tạo chưa, chương trình sẽ lưu file trong thư mục tạm thời đã tạo ở trên và đưa ra đường link đến file vừa upload.
Tạo file test.php với nội dung
Thực hiện upload file test.php, ta thấy trang web báo thành công và trả về đường link đến file vừa upload
Click vào đường link trên, ta thấy file php được thực thi và trả về kết quả
Thay đổi nội dung file, thực hiện upload và truy cập đường link, trang web trả về kết quả của câu lệnh whoami
Level 2
Source code của level 2:
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
<?php
error_reporting(0);
// Create folder for each user
session_start();
if (!isset($_SESSION['dir'])) {
$_SESSION['dir'] = 'upload/' . session_id();
}
$dir = $_SESSION['dir'];
if ( !file_exists($dir) )
mkdir($dir);
if(isset($_GET["debug"])) die(highlight_file(__FILE__));
if(isset($_FILES["file"])) {
$error = '';
$success = '';
try {
$filename = $_FILES["file"]["name"];
$extension = explode(".", $filename)[1];
if ($extension === "php") {
die("Hack detected");
}
$file = $dir . "/" . $filename;
move_uploaded_file($_FILES["file"]["tmp_name"], $file);
$success = 'Successfully uploaded file at: <a href="/' . $file . '">/' . $file . ' </a>';
} catch(Exception $e) {
$error = $e->getMessage();
}
}
?>
Đoạn code trên sẽ thực hiện tách tên file bằng hàm explode. Hàm explode là một hàm xử lý chuỗi trong php, dùng để tách 1 chuỗi được phân tách với nhau bằng 1 kí tự (trong đoạn code trên là kí tự "."
) và trả về 1 mảng những chuỗi đã được phân tách. Ví dụ:
1
2
3
4
5
6
7
8
9
10
11
12
$a = "he.llo.wor.ld";
var_dump(explode(".",$a));
//Return array(4) {
// [0]=>
// string(2) "he"
// [1]=>
//string(3) "llo"
//[2]=>
//string(3) "wor"
//[3]=>
//string(2) "ld"
//}
Sau khi tách chuỗi, chương trình sẽ check xem chuỗi ở vị trí thứ 1 trong mảng có phải .php không, nếu có sẽ dừng chương trình và in ra “Hack detected”
Bypass bằng cách thêm 1 đuôi file nữa vào (ở đây mình thêm đuôi .png) , khi này, mảng $extension
sẽ có giá trị [”ten_file”,”png”,”php”]
và biến $extension
sẽ có giá trị “png”
Upload file và truy cập đường dẫn
Trang web hiển thị kết quả của câu lệnh whoami
Level 3
Source code của level 3
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
<?php
error_reporting(0);
// Create folder for each user
session_start();
if (!isset($_SESSION['dir'])) {
$_SESSION['dir'] = 'upload/' . session_id();
}
$dir = $_SESSION['dir'];
if ( !file_exists($dir) )
mkdir($dir);
if(isset($_GET["debug"])) die(highlight_file(__FILE__));
if(isset($_FILES["file"])) {
$error = '';
$success = '';
try {
$filename = $_FILES["file"]["name"];
$extension = end(explode(".", $filename));
if ($extension === "php") {
die("Hack detected");
}
$file = $dir . "/" . $filename;
move_uploaded_file($_FILES["file"]["tmp_name"], $file);
$success = 'Successfully uploaded file at: <a href="/' . $file . '">/' . $file . ' </a>';
} catch(Exception $e) {
$error = $e->getMessage();
}
}
?>
Đoạn code trên có phần tương tự với level 2, nhưng thay vì lấy đuôi file ở vị trí thứ 1 trong mảng như level 2 thì chương trình này sẽ lấy đuôi file cuối cùng
Bypass bằng cách sử dụng đuôi .[phar](https://filegi.com/file-info/phar-3781/)
Upload file đuôi phar
Trang web hiển thị kết quả của câu lệnh whoami
Level 4
Source code của Level 4
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
<?php
error_reporting(0);
// Create folder for each user
session_start();
if (!isset($_SESSION['dir'])) {
$_SESSION['dir'] = 'upload/' . session_id();
}
$dir = $_SESSION['dir'];
if ( !file_exists($dir) )
mkdir($dir);
if(isset($_GET["debug"])) die(highlight_file(__FILE__));
if(isset($_FILES["file"])) {
$error = '';
$success = '';
try {
$filename = $_FILES["file"]["name"];
$extension = end(explode(".", $filename));
if (in_array($extension, ["php", "phtml", "phar"])) {
die("Hack detected");
}
$file = $dir . "/" . $filename;
move_uploaded_file($_FILES["file"]["tmp_name"], $file);
$success = 'Successfully uploaded file at: <a href="/' . $file . '">/' . $file . ' </a>';
} catch(Exception $e) {
$error = $e->getMessage();
}
}
?>
Level này trang web sử dụng blacklist, nếu đường dẫn của file là php
, phtml
, phar
thì chương trình sẽ dừng và in ra dòng chữ “Hack detected”
Bypass bằng cách ghi đè file .htaccess
Upload file .htaccess
vừa tạo
Đổi đuôi file sang php2
và tiến hành upload file
Trang web hiển thị kết quả câu lệnh whoami
Level 5
Source code level 5:
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
<?php
error_reporting(0);
// Create folder for each user
session_start();
if (!isset($_SESSION['dir'])) {
$_SESSION['dir'] = 'upload/' . session_id();
}
$dir = $_SESSION['dir'];
if ( !file_exists($dir) )
mkdir($dir);
if(isset($_GET["debug"])) die(highlight_file(__FILE__));
if(isset($_FILES["file"])) {
$error = '';
$success = '';
try {
$mime_type = $_FILES["file"]["type"];
if (!in_array($mime_type, ["image/jpeg", "image/png", "image/gif"])) {
die("Hack detected");
}
$file = $dir . "/" . $_FILES["file"]["name"];
move_uploaded_file($_FILES["file"]["tmp_name"], $file);
$success = 'Successfully uploaded file at: <a href="/' . $file . '">/' . $file . ' </a>';
} catch(Exception $e) {
$error = $e->getMessage();
}
}
?>
Đoạn code thực hiện check MIME type của file được upload lên, nếu không là 1 trong 3 kiểu "image/jpeg", "image/png", "image/gif"
thì chương trình sẽ dừng và in ra màn hình chuỗi “Hack detected”
Sử dụng Burp Suite để bắt POST request upload file
Chỉnh sửa Content-Type thành image/gif
và gửi lại request, ta thấy trang web thông báo upload thành công
Truy cập url chứa file đã upload
Level 6
Soure code level 6:
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
<?php
// Create folder for each user
session_start();
$dir = 'upload/' . session_id();
if ( !file_exists($dir) )
mkdir($dir);
$error = '';
$success = '';
if(isset($_GET["debug"])) die(highlight_file(__FILE__));
if(isset($_FILES["file"])) {
try {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $_FILES['file']['tmp_name']);
$whitelist = array("image/jpeg", "image/png", "image/gif");
if (!in_array($mime_type, $whitelist, TRUE)) {
die("Hack detected");
}
$file = $dir . "/" . $_FILES["file"]["name"];
move_uploaded_file($_FILES["file"]["tmp_name"], $file);
$success = 'Successfully uploaded file at: <a href="/' . $file . '">/' . $file . ' </a>';
} catch(Exception $e) {
$error = $e->getMessage();
}
}
?>
Đoạn code sử dụng hàm finfo_file để lấy MIME type của file, sau đó check xem có trong whitelist đã được khai báo trước không, nếu không có trong whitelist định trước chương trình sẽ dừng và in ra chuỗi “Hack detected”
Bypass bằng cách thêm header của file gif vào trước đoạn code php
Bypass và upload file thành công
Truy cập url của file đã upload
Level 7
Ở level này, trang web cho phép người dùng upload 1 file nén, phía backend của trang web sẽ unzip (giải nén) và lưu vào folder cho người dùng
Tiến hành upload thử một file
Mình chú ý đến câu lệnh để unzip file được in phía dưới, tên file sẽ được đưa vào một câu lệnh để giải nén file, và tên file là do phía người dùng cung cấp nên chúng ta có thể chỉnh sửa tên file để khai thác lỗ hổng OS Command Injection
1
Unzipper command: unzip /usr/upload/616609e23f10f16ea1ff8e114b4974c3/e66ea8344f034964ba0b3cb9879996ff.tar -d /usr/upload/616609e23f10f16ea1ff8e114b4974c3
Thực hiện bắt post request upload file và chỉnh sửa tên file thành ten_file & <command> &
.Payload & <command> &
với &
là một toán tử câu lệnh trong linux với mục đích chạy ngầm 1 câu lệnh. Thay command = echo hell, ta thấy trang web trả về chuỗi “hell”
Thay command thành whoami
, trang web trả về www-data
Level 8
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
<?php
error_reporting(0);
if (!isset($_GET['game'])) {
header('Location: /?game=fatty-bird-1.html');
}
$game = $_GET['game'];
if(isset($_GET["debug"])) die(highlight_file(__FILE__));
?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php include './views/header.html'; ?>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a href="?game=fatty-bird-1.html&debug">Debug source</a>
</nav>
<br><br>
<h3 class="display-4 text-center">File upload workshop</h3>
<h4 class="display-4 text-center">Level 8</h4>
<p class="display-5 text-center">Goal: read /etc/passwd</p>
<br>
<div style="background-color: white; padding: 20px;">
<?php include './views/' . $game; ?>
</div>
</body>
<?php include './views/footer.html' ?>
</html>
Đoạn code trên thực hiện lấy GET parameter “game” và truyền vào phần dưới của trang web:
1
<?php include './views/' . $game; ?>
Đây là lỗi Path Traversal, như quan sát thấy, chúng ta đang ở thư mục views, là thư mục con của /var/www/html/ (Thư mục default của apache) vì vậy cần sử dụng 4 lần ../
để về thư mục gốc của hệ điều hành, sau đó truy cập /etc/passwd
Payload: ../../../../etc/passwd
Level 9
Source code của phần game:
Tương tự như lv 8, lv 9 cũng dính lỗi Path Traversal
Trang Profile có chức năng upload avatar người chơi
Upload file hehe.php với nội dung
Ta thấy trang web không hề filter file php
Truy cập file avatar từ trang Hall of fame, ta thấy tên file đã được đổi thành avatar.jpg và code php không được thực thi
Check file source code của trang profile, ta thấy đường dẫn lưu file avatar do người dùng upload lên là /usr/upload
Sử dụng Path Traversal để truy cập đến avatar của bản thân, ta thấy câu lệnh whoami
được thực thi và in ra kết quả
Shout out to CyberJutsu vì challenge chất lượng ❤️