The Great Disappearing Act
Asylum Escape Challenge
Mô tả: You now take control of Hopper, with one ultimate goal. Free yourself from this wrongful imprisonment. To do this, you must follow Hopper’s 5-step escape plan:
- Unlock Hopper’s Cell Your escape begins in the Cells and Storage area. Hopper is locked inside, and the door is secured with a digital lock. Your first task is to access the cell controls and unlock his door. Once Hopper is free, you can begin moving toward the lobby.
- Move Through the Lobby With the cell unlocked, head straight ahead into the lobby. This area connects the different blocks of the facility. Cameras are active, so stay alert. Your objective is to reach the Psych Ward entrance on the east side of the lobby.
- Bypass the Psych Ward Keypad The Psych Ward is protected by a keypad system. You must identify the correct code or exploit the keypad to continue. Once the keypad is bypassed, you will gain access to the Psych Ward Exit hallway.
- Reach the Main Corridor From the Psych Ward Exit you can move south and loop around into the Main Corridor. This is the final section of the escape route. The last challenge awaits here, and completing it will open the final exit door.
- Escape the Facility Solve the final challenge in the Main Corridor and make your way toward the exit marked on the map. Once the door opens, Hopper is free, and the escape is complete.
Nhận diện ban đầu:
Sử dụng Rustscan thì ta có được các cổng được mở như sau:
Lần lượt truy cập các cổng đã mở ta có được các trang web như sau:
Cổng 80 và 8080 - có lẽ đây là giao diện chính của thử thách, tuy nhiên ta không có tài khoản và mật khẩu để đăng nhập vào trang này:
Cổng 8000 - tại đây chứa 1 trang mạng xã hội, chúng ta có thể đăng kí tài khoản và đăng nhập để truy cập vào mạng xã hội này ( Có lẽ trang này phục vụ mục đich Osint ):
Cổng 9001: SCADA terminal yêu cầu mã xác thực:
Cổng 13400 - đây là 1 trang web để quản lý phòng giam như được đề cập trong thử thách, ta cũng không biết tài khoản mật khẩu để truy cập:
Cổng 13402:
Cổng 13404 - có lẽ là backend của API nào đó:
Bắt đầu thử thách
Quay trở lại trang web nằm tại công 80 và 8080 và xem mã nguồn của trang web ta có 1 đoạn mã nguồn để quản lý các flag như sau: main.js
Flag thứ 1.
Đối với flag đầu tiên thì ta có đoạn code để lấy flag như sau:
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
async function unlockCell() {
const flagDiv = document.getElementById("hopperFlag");
const span = document.getElementById("hopperFlagText");
if (flagDiv) flagDiv.style.display = "none";
try {
const res = await fetch("/cgi-bin/key_flag.sh?door=hopper");
const data = await res.json();
if (data && data.ok && data.flag) {
if (span) span.textContent = data.flag;
if (flagDiv) flagDiv.style.display = "block";
markUnlocked("hopper");
} else {
if (flagDiv) {
flagDiv.style.display = "block";
flagDiv.innerHTML =
"<div>Unlock succeeded, but flag could not be retrieved.</div>";
}
markUnlocked("hopper");
}
} catch (e) {
if (flagDiv) {
flagDiv.style.display = "block";
flagDiv.innerHTML = "<div>Error contacting server for flag.</div>";
}
}
}
Dựa vào đoạn code trên ta có thể có nhiều phương án để lấy được flag
Cách 1 : Trực tiếp.
ta có thể gửi trực tiếp request tới url http://ipweb/cgi-bin/key_flag.sh?door=hopper để lấy flag:
Cách 2: thông qua giao diện.
Thông qua đoạn code dưới đây thì ta hoàn toàn có thể truy cập vào bản đồ các buồng giam trong thử thách mà không cần phải đăng nhập bằng cách set giá trị mapscren từ none thành block thông qua công cụ devtool trong trình duyệt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
async function checkSession() {
const loginWin = document.getElementById("loginWindow");
const map = document.getElementById("mapScreen");
try {
const res = await fetch("/cgi-bin/session_check.sh", { cache: "no-store" });
const data = await res.json();
if (data && data.authed) {
loginWin.style.display = "none";
map.style.display = "block";
} else {
loginWin.style.display = "block";
map.style.display = "none";
}
} catch (e) {
loginWin.style.display = "block";
map.style.display = "none";
}
}
Sau khi đổi giá trị của mapscreen từ none thành block thì ta được giao diện như bên dưới. Sau đó để lấy được flag thì ta đơn giản chỉ cần nhấp vào hình chìa khóa của phòng Cell / Storage và sau đó nhấn nút Unlock Cell Door để nhận được flag:
Cách 3: Đăng nhập và lấy flag
Với 2 cách đã được đề cập bên trên thì có lẽ chỉ giúp ta lấy được flag thứ nhất, còn để lấy được các flag còn lại mà không dùng đến thông tin đăng nhập thì quả thật là rất khó. Để ý các trang web tại port 80, 8080, 13400 đều yêu cầu đăng nhập để có thể truy cập. Chính vì vậy nhiệm vụ của chúng ta là phải tìm kiếm thông tin để truy cập vào các trang web trên.
Để ý thì trang web nằm tại port 8000 là một trang web mạng xã hội và ta cũng có thể tạo một tài khoản của riêng mình để truy cập vào mạng xã hội này. Chinh vì vậy, đây là một trang web vô giá để ta có thể thu thập các manh mối về thông tin đăng nhập.
Sau khi tạo một tài khoản trong trang web nằm tại port 8000 trên và đăng nhập thì ta đã thấy luôn 1 địa chỉ email khả nghi được công khai guard.hopkins@hopsecasylum.com:
Tiếp tục tìm kiếm thêm thông tin thì ta có thêm thông tin về mật khẩu mà Hopkins đã từng sử dụng đó là: Pizza1234$
Tuy nhiên khi dùng mật khẩu này thì đăng nhập vào các trang web bên trên thì đều không được chứng tỏ mật khẩu thực sự đã được đổi đúng như lời của Hopkins. Tuy nhiên thông thường thì người dùng thường có thói quen đặt mật khẩu theo một format nào đó. Ở đây thì format của Hopkins là Tên thứ mình thích + dãy số + kí tự đặc biệt chính vì vậy ta phải thu thập thêm các thông tin từ của Hopkins, việc này khá dễ dàng bởi lẽ anh ta cũng có khá nhiều bài đăng trong mạng xã hội này.
Ta thu thập được khá nhiều thông tin từ các bài viết dưới đây:
Qua đây ta có thể khoanh vùng được các thông tin là 1982 , Johnnyboy, DoorDasher. Tạo các giá trị mật khẩu theo format đã suy luận bên trên và thử thì ta có được giá trị mật khẩu là Johnnyboy1982!
Thông tin đăng nhập:
- Email: guard.hopkins@hopsecasylum.com
- Mật khẩu: Johnnyboy1982!
Sử dụng thông tin trên và truy cập trang web nằm tại port 8080 để nhận flag đầu tiên.
Lưu ý: 2 trang web nằm tại port 8080 và 80 đều có chung giao diện nhưng chỉ có web nằm tại port 8080 có thể tương tác ( Chưa hiểu ý đồ của tác giả :v )
Flag thứ 2:
Theo gợi ý của đề bài thì để lấy được flag thứ 2 thì ta phải truy cập trang web nằm tại port 13400 ( Thông tin xác thực như bên trên ). Tuy nhiên ta không có đặc quyền để xem camera của Psych Ward Exit do yêu cầu quyền admin:
Tuy nhiên khi Ctrl + U xem mã nguồn của trang thì ta thu thập được mã nguồn về cách hoạt động của trang web này: main.js
Để ý đến đoạn code này:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
async function requestTicket(camera_id, tier) {
const r = await authedFetch(API + "/v1/streams/request", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ camera_id, tier }),
});
const j = await r.json();
if (!j.ticket_id) return;
if (camera_id !== "cam-admin" && j.effective_tier === "guard") {
attachWithReconnect(API + "/v1/streams/" + j.ticket_id + "/manifest.m3u8");
}
if (camera_id === "cam-admin" && j.effective_tier === "admin") {
attachWithReconnect(API + "/v1/streams/" + j.ticket_id + "/manifest.m3u8");
}
}
Khi ta nhấn vào 1 trong các camera trong giao diện web thì tùy thuộc vào camera mà chúng ta chọn thì nó sẽ gửi một yêu cầu POST tới /v1/streams/request chứa ID của carmera và tier của ta. Và server sẽ trả về effective_tier và ticket_id và id này sẽ được sử dụng để truy xuất video tại **/v1/streams/
Tuy nhiên nếu chúng ta thay đổi giá trị của tier trong yêu cầu POST thì effective_tier trong respone trả về sẽ được set thành giá trị guard
. Tuy nhiên trường hợp này lại không xảy ra với các đầu vào khác giá trị admin. Chứng tỏ server đã có 1 hàm nào đó xử lí riêng việc dữ liệu đầu vào là admin này
Và logic trên được giải mã bằng cách khai thác lỗ hổng HTTP Parameter Pollution bằng cách truyền tham số trong phần body và query của POST request như hình bên dưới
Bây giờ để xem được video của admin thì ta chỉ cần chỉnh sửa request của giao diện web trong quá trình gửi dữ liệu đến server là được. Ta thực hiện điều này bằng tính năng intercerp của BurpSuite.
Và đây là mã pin để mở khóa flag thứ 2
Tuy nhiên sau khi nhập mã PIN thì ta chỉ nhận được 1 nửa flag thứ 2.
Flag 2 - Part1: THM{********
Phần còn lại vẫn còn ẩn giấu ở đâu đó Quay trở lại BurpSuite ta thấy dữ liệu trả về có 1 số thông tin đặc biệt
Trong đó có 2 đường dẫn là /v1/ingest/diagnostics , /v1/ingest/jobsvà rtspurl = rtsp://vendor-cam.test/cam-admin
Thử sửa request đến /v1/ingest/diagnostics thì thấy không dùng được GET request mà chỉ được phép gửi request POST và OPTIONS.
Sửa lại request thành POST thì ta nhận được kết quả sau:
Thêm trường rtsp_url vào body và giá trị url là rtsp://vendor-cam.test/cam-admin lấy từ bên trên thì nhận được kết quả sau:
Tiếp tục truy cập vào /v1/ingest/jobs/ff27a927-ec4f-4cff-837f-b66924a04638 ( Lưu ý thêm header chứa thông tin xác thực phiên ) thì nhận được kết quả như sau:
Kết nối đến port 13404 và nhập token xác thực với câu lệnh sau:
1
nc ip_machine 13404
Sau khi nhập token thì ta nhận truy cập được shell sau:
Tìm kiếm trong thư mục của user thì nhận được phần còn lại của flag thứ 2:
Flag thứ 3.
Để ý đến phần để lấy flag tại cổng 8080 có đề cập đến từ khóa SCADA - thứ đang nằm tại cổng tại cổng 9001 - Tuy nhiên cổng này yêu cầu xác thực.
Sau khi thử các chuỗi xác thực khác nhau thì đến khi nhập flag vào input xác thực thì ta vượt qua được phần xác thực. Tuy nhiên giao diện sau xác thực cũng không mấy khả quan bởi vì câu lệnh để mở khóa terminal này cũng yêu cầu phải có một mã Code - có thể Code này cũng được dùng để lấy flag tại trang web chính.
Để ý đến gợi ý của đề bài trong phần cuối này thì ta có Escape the Facility, và ta đã có sẵn shell của user svc_vidops được sandbox. Chính vì vậy ta phải tìm cách để leo thang đặc quyền ra khỏi user svc_vidops.
Do không có password của user svc_vidops (do kết nối thông qua token xác thực) nên ta không thể leo thang theo phương pháp Sudoers. Phương án khả thi nhất lúc này là leo thang nhờ việc cấu hình sai quyền SUID.
Sử dụng lệnh sau để tìm các file có quyền SUID:
1
find / -perm -u=s -type f 2>/dev/null
Kết quả thực thi từ câu lệnh trên cho kết quả là một tệp nhị khá đặc biệt, không nằm trong phạm vi các câu lệnh hệ thống thông thường /usr/local/bin/diag_shell:
File trên thuộc quyền sở hữu của dockermgr
Sau khi chạy câu lệnh thì ta có được shell của dockermgr nhưng không đầy đủ quyền hạn. Do cơ chế SUID chỉ thay đổi Effective User ID (EUID) nhưng không thay đổi Group ID và chúng ta không thuộc nhóm dockermgr nên không thể thực thi các câu lệnh docker.
Tuy nhiên do chúng ta có quyền ghi vào thư mục chính của dockermgr /home/dockermgr/ nên để khắc phục vấn đề thiếu nhóm, ta cần thiết lập một phiên đăng nhập SSH chính thức để hệ điều hành nạp lại toàn bộ quyền nhóm (bao gồm nhóm docker). Ta sẽ tạo file authorized_keys chứa Public Key của mình. Khi SSH vào, Linux sẽ đọc file /etc/group và cấp đủ quyền cho user.
Đầu tiên ta tạo khóa trên máy của mình
Sau đó dùng khóa công khai này gắn vào thư mục /home/dockermgr/.ssh trên shell đang truy cập.
Sau đó dùng lệnh để truy cập shell đầy đủ đặc quyền.
1
ssh -i <public_file_key> dockermgr@<target_ip>
Truy cập vào trong docker để tìm thêm thông tin
1
docker exec -it 1cbf40c715f4 /bin/sh
Ta có được mã nguồn của file terminal nằm tại cổng 9001
Đọc mã nguồn ta có được mã Code:
Nhập code để lấy được flag:
Cuối cùng nhập cả 3 flag vừa tìm được để mở khóa thử thách phụ







































