Description

Tiếp nối series “linh tinh” của Jang, mình sẽ viết về lỗ hổng Java Deserialization RCE CVE-2021–2302 trên Oracle Business Intelligence (BI), được mình tìm thấy đợt cuối năm ngoái.

CVE-2020-2302 được Oracle công bố vào tháng 4/2021

CVE-2020-2302

Lỗ hổng này tồn tại trên product Oracle Platform Security for Java (OPSS), đây là framework có thể được sử dụng trong môi trường của Oracle cũng như bên thứ ba, trong đó có Oracle Business Intelligence.

Để sử dụng BI thì phải cài đặt nó trên nền tảng Oracle Fusion Middleware hay chính là Oracle Weblogic, CVE-2021–2302 được mình khai thác qua entrypoint tại giao thức T3 của Weblogic cổng 9500, những ai chưa biết về entrypoint huyền thoại này thì có thể tham khảo bài viết này của tác giả. Vì report đã lâu nên đợt này xem lại mới để ý thấy Oracle công bố thành HTTP, đây có thể là do nhầm lẫn của Oracle. Gadget Chain lần này rất đơn giản, khá phù hợp với những bạn mới tìm hiểu về kiểu lỗ hổng này.

Vulnerability Detail

Setup môi trường

Phần dựng lab và cách debug đã được Jang đề cập tại part 1, ngoài ra các bạn cũng có thể tham khảo link setup rõ ràng hơn dưới đây

https://www.peakindicators.com/blog/install-and-configure-obiee-12c

Lab của mình được setup như sau:

  • Orace Weblogic Server: 12.1.2.3
  • Oracle Business Intelligence: 12.1.2.4
  • Oracle Database 19c

Phân tích lỗ hổng

Nói qua một chút về ý tưởng tìm kiếm, đợt cuối năm ngoái, Weblogic có tồn tại CVE-2020–14882, đây cũng là lỗ hổng Java Deserialization nhưng đi qua giao thức HTTP. Khi research thì mình có để ý cách lỗ hổng này được trigger. Nói một cách ngắn gọn thì CVE-2020–14882 lợi dụng đoạn code có tạo mới instance của class bất kì, mà constructor của class đó có thể dẫn tới RCE, phần dưới của bài viết mình sẽ phân tích kĩ hơn. Ý tưởng kiểu này thì đã có từ lâu, nhưng không hiểu sao mình lại không để ý lắm. Chuyển sang research BI, lúc này không gian tìm kiếm Gadget chain không chỉ gói gọn trong Weblogic nữa mà được mở rộng ra, thêm rất nhiều lib của BI, nên là trước hết là mình sửa tool (như hình dưới) và chạy thử xem sao thì đâu đó khoảng 10–15 phút là tìm ra Gadget chain của CVE-2021–2302 sẽ được phân tích chi tiết tiếp theo.

Mình thêm điều kiện này và comment toàn bộ điều kiện khác trong method isSinK() thuộc class GadgetChainDiscovery của tool.

GadgetInspector

The Sink

Nơi trigger RCE nằm tại class oracle.security.jps.az.internal.common.principals.UnresolvedPrincipal.getResolvedPrincipal()

oracle.security.jps.az.internal.common.principals.UnresolvedPrincipal.getResolvedPrincipal()

Luồng hoạt động ngắn gọn của method này như sau:

  • Tại dòng số 58, Class.forName(…) thực hiện load một lớp có tên chính là một chuỗi lấy từ this.principalEntry.getClassName()
  • Tiếp theo, tìm trong class được load nói trên một constructor nhận vào một argument kiểu String
  • Cuối cùng là thực hiện tạo một instance mới của class đó với giá trị argument lấy từ this.principalEntry.getName() truyền vào constructor

Vậy để lợi dụng luồng hoạt động trên dẫn tới RCE ta cần thỏa mãn các điều kiện sau:

1. Có quyền kiểm soát biến principalEntry, để từ đó có thể kiểm soát giá trị trả về từ this.principalEntry.getClassName() và this.principalEntry.getName()

2. Tìm được một class có constructor nhận vào 1 argument kiểu String và có thể lợi dụng để RCE

Trong Java Deserializaton, nếu biến được khai báo với keyword static hoặc transient thì thường không thể kiểm soát được giá trị của các biến này bởi:

  • Keyword static thể hiện biến đó sẽ không tham gia vào quá trình serialize/deseriaize. Làm về Java Deserialization mà thấy biến mình cần kiểm soát có keywork này thì thoi bỏ đi.
  • Keyword transient thể hiện biến đó vẫn sẽ tham gia vào quá trình serialize/deseriaize. Tuy nhiên quá trình sẽ làm ngơ giá trị của biến và không có sự thay đổi nào xảy ra, trừ khi dữ liệu được serialize bằng java.io.Externalizable interface. Vậy nên tương tự như trên nếu có source nhận dữ liệu qua java.io.Externalizable interface thì xem xét nghiên cứu tiếp.

Trong hợp cụ thể đang phân tích, biến principalEntry được khai báo với keyword private, như vậy ta hoàn toàn có thể kiểm soát giá trị của biến này khi viết payload, thỏa mãn điều kiện số 1.

oracle.security.jps.az.internal.common.principals.UnresolvedPrincipal

Đối với điều kiện số 2, việc tìm ra một class như vậy đã được đề cập và ứng dụng trước đó trong nhiều lỗ hổng. Class mình chọn cho lỗ hổng này là com.tangosol.coherence.mvel2.sh.ShellSession. Constructor của class này nhận vào argument init kiểu String, sau đó truyền init vào method exec()Method exec() sẽ thực hiện MVEL expression, có thể lợi dụng để RCE.

com.tangosol.coherence.mvel2.sh.ShellSession

com.tangosol.coherence.mvel2.sh.ShellSession.exec()

Ngoài com.tangosol.coherence.mvel2.sh.ShellSession, còn một số class khác có thể tham khảo tại đây, lưu ý là các class này yêu cầu hệ thống phải có outbound.

Cả hai điều kiện nêu trên đều đã thỏa mãn, vậy để tới được sink thì chắc chắn là phải đi tìm source.

The Source

Thường thì source sẽ ở một class khác và phải kinh qua nhiều “kiếp nạn” thì mới tới được sink nhưng oracle.security.jps.az.internal.common.principals.UnresolvedPrincipal cực kì “ưu ái” mình khi không cần phải đi đâu xa, source xuất hiện luôn trong class hơn nữa là có tận 3 cái để lựa chọn cho thoải mái 😅

oracle.security.jps.az.internal.common.principals.UnresolvedPrincipal

equals(), hashCode()  toString() đều có thể dùng để làm source, với CVE này mình chọn toString() cho đơn giản.

Việc cuối cùng là kết hợp tất tần lại sẽ được một Gadget chain như sau:

CVE-2021–2302

Vulnerability Proof

Toàn bộ PoC của mình để tham khảo có thể truy cập dưới đây:

https://github.com/quynhle7821/CVE-2021-2302

Conclusion

CVE-2021–2302 đã được Oracle đã chính thức phát hành bản vá tại https://www.oracle.com/security-alerts/cpuapr2021.html và liên tục cập nhật các bản vá mới 3 tháng một lần tại https://www.oracle.com/security-alerts/, người dùng được khuyến cáo nên vá hệ thống thường xuyên. Ngoài ra, nếu không có nhu cầu sử dụng T3 Weblogic, thực hiện vô hiệu hóa giao thức này để phòng tránh các lỗ hổng có liên quan trong tương lai.

 

Cảm ơn các bạn đã đọc bài!

1.169 lượt xem