Tổng quan

CVE-2022-21445 (điểm CVSS 9,8), lỗ hổng là sự giải mã dữ liệu không đáng tin, được xác định tồn tại trong ADF Faces component, có thể bị tin tặc khai thác từ xa mà không cần xác thực (pre-authentication) để thực hiện RCE.

Lỗ hổng trên được phát hiện bởi 2 chuyên gia an ninh mạng PeterJson của VNG Corporation và Nguyen Jang của VNPT. Sau đó Oracle nhận được báo cáo này vào tháng 10 năm 2021 và phải mất tới 6 tháng, tức là đến tháng 4/2022 mới cho ra mắt bản vá.

Ở bài viết này, việc khai thác tập trung vào Oracle Bussiness Intelligence phiên bản 12.2.1.4.0

Phân tích - Tái hiện lỗ hổng

Cài đặt môi trường

Phía máy victim/target

Điều kiện: Cài window 10+ Pro hoặc Window Home (x64) đã active license hoặc dùng Window Server (ưu tiên dùng hàng của Oracle)

Bước 1: Cài Java, phiên bản jdk 8u112 hoặc lớn hơn (8Ux), link tải: JDKv8U112

  • Thêm JAVA_HOME với đường dẫn hướng tới thư mục jdk (không phải jre) Ảnh 1.1: Cài Java

Bước 2: Cài đặt Oracle Database 19c, link tải: Oracle 19c

  1. Chuẩn bị sẵn một folder để cài đặt database, tạo một đường dẫn như bên dưới và giải nén file zip database mới tải về vào đây C:\app\oracle\product\19c\db_home1

  2. Chạy file setup.application với quyền quản trị viên Ảnh 2.1: Chạy setup DB

  3. Thực hiện từng bước Step by Step như hướng dẫn tại Hướng dẫn cài DB

  4. Hết sức lưu ý: Tại bước 8/17, nhớ tích chọn Create as Container database để mở một pluggable db phục vụ cho tiến trình cài đặt Fusion Middleware sắp tới Ảnh 2.2: Khởi tạo Pluggable Database

Tại bước 9/17, chọn character là Unicode (AL32UTF8) Ảnh 2.3: Chọn Unicode

  1. Sau khi tiến trình cài hoàn tất thì hãy kiểm tra cẩn thận tại Services của Window để đảm bảo rằng các 4 servide chính như hình bên dưới có trạng thái là RUNNING Ảnh 2.4: Cài thành công

Ảnh 2.5: Check service

  1. Tạo một tài khoản oracle database mới theo các bước:
  • Terminal Administrator -> sqlplus / as sysdba
  • Tạo user hệ thống system: alter user system identified by system_password account unlock;
  • Kiểm tra sự tồn tại của user system: select username from dba_users;
  • Thiết lập môi trường: alter session set “_oracle_script”=true;
  • Tạo user thông thường hr: create user hr identified by user_password;
  • Cấp quyền: grant all privileges to hr;
  • Mở khóa tài khoản – chỉnh mật khẩu: alter user hr identified by hr_pass account unlock;
  • Tạo tài khoản hệ thống mới: alter user sys identified by sys_pass account unlock;

Bước 3: Cài đặt SQL Developer, phiên bản no-jre, link tải: SQLDev-NoJRE Ảnh 3.1: Tải SQL Developer

  • Chạy file sqldeveloper.application với quyền quản trị viên Ảnh 3.2: Khởi chạy SQL Developer

  • Thiết lập các thông số cho một connection mới như hình bên dưới, lưu ý thay đổi Username và Password (như ví dụ mẫu ở trên là hr), Hostname(mặc định là localhost), Port(mặc định là 1521), SID (là global database name đã cài ở bước 2) Ảnh 3.3: Thiết lập thông số SQL Developer

  • Nếu khi chọn Test mà có thông báo là Success thì kết nối thành công, chọn Connect

Bước 4: Cài đặt Fusion Middleware Infrastructure (FMW) phiên bản 12.2.1.3.0, link tải FMW_ver_12.2.1.3.0 Ảnh 4.1: Tải FMW

  • Tạo đường dẫn cho thư mục cài FMW theo dạng C:\Oracle\Middleware\Oracle_Home
  • Thực hiện lần lượt các bước theo hướng dẫn: Hướng dẫn cài FMW

