- vừa được xem lúc

Phân tích CVE-2023-39476 Inductive Automation Ignition Deserialization và vấn đề với Gadget Jython2

0 0 7

Người đăng: Real Alpha Man

Theo Viblo Asia

Một CVE mới từ một pháp sư trung hoa nào đó. Mình sẽ viết lại vì quá trình reproduce nó khá hay và trắc trở. Trong đó trung tâm bài này là Gadget Jython. Automation Ignition sử dụng jython-ia là library riêng thay vì jython-standalone trong ysoserial. https://github.com/frohoff/ysoserial/pull/200/commits/93fad0750ae075544d4df5f9a965ffe9724be939

Link bài writeup tại đây, các bạn có thể tham khảo.

Các bước install và debug đã được nêu rõ trong bài gốc, vì vậy mình đi luôn vào phần phân tích.

1. Vị trí gây lỗi

Nơi Object được serialize là com.inductiveautomation.metro.impl.codecs.JavaSerializationCodec#decode

Hàm này được gọi trong com.inductiveautomation.metro.impl.transport.ServerMessage#decodePayload

Và được gọi từ com.inductiveautomation.metro.impl.ConnectionWatcher#handleConnectionMessage nếu intentName khác _conn_init

Trong com.inductiveautomation.metro.impl.ConnectionWatcher#handle, nếu intentName bắt đầu bằngg _conn_ thì sẽ được gọi:

Được gọi từ com.inductiveautomation.metro.impl.protocol.websocket.WebSocketConnection#forward

Từ com.inductiveautomation.metro.impl.protocol.websocket.WebSocketConnection#onDataReceived

Tuy nhiên để có thể gọi được đến đây, address phải từ một nguồn không bị access denied.

com.inductiveautomation.metro.impl.protocol.websocket.servlet.DataChannelServlet#doPost đã gọi đến hàm onDataReceived

Servlet này có endpoint uri là /ws-datachannel-servlet

Tuy nhiên đây không phải là endpoint thực

Dynamic route đã được khai báo trong com.inductiveautomation.ignition.gateway.gan.WSChannelManager#restartChannels(Optional<ServerId>)

Như vậy endpoint là /system/ws-datachannel-servlet. Vấn đề ở chỗ nếu ta truy cập trực tiếp thì sẽ trả về 403

Debug tại com.inductiveautomation.metro.impl.protocol.websocket.servlet.DataChannelServlet#service ta thấy lí do là vì SSL=true nhưng ta truy cập từ giao thức http không thỏa mãn.

Nếu đổi thành https hoặc sử dụng port 8060 là port https của nó thì sẽ bị BAD_SSL

Như vậy, để thực hiện được khai thác, ta cần 2 setup Disable SSL và add WhitelistIP (hoặc để Unstricted) trong Gateway setting

2. Gadget

Gadget được tác giả sử dụng là Jython, tuy nhiên khi mình dựng gadget này (sử dụng POC từ bài writeup) đã gặp lỗi đó là

Đi vào lib, mình thấy Automation Ignition sử dụng library riêng là jython-ia-2.7.2.1 chứ không phải jython-standalone như trong gadget của ysoserial. Nếu mình sử dụng jython-standalone thì gadget hoạt động bình thường. Ta hãy cùng phân tích root cause.

Về sink của gadget, nó sẽ thực thi Py.eval(). Vì vậy command truyền vào sẽ là 1 dạng của hàm eval trong Python. Chi tiết hơn về cách thực thi code trong hàm eval, các bạn có thể tham khảo thêm tại đây. Trong file gadget, tác giả cũng đã note rằng nó thực thi hàm eval của python2. Nếu như server cài đặt Python2 thì nó sẽ có module os. Ví dụ

Dựa trên kết quả debug của server ta thấy đã có thể import os.

Tuy nhiên khi trên server là Python3 thì kết quả vẫn vậy =)). Nên mình xác nhận nó vẫn hoạt động trên Python3. Nhưng nó sẽ không hoạt động khi chúng ta cài đặt Python không thêm Python vào path env. Khi ấy, ta chỉ import được các default module. Trùng hợp thay mình đã làm điều đó và vô tình dính phải trường hợp này rồi mất thêm vài ngày nghiên cứu. Dưới đây là những gì mình thử trên máy Windows với việc cài đặt Python mà không thêm vào path env.

