Linh tinh về Oracle Business Intelligence [part 3]

Peterjson
8 min readSep 16, 2021

Để tiếp nối series Oracle Business Intelligence, mình sẽ write-up 2 bug pre-auth RCE mà mình tìm được đợt này CVE-2021-2244 và CVE-2021-2456 (số đẹp vkl ( ͡° ͜ʖ ͡°) ). Bài viết này sẽ nói về 2 bug trên cũng như những tip/trick khi target Oracle BI.

Enviroment

Weblogic: 12.2.1.3.0

Oralce BI: 12.2.1.4.0

CVE-2021–2244

Lần trước thì mình có đã có một bài blog về cách tiếp cận khi exploit bug CVE-2019-2950 và sau đó là mở màn cho những bug trên mà tụi mình đã tìm thấy trong quá trình ngâm Oracle Business Intelligence. Sau khi đã pwn được target bằng cách response HTTP qua AMF Deserialization thì target mình nhắm tới đã upgrade và patch lên latest version. Vì sự cay cú này nên mình quyết định tìm bug Oracle BI và RCE lại target đó. Về cách setup và môi trường thì anh Jang đã trình bày rất rõ trong part 1.

Sau khi setup xong Oracle BI thì port 9502 thường sẽ được public ra internet để user access và thao tác cùng với đó port 9500 sẽ là port của Weblogic Console.

Trong bài viết của mình về CVE-2019-2950 mình cũng đã đề cập những module, application được deploy trên Weblogic để chạy Oracle BI. Để dễ hình dung hơn từ UI, sau khi login Weblogic Console các bạn access

Domain Structure -> Deployments

Ở tab Monitoring các bạn sẽ thấy những module được xài cho Oracle BI. CVE-2019-2950 nằm ở module jbips.war , và lần review này mình review hết những module còn lại và CVE-2021-2244 nằm ở module aps.war

Domain Structure -> Deployments -> Monitoring

Vào Oracle Home rồi search aps.war rồi unpack ra xem có gì thôi

aps module

Cơ bản chỉ có vài servlet, filter mình có thể access, và bug đã đến với mình một cách hết sức dễ dàng, không filter ObjectInputStream, gadget thì vô tận

RCE VKL ( ͡° ͜ʖ ͡°)

Công việc của mình hết sức đơn giản, lắp CVE-2020-2883 vào cùng với template response HTTP và cho ra đời pre-auth RCE CVE-2021-2244

CVE-2020–2883 response HTTP

Và đây là exploit mà mình đã submit cho ZDI, chắc do đó giờ làm những target khó nên mình luôn muốn payload RCE dành cho tất cả mọi case như kiểu response HTTP chẳng hạn, còn để persistence thì có thể găm fileless shell vào để thuận tiện cho công tác sau này ( ͡° ͜ʖ ͡°)

Thời điểm này sau khi mình submit cho ZDI xong, có bảo với anh @Jang về module này và chờ đợi vào blacklist từ Oracle ( ͡° ͜ʖ ͡°) để bypass như T3. Sau đó anh Jang đã dùng gadget inspector cào ra chain mới và chờ đợi patch từ Oralce (vì rice shirt rice money :( ). Nhưng cuộc đời không như là mơ, Oracle đã khôn hơn trước

fix bug làm gì, xóa cho lẹ :)

Oracle remove đi module này khỏi BI 12.2.1.4 và whitelist class khi deserialize ở version 11.1.2.4 .

ESSObjectInputStream instead of ObjectInputStream
ESSObjectInputStream implement JEP 290