Bước 5: Cài đặt Oracle Bussiness Intelligence (OBIEE) phiên bản 12.2.1.4.0, link tải: OBIEE_ver_12.2.1.4.0

  • Chạy file setup_bi_platform-12.2.1.4.0_win64.exe với quyền quản trị viên Ảnh 5.1: Chạy file cài OBIEE

  • Cài đặt step by step theo Hướng dẫn cài OBIEE

  • Chú ý: Đường dẫn của BI phải giống đường dẫn đã cài đặt FWM, như ở đây là Oracle/Middleware/Oracle_Home Ảnh 5.2: Đường dẫn của BI phải giống với FWM

Bước 6: Thiết lập BI Schema bằng tiện ích Repository Creation Utility (RCU)

  • Tại đường dẫn C:\Oracle\Middleware\Oracle_Home\oracle_common\bin, chạy file rcu.bat với quyền admin

  • Thực hiện lần lượt các bước sau

Ảnh 6.1: Create Repository

Ảnh 6.2: Database Connection Detail

Ảnh 6.3: Select Component

Ảnh 6.4: Schema Password

  • Cuối cùng, hãy ấn Create để hệ thống tạo BI Schema

Bước 7: Thiết lập biến môi trường cho OBIEE

  • Vào Control Panel > System > Advanced system settings > Advanced > Environment Variables > New System Variable Ảnh 7.1: Biến môi trường

Bước 8: Tạo BI Domain

  1. Tại đường dẫn C:\Oracle\Middleware\Oracle_Home\bi\bin, chạy file config.cmd với quyền admin

Ảnh 8.1: Chạy file config

  1. Ở bước 1: Chọn cả 3 component, trong đó Essbase là OLAP server, Business Intelligence Enterprise Edition là BI Analytics và Business Intelligence Publisher là BI Publisher

Ảnh 8.2: Chọn component

  1. Ở bước 3: Thiết lập domain mới như hình dưới, !! HÃY GHI NHỚ MẬT KHẨU CHO DOMAIN VÌ SẼ RẤT KHÓ ĐỂ LẤY LẠI. và hãy để domain là bi vì nó là mặc định.

Ảnh 8.3: Tài khoản domain

  1. Ở bước 4: Cập nhật thông tin domain cho Database

Ảnh 8.4: Cập nhật thông tin

  1. Ở bước 8: Nếu như tiến trình thuận lợi thì sẽ có kết quả như hình dưới

Ảnh 8.5: Cấu hình thành công

  1. Nếu mọi thứ đều Done thì lưu lại file thông tin của OBIEE bước tiếp theo, login vào url mở:
  1. Một số lỗi có thể diễn ra
  • Tại bước 4, hệ thống báo fail to logon thì hãy kiểm tra lại mật khẩu của domain xem có chính xác không

  • Tại bước 8, nếu hệ thống báo lỗi như ảnh dưới thì hãy kiểm tra xem bạn đã active bản quyền window chưa và window của bạn có như phần điều kiện mô tả không.

Ảnh 8.6: Lỗi bản quyền

  • Lỗi chưa thêm BI_HOME_PRODUCT, xem lại Bước 7
  • Update lỗi ...

Bước 9: Sau khi setup xong truy cập vào bi domain vừa tạo ở đường dẫn $Oracle_Home\user_projects\domains\bi\servers\AdminServer\tmp_WL_user\adf.oracle.domain.webapp\i83uao

  • Tiến hành copy hết tất cả file jar ở đây cho vào một thư mục riêng, share tới máy attack (môi trường dựng lap thì làm vậy, khi attack thực tế thì tại máy attack cũng phải cài như ở máy target để lấy được source code)

  • Thêm cả thư viện coherence.jar ở đường dẫn $Oracle_Home\coherence\lib vào thư mục này.

  • Đây là thư mục quan trọng quyết định đến payload thành công hay không bởi vì mỗi phiên bản FMW hay BI hay môi trường mỗi máy cài thường sẽ khác nhau nên cần chính xác phiên bản nhằm hạn chế rủi ro hay exception bật ra trong lúc truyền payload.

