[CVE-2017-3066] AMF Deserialization Remote Code Execution in Adobe ColdFusion

gumgumgumgum
3 min read

Tổng quan

Adobe ColdFusion là một nền tảng phát triển ứng dụng web mạnh mẽ, được Adobe Systems duy trì và phát triển. Nó cho phép các lập trình viên xây dựng các ứng dụng web động và mạnh mẽ một cách nhanh chóng bằng cách sử dụng ngôn ngữ lập trình CFML (ColdFusion Markup Language).

Lỗ hổng CVE-2017-3066 có liên quan tới AMF deserialization và được mô tả như sau:

Phân tích

Qua bài phân tích của codewhitesec ta biết được entrypoint của lỗ hổng nằm ở endpoint /flex2gateway/amf và theo config của web.xml, MessageBrokerServlet sẽ handle endpoint này với 1 init param là coldfusion.flex.ColdFusionMessageBrokerServlet

Đặt breakpoint tại MessageBrokerServlet.service() -> ColdFusionMessageBrokerServlet.service() -> MessageBrokerServlet.service(), tại đây sẽ gọi tiếp endpoint.service và vì endpoint class của flex2gateway/amfflex.messaging.endpoints.AMFEndpoint nên call tới AMFEndpoint.service()

AMFEndpoint kế thừa BasePollingHTTPEndpoint, BasePollingHTTPEndpoint kế thừa BaseHTTPEndpoint.

hai class trên không có override method HttpServlet.service(), nên khi MessageBrokerServlet invoke endpoint service, nó sẽ invoke 1 override method gần nhất, đó là BaseHTTPEndpoint.service().

tại hàm này gọi tiếp tới filterchain.invoke()

filterChain lại được init tại AMFEndpoint.createFilterChain()

hàm này trả về object serializationFilter ở đây là flex.messaging.endpoints.amf.SerializationFilter.

Như vậy filterchain.invoke() sẽ call tới SerializationFilter.invoke(), đây cũng chính là class sẽ handle AMF message của người dùng.

Tại đây body request sẽ được đưa vào AmfMessageDeserializer.readMessage() để thực hiện AMF deserialize

tiếp tục debug vào AmfMessageDeserializer.readBody(), method này tiếp tục gọi AmfMessageDeserializer.readObject() để reconstruct object

Từ đây tiếp tục gọi tới Amf0Input.readObject() -> Amf0Input.readObjectValue()

rồi lại call tới Amf3Input.readObject() -> Amf3Input.readObjectValue() -> Amf3Input.readScriptObject()

Method Amf3Input.readScriptObject() kiểm tra class đang được xử lý có implement Externalizable hay không.

Nếu ta dùng 1 Object có implement Externalizable thì sẽ call tới method readExternal() của object đang được xử lý -> object.readExternal()

Nếu object không implement Externalizable sẽ chuyển sang 1 nhánh khác để xử lý. Nhánh này sẽ lấy các property của class và sử dụng BeanProxy.setValue() để set lại các giá trị này.

lúc này BeanProxy sẽ cố gắng tìm các setter method của class và invoke nó.

Như vậy ta sẽ có hai hướng để khai thác AMF deser.

  1. Tìm một chain mà có thể lead từ Externalizable.readExternal tới object.readObject()
  2. Tìm một chain mà có setter method có thể gọi tới readObject()

Setter-based Exploit

Codewhitesec đã tìm được một class có thể lợi dụng setter method để trigger RCE.

Class org.jgroups.blocks.ReplicatedTree có method setState(byte[] new_state)

có thể thấy method này nhận vào mảng byte, sau đó gọi tiếp Util.objectFromByteBuffer().

Util.objectFromByteBuffer() nhận vào mảng byte và sau đó khởi tạo ObjectInputStream và gọi readObject()

Như vậy ta chỉ cần gói serialized object vào field state, ròi serialize tiếp bằng AMF là xong.

Trong lib của server có Commons BeanUtils 1.8.0 nên mình sẽ dùng chain CommonsBeanutils1 của ysoserial để RCE

Externalizable-based Exploit

Trong các class implement Externalizable thì có class org.apache.axis2.util.MetaDataEntry với method readExternal() như sau:

Tại đây gọi tới SafeObjectInputStream.readObject() -> SafeObjectInputStream.readObjectOverride()

cuối cùng readObjectOverride thực hiện gọi readObject của Java Native

Như vậy lúc này ta chỉ cần wrap serialized object vào MetaDataEntry.

Ref

  • https://codewhitesec.blogspot.com/2017/04/amf.html
  • https://codewhitesec.blogspot.com/2018/03/exploiting-adobe-coldfusion.html
  • https://docs.google.com/presentation/d/116DwvGitgknoiq_AOLmRlrkjCrUWfi38t_u-GdU4k2k/edit#slide=id.g8b4eedddee_0_773
0
Subscribe to my newsletter

Read articles from gumgum directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

gumgum
gumgum