Thế là không có bypass gì nữa, do đó anh @Jang quyết định public chain exploit kia vì nó khá là hay ho nhưng không có đất phô diễn :( . Để hiểu rõ hơn cơ chế cũng như cách tìm ra những gadget chain như thế này, các bạn có thể xem lại bài blog của anh Jang . Và đây là gadget mà anh Jang đã tìm ra với classpath Weblogic + Oracle BI.

BadAttributeValueExpException.readObject()
XmlSimpleList.toString()
AutoPopulatingList.get()
VectorSet.set()
CaseInsensitiveOrderedSet.add()
MapBackedSet.add()
EnvVars.put()
command injection VKL ( ͡° ͜ʖ ͡°)

Và đây là gadget chain của anh @Jang , khuyến khích các bạn debug để hiểu rõ hơn gadget này hoạt động như thế nào

demo

CVE-2021–2456

Trong thời gian chờ đợi ZDI mòn mỏi, mình có quay lại module jbips để xem Oralce fix CVE-2019–2950 như thế nào, và Oracle đã làm mình không thất vọng vì chỉ blacklist những gadget cũ. Điều này có nghĩa nếu mình muốn RCE thì phải tìm một gadget mới, context ở đây khó hơn Java Deserilaization native vì context này là AMF Deserialization. Để hiểu rõ cái khó của AMF các bạn có thể tìm đọc lại bài phân tích của mình về CVE-2019-2950 nhé.

Vậy thì Oracle đã blacklist như thế nào cho sau CVE-2019-2950?

blacklist class/package
check blacklist

Để tìm ra CVE-2021-2456 mình đã custom lại một tý gadget inspector cho phù hợp với context của AMF. Cụ thể là mình đã tạo một class mới implement SourceDiscovery và chỉ focus một số source phù hợp với AMF Deserialization.

  1. Với setter thì source cần phải thỏa mãn có Constructor không có args, setter phải có modifier là public và chỉ có một arg
  2. focus vào readExternal() thay vì readObject()
  3. blacklist đi những package, class mà Oracle đã blacklist ở AMF

Sau đó mình sẽ focus vào một số sink để có thể RCE

Ở đây mình bỏ đi sink về readObject() method bởi vì trong context của AMF, ngoại trừ stream input của chúng ta được wrap qua một stream khác thì lúc đó khả năng convert từ AMF -> Java Deser sẽ cao hơn, vì thế mình thêm một sink về ObjectInputStream để detect AMF stream từ user input sẽ được convert sang ObjectInputStream

Sau một hồi chạy và sàng lọc từng kết quả (pain :< ) thì mình đã ra được một chain khá như ý (AMF Deserialization -> Java Deserialization ) để tiện cho việc attack sau này như chạy java code, inject fileless shell, …

Vì hiện tại đang work from home và mình cũng không có đủ resource để chạy full classpath của Oracle BI (mình collect những jar từ ProcessHacker + cohenrence library) nên mình sẽ chạy demo ở package mà mình đã tìm ra cái chain cho CVE-2021-2456 ở eclipselink.jar. Lưu ý khi run nhớ thêm cả rt.jar để gadgetinspector có thể nhận được class ObjectInputStream.

org.eclipse.persistence.internal.sessions.factories.model.login.LoginConfig.setEncryptedPassword()
org.eclipse.persistence.internal.security.JCEEncryptor.decryptPassword()

Khá may mắn là cả AES và DES đều hardcore key trong lib này luôn nên việc generate ra một gadget hoàn chỉnh là điều hoàn toàn có thể

Ngoài LoginConfig thì JNDINamingServiceConfig cũng có chain tương tự. Chain này chỉ affect 12.2.1.4.0 còn version 11.x version của eclipselink.jar cũ hơn nên không có đoạn code như ver 12.2.1.4.0

org.eclipse.persistence.internal.sessions.factories.model.login.LoginConfig.setEncryptedPassword() 11.x

Vậy thì sau CVE-2021-2456 Oracle đã patch như thế nào? Oracle không sử dụng blacklist nữa mà thay vào đó là whitelist, việc whitelist này cũng dẫn đến việc rất khó bypass nhất là khi context AMF khó exploit hơn Java Deser

whitelist instead of blacklist
check whitelist

Do đó việc tìm một gadget chain khác để exploit cũng khó hơn và tốn công sức hơn. Mình quyết định tìm kiếm những target mới, task mới làm để học được nhiều hơn và kết thúc Oracle BI tại đây.

Bonus

Khi attack Oracle BI thì mình không chỉ focus vào RCE mà focus vào kết quả sau đó

  1. có chân internal để tiếp tục escalate tiếp phục vụ công tác về sau ( ͡° ͜ʖ ͡°)
  2. Data trên oracle về tài chính, doanh thu, tiền bạc ( ͡° ͜ʖ ͡°)

Vì tất cả các exploit mình làm đều là Java Deserialization vì thế mình dễ dàng custom để inject memory shell, và cũng có thể chạy được code Java (CommonsBeanutils1 chain -> load byte code)

Trong quá trình start/stop Oracle BI mình có để ý trong quá trình Bootstrap thì có đoạn này ( ͡° ͜ʖ ͡°)

Với tính tò mò thì mình đã thử tìm file credentials đó và thật may mắn khi ta hoàn toàn có thể decrypt credentials đó bằng WLST như bài blog này. Để đơn giản hơn thì mình tiếp tục inject một filter khác vào chỉ cần input đúng path file boot.properties thì sẽ decrypt ra được pass của Admin từ đó access những info quan trọng khác

Kết

Trong quá trình làm Oracle BI mình đã gain được nhiều thứ ngoài 2 bug trên, nhưng lại cảm giác không happy bằng việc phân tích/ dev exploit / improve exploit vì nó mang lại cảm giác bạn làm được một cái gì đó mà ít người làm được hơn ( ͡° ͜ʖ ͡°). Hy vọng mình sẽ có những findings mới mẻ hơn sau này. Cảm ơn các bạn đã đọc đến đây !

PoC CVE-2021–2456: https://github.com/peterjson31337/CVE-2021-2456

--

--