Bước 10 (chỉ thực hiện nếu cần remote debug, nhắc lại là nếu test ngoài môi trường thật thì do không thể setup máy nạn nhân tùy thích, bởi vậy thì attacker cần thực hiện cả thiết lập máy target trên máy của mình để có thể remote debug kiểm tra lỗi)

  • Cài mozilla, thêm burp Proxy với port 8181

  • Bật Remote Debug phía BI server

    Truy cập localhost:9500/console

    Tại Domain Structure -> chọn bi -> Environment -> Servers

Ảnh 10.1: Domain Structure

Hai server sẽ hiển thị, đó là AdminServer của weblogic và bi_server1 của BI

Ảnh 10.2: Danh sách server hiển thị

Chọn Lock & Edit ở góc cùng bên trái, tích chọn bi_server1 để chỉnh sửa cấu hình. Tại đây, chọn tiếp vào Configuration -> Server start -> Kéo xuống cuối cùng, chọn Advance (nếu có) -> Chọn nhập vào Arguments -> Nhập thông số debug:

-Xdebug -Xnoagent – Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n

(có thể thử với 0.0.0.0:5005 nếu sau này có lỗi không khởi động lại được bi_server1)

Nhập mật khẩu weblogic (khi nãy thiết lập ở phần Config BI Domain)-> Apply change & Restart

Khởi động terminal Administrator -> Điều hướng đến đường dẫn $Oracle_Home\user_projects\domains\bi\bitools\bin chạy ./stop.cmd và ./start.cmd để khởi động lại bi_server1, trong quá trình khởi động lại nếu không có lỗi xảy ra thì debug đã được mở và lắng nghe tại cổng 5005 như trên. Nếu có lỗi xảy ra thì kiểm tra lại thông số debug ở trên xem có thừa khoảng trống hay sai ở phần address không.

Phía máy attack

Bước 1: Tải IntelliJ IDEA Ultimate, active bằng code tìm trên github.

Bước 2 (Chỉ làm bước này nếu như quá trình tấn công có nhảy lỗi như 500 Server Error, ... thì đó là do có exception trong payload)

  1. Chỉnh lại phiên bản jdk – sdk của project về phiên bản giống như ở máy target (cách cài như ở Phần máy target - Bước 1)

  2. Tạo một Project trống nhằm phân tích source code, phục vụ remote debug, 3. Tiến hành thêm hết file jar ở thư mục nhận được từ máy target vào project này

    Project Structure -> Modules -> Chọn dấu + -> 1 JARS or Directories -> Add cả thư mục jar.

Ảnh 11.1: Thêm file jar

Ảnh 11.2: Kết quả

  1. Thiết lập Remote Debug

    Run -> Edit Configurations -> + -> Remote JVM Debug

Ảnh 12.1: Thiết lập Remote Debug

 Chạy Remote Debug, nếu có thông báo ở console: Connected … thì đã thành công.

Ảnh 12.2: Chạy Remote Debug

Bước 3:

  • Clone code trong repository này về máy, xóa file coherence.jar cũ trong thư mục lib và thay bằng file mà bạn đã nhận từ máy target từ bước phía trước.

  • Kế đó, thêm vào một project chạy bằng IntelliJ, thêm các file jar trong lib với lựa chọn Add as library

  • Kiểm tra lại tên của class LambdaIdentity$.... cho đúng với phiên bản Weblogic, nếu có thay đổi hãy refactor lại file và chỉnh lại tên của file đó.

    Weblogic 12.2.1.3: LambdaIdentity$E12ECA49F06D0401A9D406B2DCC7463A

    Weblogic 12.2.1.4: LambdaIdentity$423B02C050017B24DB10DFF759AA56BF

  • Chỉnh sửa lại đường dẫn đến file LambdaIdentity$....class trong file Main.java. Để lấy được đường dẫn chính xác, có hai cách để làm: Có thể chạy javac file jar để nó sinh ra file .class; một hướng khác nữa là comment lại code của hàm main, xong đó chạy project này bình thường, đường dẫn file class hoàn toàn có thể tìm thấy ở thư mục target.

  • Kiểm tra lại jdk và sdk của project sao cho nó giống với bên máy target.

Phân tích code BI và code sinh payload

Phân tích code BI

  1. Tại đường dẫn $Oracle\Middleware\Oracle_Home\user_projects\domains\bi\servers\AdminServer\tmp_WL_user\em\fw8wi5\war\WEB-INF