Khi lib này được load, class org.python.modules.Setup được load với các default module

Các module được khai báo theo dạng: name:class. Việc rút gọn như này có thể hỗ trợ khi import module. Ta có thể import với name hoặc import với class đều được mà không gặp lỗi. Như ta thấy, không có module os.

Ví dụ:

Như này có nghĩa là module _ast có tồn tại nhưng không tồn tại method hehe. Các method có thể thực thi được khai báo bên trong hàm classDictInit của từng module:

Ví dụ:

Vì vậy, nếu ta import java.lang.Runtime thì vẫn được nhưng thực thi getRuntime.exec thì không được, vì class kia không implement classDictInit.

Mình đã duyệt qua một lượt tất cả các method trong default module, không có method nào có thể lợi dụng để thực thi command. Chỉ có 1 module là PosixModule.getOSName() trông có vẻ hứa hẹn. Mudule này trả về tên của enum

Với Windows, nó sẽ trả về nt ( bằng "NT".toLowerCase()). Trong danh sách lib nt của Python thì có hàm system, execv, execve cho ta thực thi command

Tuy nhiên vẫn có một sự cay cú không hề nhẹ là trong ngữ cảnh của Jython-ia thì không có các hàm đó.

image.png

Mặc dù không thể sử dụng hàm system, chúng ta vẫn còn nhiều hàm khác có thể lợi dụng như mkdir, rmdir, open.

Như vậy ta có thể lợi dụng để viết 1 webshell. Thư mục webroot là webserver/webapps/main

Kết quả:

Nhưng đời không như là mơ

Lí do là vì Automation Ignition viết bằng spring và coi toàn bộ các file trong thư mục đều có content type là text. Công nhận cay.

Như vậy là trên Windows mình không nghĩ ra được cách gì khác là ghi thêm command vào file .bat để khi Automation Ignition khởi động lại sẽ tự thực thi trong trường hợp Python cài không theo mặc định.

Còn trên Linux các lib Python, path env luôn có sẵn nên nó có thể import os để thực thi command trực tiếp.

Trong Jython-standalone, nó có thêm folder lib riêng của nó nên có thể import os vào để run command, có lẽ vì thế nó mới có tên là standalone.

image.png

Đây chỉ là phần additional vì thực tế trường hợp không add Python vào path cũng khá hiếm xảy ra. Bạn đọc có cách làm hay hơn có thể để lại comment bên dưới.

Tài liệu tham khảo

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tổng hợp các bài hướng dẫn về Design Pattern - 23 mẫu cơ bản của GoF

Link bài viết gốc: https://gpcoder.com/4164-gioi-thieu-design-patterns/. Design Patterns là gì. Design Patterns không phải là ngôn ngữ cụ thể nào cả.

0 0 277

- vừa được xem lúc

Học Spring Boot bắt đầu từ đâu?

1. Giới thiệu Spring Boot. 1.1.

0 0 257

- vừa được xem lúc

Cần chuẩn bị gì để bắt đầu học Java

Cần chuẩn bị những gì để bắt đầu lập trình Java. 1.1. Cài JDK hay JRE.

0 0 37

- vừa được xem lúc

Sử dụng ModelMapper trong Spring Boot

Bài hôm nay sẽ là cách sử dụng thư viện ModelMapper để mapping qua lại giữa các object trong Spring nhé. Trang chủ của ModelMapper đây http://modelmapper.org/, đọc rất dễ hiểu dành cho các bạn muốn tìm hiểu sâu hơn. 1.

0 0 180

- vừa được xem lúc

[Java] 1 vài tip nhỏ khi sử dụng String hoặc Collection part 1

. Hello các bạn, hôm nay mình sẽ chia sẻ về mẹo check String null hay full space một cách tiện lợi. Mình sẽ sử dụng thư viện Lớp StringUtils download file jar để import vào thư viện tại (link).

0 0 55

- vừa được xem lúc

Deep Learning với Java - Tại sao không?

Muốn tìm hiểu về Machine Learning / Deep Learning nhưng với background là Java thì sẽ như thế nào và bắt đầu từ đâu? Để tìm được câu trả lời, hãy đọc bài viết này - có thể kỹ năng Java vốn có sẽ giúp bạn có những chuyến phiêu lưu thú vị. DJL là tên viết tắt của Deep Java Library - một thư viện mã ng

0 0 124