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

Theo report, lỗ hổng Unauthentication SQL Injection của Manage Engine Application Manager nằm ở ở REST API module. Review source code thì thấy module này nằm ở Rest API Servlet bớ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 các GET/POST requests đến APIServlet đều gọi chung đến method APIServlet.process(), servlet này kiểm tra request có thỏa mãn điều kiện bỏ qua kiểm tra apikey, nếu không thỏa mãn thì yêu cầu authenticate cũng như cung cấp apikey: APIServlet.process

Method CommonAPIUtil.skipRESTAPIKeyValidation(): CommonAPIUtil skipRESTAPIKeyValidation

Ở đây url được split thành các node dựa vào ký tự /, nếu node thứ 3 là ApmAdminServices thì sẽ thỏa mãn điều kiện bỏ qua kiểm tra apikey và trả về true, ví dụ: /AppManager/json/ApmAdminServices/* sẽ thỏa mãn.

Nếu điều kiện đúng sẽ gọi đến method APIServlet.validateMethod(): validateMethod

Nếu node 3ApmAdminServices thì method name sẽ được gán bằng node 4, method này lấy method name cần gọi rồi gọi đến APIServlet.validateAndGatherData(). match_method

Method này kiểm tra lại request hiện tại có quyền truy cập hay không cũng như 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 2json (isJsonFormat==true) thì gọi đến APIServlet.validateAndGenerateJSONFeed(): checkResourceID_method

Tiếp tục luồng, nếu method name match với checkResourceID sẽ lấy value resourceids từ request parameter và gọi đến DependentDeviceUtil.getInstance().checkResourceIDAndGetListToBeRemoved(): endpoint_1

Tại đây là sink của lỗ hổng SQLi khi thực hiện nối chuối với tham số resourceids mà ta có thể kiếm soát.

Method kiểm tra EnterpriseUtil.isManagedServer() kiểm tra xem liệu đây có phải là remote server, nếu đúng thì tạo request tương tự đến địa chỉ server đó, không thì đơn giản là execute query trên: executed_2

Đến đây ta có thể exec sql command mà không cần authenticated.

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