Ta thấy file web.xml, file này mô tả các mối quan hệ ánh xạ liên quan tới servlet-mapping. "resources" là servlet liên quan đến tài nguyên hệ thống, chứa những dữ liệu và thông tin quan trọng, bởi thế đây là vị trí thường bị các attacker nhắm tới.

Ảnh 13.1: Mối quan hệ servlet-mapping

  1. Đi sâu vào class ResourceServlet, cụ thể là org.apache.myfaces.trinidad.webapp.ResourceServlet ta sẽ thấy được hàm doGet với nhiệm xử lý request get được gửi đến server.

Ảnh 13.2: hàm doGet

  • Tại đây, thông qua method _getResourceLoader(), một loader mới được tạo từ request đầu vào. Đồng thời một resourcePath cũng được khởi tạo và nhận giá trị servletPath và servletInfo thông qua method getResourcePath với tham số truyền vào là request. Loader đó sẽ gọi đến hàm getResource(resourcePath), cố gắng nạp resource từ rrquest đầu vào và tìm nó thông qua hàm org.apache.myfaces.trinidad.resource.ResourceLoader.getResource.findResource(), sau cùng giá trị tìm được sẽ được truyền cho một instance url của lớp URL.class.

Ảnh 13.3: hàm getResource

  • _getResourceLoader duy trì ConcurrentMap để lưu trữ mối quan hệ ánh xạ giữa servletPath và loaders. Mối quan hệ này được định nghĩa rõ ràng trong oracle.adfinternal.view.resource.rich.RenderKitResourceLoader

Ảnh 13.3: class RenderKitResourceLoader

  • Method _register trong hàm RenderKitResourceLoader() được gọi đến và truyền vào các regex + loader tương ứng, sau đó trả về super.register là hàm cha của nó. Hàm này sẽ thêm vào concurrentmap_loaders giá trị partern và loader tương ứng. Do đó, khi loader được khởi tạo tại hàm doGet() và nhận tham số request đầu vào thì giá trị servletPath từ url request gửi đến được lấy để truyền vào _loader.get() nhằm lấy ra servlet tương ứng.

Ảnh 13.4: method _register

Ảnh 13.5: method register (method cha)

  • Tác giả của lỗ hổng cho rằng trong các class chứa method override lại findResource(), thì oracle.adfinternal.view.resource.rich.RemoteApplicationResourceLoader là class chứa nguy cơ dẫn đến deserialization. Hãy cùng phân tích nó để tìm kiếm lí do.

Phân tích hàm findResource() trong RemoteApplicationResourceLoader.class

Ảnh 13.6: hàm findResource()

Hàm này trả về một method chứa giao thức tùy chỉnh RAStreamHandler(). RAStreamHandler sẽ tạo một đối tượng URLConnection với giá trị là new RAURLConnection

Ảnh 13.7: method RAStreamHandler()

Hàm RAURLConnection call hàm _getPathBean

Ảnh 13.8: method RAURLConnection ()

hàm _getPathBean chứa một đối tượng bean được tạo thông qua việc gọi đến hàm getInstanceFromString() làm nhiệm vụ xử lý chuỗi string nhận vào để lấy ra các key tương ứng (filter).

Ảnh 13.9: hàm _getPathBean

Chuỗi bean đầu vào sẽ được chuyển đổi thông qua lớp SerializationUtils từ dạng URL encoded thành một đối tượng URLEncoderPathBean. Nếu mọi thứ vẫn ổn input phía sau sẽ tiếp tục được truyền vào hàm fromURLEncodeString().

Ảnh 13.10: hàm getInstanceFromString()

Ảnh 13.11: hàm fromURLEncodedString()

Trường hợp chuỗi đầu vào gặp lỗi sẽ nhảy ra exception. Exception chủ yếu đến từ lib được dùng trong payload, do lệch phiên bản hoặc do đường dẫn đến file Lambda sai.

Tại hàm fromURLEncodedString(), một hàm fromString được trả về với tham số url, và code của nó như sau:

Ảnh 13.12: hàm fromString()

