I. Mở bài
Trong một lần coi livestream định hướng của CyberJutsu, mình tình cờ thấy được demo cho cái bug này. Nhớ lại trong scope mình handle cũng không ít site sử dụng moodle. Nên thử reproduce.
II. Hướng dẫn cài đặt
Mình sử dụng version 3.9.7 để làm POC.
Link Download: https://download.moodle.org/download.php/stable39/moodle-3.9.7.tgz
Sau khi cài đặt xong, vào Site administration -> Plugins -> Authentication -> Manager Authentication
Sau đó active plugins shibboleth
II. Phân tích Lỗi
Bài này phân tích khá chi tiết: https://buaq.net/go-81019.html. Nên mình chỉ tóm tắt lại
Vị trí lỗi nằm ở file /auth/shibboleth/classes/helper.php
Khi thực thi hàm logout_file_session, server sẽ chạy 1 vòng lặp để unserialize tất cả session trong thư mục /moodledata/sessions/ để tìm ra cái shibboleth_session_id. Sau đó mới so sánh với spsessionid hiện tại – Một pha xử lý khá cồng kềnh.
Khi thực thi hàm unserializesession, đoạn code tạo một preg_split với patern (\w+)\| để cắt chuỗi, như vậy nếu control được session và chèn (\w+)\| vào thì có thể tách chuỗi ra để unserialize được.
$a = preg_split("/(\w+)\|/", $serializedstring, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
Sử dụng regex tìm kiếm với file chứa cả 2 chuỗi patern \$SESSION.->.= và (optional_param\(|required_param\(), sau đó phân tích dữ liệu tìm được, có thể tìm ra /grade/report/grader/index.php chứa đoạn code mà user có thể control.
Đoạn code này có thể control được SESSION input thông qua chèn sifirst hoặc silast mà không cần Authen.
Từ đó rút ra được các bước khai thác như sau:
III. Exploit
1. Các bước khai thác
S1: Requests tới /grade/report/grader/index.php và chèn payload vào param sifirst hoặc silast với 1 MoodleSession hợp lệ.
Payload sẽ có dạng (\w+)\|input_payload_SERIALIZE_here(\w+)\|
S2: Gọi hàm logout_file_session bằng cách Request WSDL tới /auth/shibboleth/logout.php để trigger đoạn code
2. Gadget
** Một vài nhận xét:
- Trong đoạn code thực thi logout_file_session không có thao tác ngầm ép kiểu String nên First Link không thể là một class chứa __toString, một số chain trên mạng sẽ không work. First Link sẽ là class chứa __destruct.
- Để đa dạng hoá gadget chain, có thể tìm first link ép kiểu String.
- Default Moodle sẽ gọi được các class trong /*/classes/*. Do đó first link sẽ nằm trong /*/classes/*.
- Có thể gọi những class ngoài /*/classes/* bằng cách gọi một class khác có chứa hàm include(_once), require(_once), class đó.
** First Link: Sử dụng search __destruct với */classes/* sẽ tìm ra ứng cử viên cho First Link.
Sau khi đọc code 3 hàm này thì link duy nhất \core\lock\lock() có khả năng ứng cử vì sử dụng ép kiểu string thông qua cộng chuỗi.
** Next Link:
Tới đây chỉ cần $this->caller trỏ tới Next Link, mình có thể gọi 1 class khác chứa chain __toString()
Với 136 kết quả sẽ làm đa dạng hoá gadget chain.
Bài này có sử dụng 1 gadget chain đổi password admin, mình đem về modify lại trong context này.
Moodle – Remote Code Execution
Để khai thác chain này, có 2 vấn đề, thứ nhất __toString() không được gọi, vấn đề này đã được giải quyết, vấn đề thứ hai, các class \grade_grade \grade_item sẽ không gọi được do không nằm trong */classes/*.
Để xử lý bài toán này, mình sẽ gọi 1 class khác chứa hàm include class này.
/lib/grade/grade_grade.php <- /lib/gradelib.php <- /analytics/classes/course.php <- \core_analytics\course
-> Gọi class \core_analytics\course sẽ include file /lib/grade/grade_grade.php, sau đó có thể gọi được class \grade_grade
/lib/grade/grade_item.php <- /lib/gradelib.php <- /analytics/classes/course.php <- \core_analytics\course
-> Gọi class \core_analytics\course sẽ include file /lib/grade/grade_item.php, sau đó có thể gọi được class \grade_item
Ngoài ra có 1 chain khác khai thác dễ dàng hơn, link mình để phần POC
3. POC
https://github.com/dinhbaouit/CVE-2021-36394
VIdeo Tutorial Step by Step:
IV. Kết bài
Cơ bản lỗi này sẽ chỉ ảnh hưởng tới những site enable shibboleth plugin, sau khi đi săn mình thấy đa số trường Đại Học ở VN không enable plugin này. Lỗi này nói chung là có điều kiện cần và impact integrity khá gắt nên khả năng khai thác thực tế khá rủi ro.
Tuy nhiên cũng không nên chủ quan, vì còn nhiều chain khác cũng có thể khai thác mà không cần đổi password admin. Ví dụ
V. References:
https://buaq.net/go-81019.html
https://moodle.org/mod/forum/discuss.php?d=424799
Moodle – Remote Code Execution