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

theme

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:

  1. 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.

  2. Tìm đến AppManager_path\working\conf\wrapper.conf và xóa comment các dòng sau để enable remote debug mode. wrapper.conf

  3. 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/*:

RestAPIServlet

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: APIServlet.process

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.: CommonAPIUtil skipRESTAPIKeyValidation

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

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

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(): checkResourceID_method

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

Đế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: executed_2

Đế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:

  1. 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ủa admin.
    • $$: thay thế cho "
  2. Login với username/passwordsuper_admin/admin mà ta đã Inject rồi vào tính năng Create Action của AM: execute_prog

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.

  1. Exec exec_cmd