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

[CVE-2019-16891] Liferay RCE via JSON Deserialization

0 0 12

Người đăng: Kaito Vũ

Theo Viblo Asia

Description

1.Liferay

Liferay Portal là giải pháp Cổng điện tử được thiết kế phù hợp với các mô hình ứng dụng trong các cơ quan, tổ chức và doanh nghiệp có nhu cầu phát triển hệ thống thông tin trên môi trường web nhằm thực hiện các giao dịch trực tuyến và sử dụng Intranet/Internet như một công cụ thiết yếu trong các hoạt động, cung cấp thông tin, giao tiếp, quản lý và điều hành, trao đổi và cộng tác.

2.CVE-2019-16891

Liferay Portal từ phiên bản 7.1.0 trở về trước bị dính lỗi RCE thông qua lỗ hổng liên quan tới json deserialization. Đây là lỗ hổng có thể khai thác mà không cần có tài khoản.

Setup Debug

1.Server

set JPDA_ADDRESS=8000 set JPDA_TRANSPORT=dt_socket set JRE_HOME=%ProgramFiles%\Java\jre1.8.0_202 (*thay đổi đường dẫn tương ứng) catalina.bat jpda start

2.Client Ở đây mình dùng Intellij để remote debug.

Mở project -> Edit configuration -> Add new config -> Remote JVM Debug -> config port 8000

Analysis

Entrypoints

JSONFactoryImpl là class sẽ handle hầu hết các tác vụ liên quan tới json (convert,deserialize,...).

Có rất nhiều method ở đây nên mình sẽ rải breakpoint đồng thời fuzz các entrypoint cho tới khi request trigger được breakpoint.Sau một hồi thì thử đến phần login thì đã trigger được breakpoint.

Quan sát stacktrace thì tìm được Chain từ HttpServlet qua tới đoạn call deserialize JSON.

HttpServlet.service() -> PollerServlet.service() -> PollerServlet.getContent() -> PollerRequestHandlerUltil.getPollerHeader() -> PollerRequestHandlerImpl.getPollerHeader() -> PollerRequestHandlerImpl.parsePollerRequestParameters() -> JSONFactoryImpl.deserialize()

Tóm tắt

  • Endpoint login : /web/guest/home
  • Endpoint triggers bug : /poller/receive
  • Method thực hiện deserialize : JSONFactoryImpl.deserialize(String)
  • Chain này cần phải được Authenticate

JSON Deserialize

Method thực hiện deserialize ở đây là JSONFactoryImpl.deserialize(String) từ đây call tới org.jabsorb.JSONSerializer.fromJSON() rồi lại call tới JSONSerializer.unmarshall() để tiếp tục deserialize object

Có thể thấy method này thực hiện lấy một loại serializer(class) thích hợp cho đoạn json string và thực hiện deserialize(unmarshall) nó theo cái serializer đó.

Set breakpoint tại method getSerializer để tìm các class thực hiện việc unmarshall

Đây là list những class có thể sẽ unmarshall object JSON truyền vào, được xét từ trên xuống dưới:Locale,Liferay,Primitive,... Trong list này thì thấy org.jabsorb.serializer.impl.BeanSerializer là đáng nghi nhất. Method BeanSerializer.unmarshall() có invoke Setter Method của cái object được khởi tạo từ JSON String ra:

public Object unmarshall(SerializerState state, Class clazz, Object o) throws UnmarshallException {
...
instance = clazz.newInstance();
...
while(i.hasNext()) { String field = (String)i.next(); Method setMethod = (Method)bd.writableProps.get(field); if (setMethod != null) { Object fieldVal; try { Class[] param = setMethod.getParameterTypes(); fieldVal = this.ser.unmarshall(state, param[0], jso.get(field)); } catch (UnmarshallException var13) { throw new UnmarshallException("could not unmarshall field \"" + field + "\" of bean " + clazz.getName(), var13); } catch (JSONException var14) { throw new UnmarshallException("could not unmarshall field \"" + field + "\" of bean " + clazz.getName(), var14); } if (log.isDebugEnabled()) { log.debug("invoking " + setMethod.getName() + "(" + fieldVal + ")"); } invokeArgs[0] = fieldVal; try { setMethod.invoke(instance, invokeArgs); } catch (Throwable var19) { Throwable e = var19; if (var19 instanceof InvocationTargetException) { e = ((InvocationTargetException)var19).getTargetException(); } throw new UnmarshallException("bean " + clazz.getName() + "can't invoke " + setMethod.getName() + ": " + e.getMessage(), e); } }
...

Với field là param key, dòng này sẽ lấy setter method của field từ class bd (class thỏa mãn method canSerialize() của BeanSerializer). Nếu setMethod tồn tại thì sẽ lấy param types và value của field sau đó invoke invokeArgs[0] = fieldVal; => Để trigger được unmarshall() bằng BeanSerializer thì class để trigger setter method không được Serializable, nếu class này Serializable thì nó sẽ dừng ngay ở LiferaySerializer khi gọi method getSerialize(), method này không invoke setter method.

Tóm tắt

Source class có thể trigger được BeanSerializer này là 1 class có dạng:

  • Có public constructor không có arg
  • Không implement Serializable
  • Có setter method có thể lợi dụng được!

Exploit

Class thỏa mãn các điều kiện trên là com.mchange.v2.c3p0.mbean.C3P0PooledDataSource

Class này có emty constructor, không implement Serializeable,có setter method có thể lợi dụng để deserialize object qua rmi BeanSerializer.unmarshall -> C3P0PooledDataSource.setJndiName.invoke(instance, jndiName) -> C3P0PooledDataSource.rebind(jndiName, obj) => rmi

POC

Authenticated endpoint:

https://github.com/DuyVuong/CVE-Analysis/assets/125139802/3ff2521f-563c-4308-a7b5-7f3a274fb162

Unauthenticated endpoint (https://dappsec.substack.com/p/an-advisory-for-cve-2019-16891-from) :

POST /c/portal/portlet_url HTTP/1.1
Host: liferay.victim.example.com
Content-Type: application/x-www-form-urlencoded; charset=UTF-8 parameterMap={"Json payload for deserialization in here!"}

https://github.com/DuyVuong/CVE-Analysis/assets/125139802/21490733-4e5c-455a-893f-1f7efb715b20

References

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 302

- 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 277

- 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 50

- 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 194

- 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 71

- 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 139