Tìm hiểu CVE-2020-15394 - Manage Engine Application Manager unauth RCE

Preface
CVE-2020-15394 - Unauthenticated Remote Code Execution via SQL injection in REST API module: https://www.manageengine.com/products/applications_manager/security-updates/security-updates-cve-2020-15394.html
Affected Builds: builds < 14684; 14689 < builds < 14740
Recommended Fix: Upgrade Applications Manager to version 14740 or above.
Setup step
Application Manager installation archives: https://archives.manageengine.com/applications_manager/
Restricted installation: MangeEngine hạn chế cho phép tải các phiên bản cũ (<=14700) để hạn chế bugs: https://pitstop.manageengine.com/portal/en/community/topic/license-file-might-be-missing
Release Notes: https://www.manageengine.com/products/applications_manager/release-notes.html?utm_source=set3
Đầu tiên setup remode debug bằng Intellij:
-
Từ Intellij mở folder
Application Managervà đợi nó index các file. Tìm tất cả file.jarsau đóAdd as libraryđể intellj index nốt. -
Tìm đến
AppManager_path\working\conf\wrapper.confvà xóa comment các dòng sau để enable remote debug mode.
-
Intellij RemoteJVMDebug kết nối đến
Tracing
Lỗ hổng nằm ở RestAPI module của AM tương ứng với url mapping là /AppManager/*:

Luồng tới sink dính SQLi như sau:
APIServlet.doGet() / APIServlet.doPost()
-->APIServlet.process()
--> APIServlet.validateMethod()
--> APIServlet.validateAndGenerateJSONFeed()
--> DependentDeviceUtil.getInstance().checkResourceIDAndGetListToBeRemoved()
Đầu tiên, APIServlet có chức năng routing request đến các api và cho phép bỏ qua apikey nếu thỏa mãn một số điều kiện:

Tại CommonAPIUtil.skipRESTAPIKeyValidation(), url được chia thành các node dựa vào separator /, nếu node thứ 3 là ApmAdminServices thì cho phép bỏ qua kiểm tra apikey và trả về true, ví dụ: /AppManager/json/ApmAdminServices/* sẽ thỏa mãn.:

Sau đó gọi APIServlet.validateMethod():

Method name sẽ là node thứ 4 rồi gọi đến APIServlet.validateAndGatherData().

Tại đây method lại kiểm tra request hiện tại có quyền truy cập hay không để gọi đến service tương ứng với method name. Nếu không tìm thấy service nào ứng với method name mà node thứ 2 lại là json (isJsonFormat==true) thì request reach đến được APIServlet.validateAndGenerateJSONFeed():

Với method name là checkResourceID sẽ lấy value resourceids từ request parameter và gọi đến DependentDeviceUtil.getInstance().checkResourceIDAndGetListToBeRemoved():

Đến đây đã reach đến được sink của lỗ hổng SQLi do tính năng thực hiện nối chuối với tham số resourceids mà ta có thể kiếm soát.
Vòng if EnterpriseUtil.isManagedServer() để kiểm tra xem liệu đây có phải là remote server, nếu không sẽ execute query trên:

Đến đây ta có thể exec sql command mà không cần xác thực.
RCE
Application Manager là phần mềm dùng để quản trị các application servers, resources, databases,… và với quyền tài khoản là quản trị viên(admin) thì ứng dụng này cho phép thực thi command trực tiếp từ ứng dụng với tính năng Actions --> Execute Program.
Để RCE ta đơn giản lợi dụng lỗ hổng Unauth SQLi trên tạo 1 tài khoản quản trị rồi login vào thực thi command, các step:
- Tạo tài khoản sau đó add vào group admin, request sqli như sau:
http://localhost:9090/AppManager/json/ApmAdminServices/checkResourceID?resourceIds=1);insert into AM_UserPasswordTable (userid,username,password) values ($$191202$$,$$super_admin$$,$$21232f297a57a5a743894a0e4a801fc3$$);insert into Am_UserGroupTable (username,groupname) values ($$super_admin$$,$$ADMIN$$);-- -. Trong đó:21232f297a57a5a743894a0e4a801fc3: là md5 hash củaadmin.$$: thay thế cho"
- Login với
username/passwordlàsuper_admin/adminmà ta đã Inject rồi vào tính năngCreate Actioncủa AM:
Sau khi tạo Action, ta exec program rồi lưu kết quả vào file, nơi mà có thể thể truy cập được, ở đây mình chọn thư mục blog.
- Exec
