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 Manager
và đợi nó index các file. Tìm tất cả file.jar
sau đóAdd as library
để intellj index nốt. -
Tìm đến
AppManager_path\working\conf\wrapper.conf
và 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/password
làsuper_admin/admin
mà ta đã Inject rồi vào tính năngCreate Action
củ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