Ở hàm fromString data được readObject() và return lại. Có thể thấy input từ đầu vào không hề bị filter. chảy qua nhiều hàm và cuối cùng được deserialize ở fromString(). Đây chính là sink phục vụ khai thác. Có sink rồi, vậy giờ cần tìm source là xong.

  1. Tìm source: như đã phân tích phía trên, để tìm được source thì cần phải xác định url request đầu vào. Ta thấy, để gọi được hàm findResource() thì phải có quyền điều hướng tới class RemoteApplicationResourceLoader. Tại class RenderKitResourceLoader đã định nghĩa rất rõ:
this._register("/.*/remote/(.*)", new RemoteApplicationResourceLoader());

Do đó, để gọi được đến class kể trên thì ta cần có regex dạng “/./remote/(.)”. Bởi thế, khi router hay đường dẫn đầu vào có dạng /em/afr/foo/remote/payload thì nó sẽ thỏa mãn cấu trúc được quy định ở file này, khi đó RemoteApplicationResourceLoader sẽ được sử dụng như loader tại doGet, và file class tương ứng oracle.adfinternal.view.resource.rich.RemoteApplicationResourceLoader sẽ gọi đến hàm findResource() được override trong đó.Thế cho nên nếu như truyền payload đến đúng địa chỉ thì dữ liệu sẽ được được truyền đi dễ dàng mà không vướng phải filter.

Đây là url sau cùng dùng cho khai thác: hostname:port/contextApp/afr/foo/remote/payload/

Trong đó contextApp là một trong những path khi mới cài đặt xong OBIEE sẽ có như /em; /bicomposer; ….

Foo là chuỗi bất kỳ

Payload là chuỗi sinh ra khi chạy hàm Main của Project tấn công đã chuẩn bị.

Phân tích code dùng để tạo payload

Project này tuân theo gadget chain của CVE-2020-14644

file Lambda

Class LambdaIdentity$E12ECA49F06D0401A9D406B2DCC7463A được kế thừa từ AbstractRemotable được sử dụng để tương tác với hệ thống từ xa.

Với việc sử dụng Java Reflection API, attacker có thể dễ dàng lấy ra WorkAdapter từ luồng thực thi hiện tại.

Kế đó sẽ lấy tiếp trường connectionHandler của WorkAdapter và thực hiện truy vấn để lấy ra ServletRequest và ServletResponse từ connectionHandler.

Tiếp theo, lấy ra giá trị của tiêu đề "cmd" từ yêu cầu (ServletRequest), sau đó kiểm tra nếu "cmd" không rỗng, thực hiện một lệnh shell tương ứng với hệ điều hành hiện đang chạy (Windows hoặc Linux/Unix).

Đọc kết quả từ lệnh shell và gửi kết quả đó về phản hồi (ServletResponse).

Nếu có bất kỳ lỗi nào xảy ra trong quá trình thực thi, chúng sẽ được in ra màn hình console thông qua phương thức printStackTrace().

Id phía sau tên lớp LamdaIdentity phụ thuộc vào phiên bản của weblogic server, là một chuỗi được mã hóa theo giá trị băm MD5 của class com.tangosol.internal.util.invoke.ClassIdentity, và vì ở mỗi phiên bản thì class này sẽ khác nhau nên như đã nói, để payload không bị lỗi thì phải kiểm tra kỹ cái này.

Tại đây, một biến cmd được lấy từ header trong request đầu vào, sau đó được thêm vào câu lệnh Runtime.getRumtime.exec() bên dưới, được mã hóa và giải mã theo dạng mã hexa md5, sau khi được truyền đến hệ thống OBIEE sẽ trả về giá trị được deserialization.

Cuối cùng, tại hàm Main, một đối tượng RemoteConstructor được tạo ra, thông qua thư viện SerializationUtils để được chuyển đổi thành một chuỗi URL encoded. Chuỗi này sẽ truyền trực tiếp vào url source, gây ra cơ hội cho các attacker chèn lệnh cmd tùy ý.

Hàm Main

Tái hiện khai thác

Khai thác /em

Khai thác /em

Reference

  1. https://peterjson.medium.com/miracle-one-vulnerability-to-rule-them-all-c3aed9edeea2

  2. https://testbnull.medium.com/oracle-access-manager-pre-auth-rce-cve-2021-35587-analysis-1302a4542316

Author of Vulnerability: Jang Nguyen & Duc PeterJson