1 of 66

CVE-2017-3066 study case

@peterjson

2 of 66

$id

Security Enginneer @ VNG Corporation

Researching / Pentesting / Redteam

Mainly focus on server side bug, especially about Java / .NET

Twitter: https://twitter.com/peterjson

Telegram: https://t.me/peterjson

3 of 66

CVE-2017-3066

4 of 66

CVE-2017-3066 affected by CVE-2017-3066

5 of 66

CVE-2017-3066 - ENV setup

ColdFusion 11: https://drive.google.com/embeddedfolderview?id=0B9u7ipD8e7-oaW5fNlVvb1ZhQTQ#list

update verion 11: https://helpx.adobe.com/coldfusion/kb/coldfusion-11-updates.html

IDEA: IntelliJ + cài jdk ver 8 trên host

VM: ubuntu + cài jdk 8 trên VM

6 of 66

CVE-2017-3066 - setup remote debug

  • Copy all jar file to /tmp/dumpJars

$ find /opt/coldfusion11/ -name *.jar -exec cp {} /tmp/dumpJars \;

  • create empty IntelliJ Project then add library to project (with /tmp/dumpJars)
  • add jdwp to jvm.config file in bin/ folder of cfusion
  • restart server

7 of 66

CVE-2017-3066 - setup remote debug

8 of 66

CVE-2017-3066 - setup remote debug

9 of 66

CVE-2017-3066 - Identify the bug

  • viewing config in /opt/coldfusion11/cfusion/wwwroot/WEB-INF
  • How to find the entry point of the vulnerability ?
  • read web.xml
    • servlet, mapping of each servlet
    • filter
    • other config ?

10 of 66

CVE-2017-3066 - Identify the bug - flex module

This CVE was effected as third module (Apache Blaze DS) library

=> /WEB-INF/flex is config dir of this module

11 of 66

CVE-2017-3066 - Identify the bug - /flex/services-config.xml

12 of 66

CVE-2017-3066 - Identify the bug - back to web.xml

servlet class

param when init this servlet

13 of 66

CVE-2017-3066 - Servlet Life Circle

14 of 66

CVE-2017-3066 - BoostrapServlet.init()

15 of 66

CVE-2017-3066 - BoostrapServlet.init()

16 of 66

CVE-2017-3066 - BoostrapServlet.service()

17 of 66

CVE-2017-3066 - ColdFusionMessageBrokerServlet.service()

18 of 66

CVE-2017-3066 - MessageBrokerServlet.service()

19 of 66

CVE-2017-3066 - AMFEndPoint.service()

20 of 66

CVE-2017-3066 - BaseHTTPEndpoint.service()

21 of 66

CVE-2017-3066 - BaseHTTPEndpoint.filterChain.invoke(context)

22 of 66

CVE-2017-3066 - BaseHTTPEndpoint.filterChain.invoke(context)

deserialize untrusted user input

23 of 66

CVE-2017-3066 - Understanding AMF Deserializer

https://codewhitesec.blogspot.com/2017/04/amf.html

AmfMessageDeserializer.readMessage()

24 of 66

CVE-2017-3066 - Understanding AMF Deserializer

25 of 66

CVE-2017-3066 - Understanding AMF Deserializer

26 of 66

CVE-2017-3066 - Understanding AMF Deserializer

27 of 66

CVE-2017-3066 - Understanding AMF Deserializer

28 of 66

CVE-2017-3066 - Understanding AMF Deserializer

This class store basic information about the Object then using these properties to restore Object

29 of 66

CVE-2017-3066 - Understanding AMF Deserializer

30 of 66

CVE-2017-3066 - Java Proxy Mechanism

What is Java Proxy ?

31 of 66

CVE-2017-3066 - Java Proxy Mechanism - Quick example

32 of 66

CVE-2017-3066 - Understanding AMF Deserializer

33 of 66

CVE-2017-3066 - Understanding AMF Deserializer

34 of 66

CVE-2017-3066 - Apache Blaze DS 4.7.3 Release Notes

35 of 66

CVE-2017-3066 - Understanding AMF Deserializer

Where is the vulnerability ? Not like old traditional Java Deserialize huh ?

36 of 66

CVE-2017-3066 - AMF readExternalizable()

37 of 66

CVE-2017-3066 - AMF restore Object via Java Bean

38 of 66

CVE-2017-3066 - Exploit

39 of 66

CVE-2017-3066 - Exploit

40 of 66

CVE-2017-3066 - Exploit - readExternal() exploit

41 of 66

CVE-2017-3066 - Exploit - readExternal() exploit

42 of 66

CVE-2017-3066 - Exploit - readExternal() exploit

  • sample exploit

host,port of attacker JRMP server

43 of 66

CVE-2017-3066 - Exploit - readExternal() exploit

44 of 66

CVE-2017-3066 - Exploit - readExternal() exploit

45 of 66

CVE-2017-3066 - Exploit - readExternal() exploit

46 of 66

CVE-2017-3066 - Exploit - readExternal() exploit

send to JRMP server

receive back object from JRMP server, then deserialize it

47 of 66

CVE-2017-3066 - Exploit - Improvement

So what if target server has no outbound connection ? and we cannot use JRMP chain anymore?

48 of 66

CVE-2017-3066 - Exploit - Improvement

  • Chain 1: from setter to native Java Deserialization -> ReplicatedTree.setState()

49 of 66

CVE-2017-3066 - Exploit - Improvement

50 of 66

CVE-2017-3066 - Exploit - Improvement

51 of 66

CVE-2017-3066 - Exploit - Improvement

  • Chain 2: from readExternal() to native Java Deserialization (no need JRMP call chain) -> MetaDataEntry.readExternal()

52 of 66

CVE-2017-3066 - Exploit - Improvement

53 of 66

CVE-2017-3066 - Exploit - Improvement

54 of 66

CVE-2017-3066 - Exploit - CommonsBeanUtil gadget

  • sample exploit

55 of 66

CVE-2017-3066 - Exploit - CommonsBeanUtil gadget

PriorityQueue.readObject()

56 of 66

CVE-2017-3066 - Exploit - CommonsBeanUtil gadget

57 of 66

CVE-2017-3066 - Exploit - CommonsBeanUtil gadget

BeanComparator.compare()

trigger java bean TemplatesImpl.getOutputProperties()

58 of 66

CVE-2017-3066 - Exploit - TemplatesImpl.getOutputProperties()

59 of 66

CVE-2017-3066 - Exploit - TemplatesImpl.getOutputProperties()

60 of 66

CVE-2017-3066 - Exploit - TemplatesImpl.getOutputProperties()

control with java reflection API�=> load malicious java byte code

61 of 66

CVE-2017-3066 - Exploit - Ysoserial

  • Gadget.createTemplatesImpl() ysoserial

62 of 66

CVE-2017-3066 - Exploit - Ysoserial

Any gadget always end with Runtime.getRuntime().exec(“command here”)

But in scenario which target server has no outbound connection it will be a blind RCE

But how can we archive a reliable shell ?

63 of 66

CVE-2017-3066 - Exploit - Ysoserial

64 of 66

CVE-2017-3066 - Exploit - Ysoserial Improvement

Basic idea

modify CommonsBeanUtil gadget to load malicious with byte code as below:

  • finding request / response object in ThreadLocal of each Thread while handling the request
  • execute command, get the output
  • using response object to write the output of command then close the connection

65 of 66

CVE-2017-3066 - Exploit - Ysoserial Improvement

66 of 66

CVE-2017-3066 - Exploit - Result