CVE-2023-34040 Spring Kafka Deserialization Remote Code Execution
Spring Kafka deserialization vulnerability in VMware security bulletin.
Last updated
Spring Kafka deserialization vulnerability in VMware security bulletin.
Last updated
Mô tả lỗ hổng:
Lỗ hổng này xảy ra khi ứng dụng sử dụng Spring for Apache Kafka không thực hiện việc kiểm tra và lọc đầu vào đúng cách trước khi tiến hành giải tuần tự dữ liệu từ Kafka.
Cụ thể, khi dữ liệu nhận được từ Kafka không đáng tin cậy hoặc chứa mã độc, quá trình giải tuần tự có thể kích hoạt việc thực thi mã không mong muốn trên hệ thống đích.
Nguyên nhân :
Lỗi này bắt nguồn từ việc sử dụng không an toàn thư viện Jackson (một thư viện phổ biến dùng để xử lý JSON trong Java) trong quá trình giải tuần tự dữ liệu.
Khi cấu hình không đúng, Jackson có thể giải tuần tự các lớp (class) không an toàn, tạo cơ hội cho kẻ tấn công gửi các đối tượng độc hại thông qua Kafka để thực thi mã từ xa.
Không cấu hình ErrorHandlingDeserializer
cho khóa và/hoặc giá trị của bản ghi:
Người dùng không cấu hình ErrorHandlingDeserializer
, là cơ chế để xử lý lỗi trong quá trình giải tuần tự của các bản ghi Kafka.
Cấu hình thuộc tính container không an toàn:
Người dùng đã thiết lập rõ ràng các thuộc tính container checkDeserExWhenKeyNull
và/hoặc checkDeserExWhenValueNull
thành true
. Các thuộc tính này kiểm tra các lỗi giải tuần tự khi khóa hoặc giá trị của bản ghi là null
.
Cho phép nguồn không tin cậy xuất bản tới một Kafka topic:
Người dùng cho phép các nguồn không đáng tin cậy gửi thông điệp tới một chủ đề Kafka (Kafka topic) mà không có các biện pháp xác thực hoặc bảo vệ thích hợp.
Note :
Mặc định, các thuộc tính checkDeserExWhenKeyNull
và checkDeserExWhenValueNull
là false
, và container chỉ cố gắng giải tuần tự các tiêu đề nếu ErrorHandlingDeserializer
được cấu hình.
ErrorHandlingDeserializer
ngăn chặn lỗ hổng này bằng cách loại bỏ bất kỳ tiêu đề độc hại nào trước khi xử lý bản ghi.
Explain :
Source Code Review Producer không an toàn
Producer này gửi một thông điệp Kafka với các tiêu đề (header) được thêm vào từ các thông điệp được gửi tới endpoint /message/send
.
Source code Consumer không an toàn
Config Consumer không an toàn
setCheckDeserExWhenKeyNull(true)
và setCheckDeserExWhenValueNull(true)
:
Khi cả hai thuộc tính này được đặt thành true
, ứng dụng sẽ cố gắng serialize các header của thông điệp Kafka ngay cả khi khóa (key) hoặc giá trị (value) là null
.
Điều này tạo 1 path dẫn đến có thể attack deserialize dữ liệu độc hại, vì nó cho phép quá trình này xảy ra mà không có kiểm tra an toàn nào được thực hiện.
Ở đây , attacker có thể lợi dụng để đưa vào các đối tượng Java đã được tuần tự hóa (serialized Java objects) độc hại.
Payload :
Quá trình
CustomExceptionClass
, với mục đích thực thi lệnh hệ thống khi nó được deserialize.
Lớp này sử dụng gadget từ Apache Commons Collections để tạo chuỗi mã có thể thực thi khi được deserialize.
Deserialize CustomExceptionClass
thành một chuỗi byte (byte stream) sử dụng cơ chế tuần tự hóa Java (Java serialization).
Gửi Payload Độc hại qua Kafka
Gửi Payload tới Kafka Topic:
Sử dụng một Kafka producer để gửi một thông điệp chứa payload độc hại tới một Kafka topic mà ứng dụng mục tiêu đang listen.
Thông điệp Kafka này bao gồm một header với khóa đặc biệt (springDeserializerExceptionKey
) chứa dữ liệu đã tuần tự hóa của đối tượng độc hại CustomExceptionClass
.
Ví dụ :
Ứng dụng Kafka Consumer nhận và deserialize
Ứng dụng Kafka Consumer nhận thông điệp:
Ứng dụng consumer đã được cấu hình không an toàn nhận thông điệp từ Kafka topic. Vì không sử dụng ErrorHandlingDeserializer
và bật các thuộc tính không an toàn (checkDeserExWhenKeyNull
và checkDeserExWhenValueNull
), ứng dụng sẽ cố gắng deserialize các tiêu đề của thông điệp.
Deserialize payload độc hại:
Consumer cố gắng giải tuần tự giá trị của header springDeserializerExceptionKey
. Nếu header này chứa một đối tượng độc hại đã được tuần tự hóa như CustomExceptionClass
, quá trình deserialize sẽ bắt đầu.
Thực thi mã độc từ chuỗi gadget:
Trong quá trình giải tuần tự, khối mã tĩnh trong CustomExceptionClass
được thực thi.
Gadget CommonsCollections được kích hoạt, tạo ra chuỗi các lệnh để gọi Runtime.getRuntime().exec("calc.exe")
, dẫn đến việc mở ứng dụng Calculator trên máy của nạn nhân.
Payload được gửi tới đâu?
Payload độc hại được gửi tới một Kafka topic cụ thể mà ứng dụng mục tiêu đang lắng nghe. Ví dụ, nó có thể được gửi tới một topic tên là "my-topic"
mà consumer đang lắng nghe:
Ai nhận payload? Ứng dụng Kafka consumer nhận payload thông qua một Kafka listener. Khi nhận được thông điệp, consumer sẽ kiểm tra các tiêu đề (header) của thông điệp để xử lý. Nếu consumer được cấu hình không đúng cách, quá trình giải tuần tự tiêu đề (header deserialization) sẽ dẫn đến việc thực thi mã độc.
Payload độc hại được gửi qua một Kafka producer đến một Kafka topic.
Consumer nhận thông điệp này và cố gắng giải tuần tự tiêu đề, dẫn đến việc thực thi mã từ xa (RCE) nếu cấu hình không an toàn.