Nicky Bloor - BaRMIe - Poking Java's Back Door - 44CON 2017
-
Upload
nicky-bloor -
Category
Technology
-
view
1.791 -
download
5
Transcript of Nicky Bloor - BaRMIe - Poking Java's Back Door - 44CON 2017
BaRMIe – Poking Java’s Back Door
Nicky Bloor 44CON 2017
whoami
Nicky Bloor
• Managing Security Consultant at NCC Group
• Ex software developer
• Desktop, web, games, industrial control systems
• Problem solver, breaker, builder, hacker
• Hiker and rock climber
• @NickstaDB on the Interwebz
A Story of Pwn
• On-site Java application assessment
• No credentials provided until day 3…
• Supporting infrastructure was in scope
• One network service stood out…
A Story of Pwn
Java Remote Method Invocation???
…gave me the server before I got those credentials.
Too easy! This left me really intrigued!
RMI?
• How common is RMI?
• How often is it so insecure?
• What else can we do with it?
Java Remote Method Invocation
A Brief Introduction to RMI
• Remote Method Invocation
• RPC for Java
• Execute methods within another Java virtual machine (JVM)
• Local or remote
• Simple to implement
• RMI takes care of connection and transport
• Developer does not need to be aware that RMI is in use
• RMI != arbitrary remote code execution
• Only execute methods that are implemented within the other JVM
8
A Brief Introduction to RMI
Client Application
IFoo.Bar()
RMI RMIServer Application
FooImpl.Bar()
IFoo.Bar();
The RMI Registry Service
• Directory of Java objects
• Maps Java objects to names
• Listens on TCP port 1099 by default
• Interaction via java.rmi.Registry class
• void bind(String name, Remote obj)
• String[] list()
• Remote lookup(String name)
• void rebind(String name, Remote obj)
• void unbind(String name)
The RMI Registry Service
• void rebind(String name, Remote obj)
• Rebind a bound object name to another object
• Potential free man-in-the-middle attack?
• void unbind(String name)
• Unbind an object from the registry
• Potential free denial of service attack?
The RMI Registry Service
• void rebind(String name, Remote obj)
• Rebind a bound object name to another object
• Potential free man-in-the-middle attack?
• void unbind(String name)
• Unbind an object from the registry
• Potential free denial of service attack?
• Cannot bind/rebind/unbind from non-localhost
Implementing RMI
• Very easy – perhaps part of the problem!
• Server-side
• Implement java.rmi.Remote
• Instantiate object
• Bind object to RMI registry
• Client-side
• Lookup object from RMI registry
• Use as normal
What’s the Problem?
• Fairly reasonable looking method
• Authenticate first, then read the file
What’s the Problem?
What if ApplicationObjectFactory returns a remote object?
What’s the Problem?
Client Server
authenticateUser(user,pass)
readFile(filename)
true
file contents
What’s the Problem?
Client ServerreadFile(filename)
file contents
RMI Security?
• Authentication?
• No.
• Session management?
• No.
• Encryption?
• No.
• Message integrity checking/anti-tampering?
• No.
• Access controls?
• Yes. Kind of… Fine. No.
RMI Security?
• Encryption
• SSLSocketFactory can be used
• Access controls
• bind/rebind/unbind can only be called from localhost
• Risky code executes BEFORE the localhost check…
• (Pre-Java 6u131, 7u121, 8u112)
RMI Security
RMI Security
• This is a bit unfair
• RMI wasn’t designed to be secure
• RMI was designed to facilitate remote method invocation
• To compare:
• HTTP wasn’t designed to be secure
• HTTP was designed to facilitate the transfer of textual information
RMI Security
• HTTP is far more prevalent
• HTTP has evolved to support security
• Web application frameworks improve security by default
• Authentication, session management, access controls etc…
• Developers don’t need to be particularly security aware
• RMI has none of this!
• Security must be explicitly incorporated in remotely exposed classes
Insecure Use of RMI
Insecure Use of RMI
• RMI not a secure protocol
• Original attack:
• Ignore authenticate method
• Call readFile/writeFile/executeQuery directly
• How often is RMI used this insecurely?
Insecure Use of RMI
• First step: Identify software using RMI
• Little success initially searching Google & Github
• Can I identify RMI software packages remotely?
Insecure Use of RMI
• Recalled an early test program which called Registry.lookup()
• Exception reveals fully-qualified class names
• Often identifies vendor
• Sometimes identifies the application itself
• Can we identify RMI software packages remotely?
• Yes!
• Internet search for fully-qualified class names
Insecure Use of RMI
• So, we can extract fully-qualified class names…
• What else can we learn from RMI network traffic?
• How can we extract this information?
RMI Enumeration
RMI Enumeration
RMI Enumeration
RMI Enumeration
RMI Enumeration
Insecure Use of RMI
• A lot of time was spent in these tools
• Along the way code was produced to parse RMI traffic and extract
useful data…
BaRMIe - Enumeration
BaRMIe - Enumeration
• Proxy-based enumeration of RMI registries
• Start TCP proxy for RMI registry connection
• Request remote objects
• Buffer RMI ‘ReplyData’ packets
• Parse the packet contents to extract useful data
Knocking on Java’s Back Door
• Find RMI software
• Found over 14,000 RMI services on Shodan
• Over 27,000 Java objects exposed over RMI
Knocking on Java’s Back Door
• Find RMI software
• Found over 14,000 RMI services on Shodan
• Over 27,000 Java objects exposed over RMI
• Not all exposed externally
Knocking on Java’s Back Door
• Find RMI software
• Found over 14,000 RMI services on Shodan
• Over 27,000 Java objects exposed over RMI
• Not all exposed externally
Knocking on Java’s Back Door
• Find RMI software
• Found over 14,000 RMI services on Shodan
• Over 27,000 Java objects exposed over RMI
• Not all exposed externally
• Many probably shouldn’t be exposed
Knocking on Java’s Back Door
• Find RMI software
• Found over 14,000 RMI services on Shodan
• Over 27,000 Java objects exposed over RMI
• Not all exposed externally
• Many probably shouldn’t be exposed
DbVehicleSearchService drivingLicenseManagercarUseRecordManager
Knocking on Java’s Back Door
• Find RMI software
• Found over 14,000 RMI services on Shodan
• Over 27,000 Java objects exposed over RMI
• Not all exposed externally
• Many probably shouldn’t be exposed
DbVehicleSearchService drivingLicenseManagercarUseRecordManager
CameraCapturedImages CCPaymentService superviseOilManager
Knocking on Java’s Back Door
• Find RMI software
• Found over 14,000 RMI services on Shodan
• Over 27,000 Java objects exposed over RMI
• Not all exposed externally
• Many probably shouldn’t be exposed
DbVehicleSearchService drivingLicenseManagercarUseRecordManager
CameraCapturedImages CCPaymentService superviseOilManager
SecurityServer ROOT_TERMINAL AdminAPI system UserConfigAPI
Knocking on Java’s Back Door
• Find RMI software
• Found over 14,000 RMI services on Shodan
• Over 27,000 Java objects exposed over RMI
• Not all exposed externally
• Many probably shouldn’t be exposed
DbVehicleSearchService drivingLicenseManagercarUseRecordManager
CameraCapturedImages CCPaymentService superviseOilManager
SecurityServer ROOT_TERMINAL AdminAPI system UserConfigAPI
chainGunAPI
Knocking on Java’s Back Door
• Find RMI software
• Found over 14,000 RMI services on Shodan
• Over 27,000 Java objects exposed over RMI
• Not all exposed externally
• Many probably shouldn’t be exposed
DbVehicleSearchService drivingLicenseManagercarUseRecordManager
CameraCapturedImages CCPaymentService superviseOilManager
SecurityServer ROOT_TERMINAL AdminAPI system UserConfigAPI
chainGunAPI beerMachineApi
Knocking on Java’s Back Door
• Find RMI software
• Found over 14,000 RMI services on Shodan
• Over 27,000 Java objects exposed over RMI
• Not all exposed externally
• Many probably shouldn’t be exposed
DbVehicleSearchService drivingLicenseManagercarUseRecordManager
CameraCapturedImages CCPaymentService superviseOilManager
SecurityServer ROOT_TERMINAL AdminAPI system UserConfigAPI
chainGunAPI beerMachineApi praiseService
Knocking on Java’s Back Door
• Find RMI software
• Found over 14,000 RMI services on Shodan
• Over 27,000 Java objects exposed over RMI
• Not all exposed externally
• Many probably shouldn’t be exposed
DbVehicleSearchService drivingLicenseManagercarUseRecordManager
CameraCapturedImages CCPaymentService superviseOilManager
SecurityServer ROOT_TERMINAL AdminAPI system UserConfigAPI
chainGunAPI beerMachineApi praiseService
Knocking on Java’s Back Door
• Honestly, no idea what any of these do!
• These are just examples of what people expose over RMI.
• This is bad if these services are implemented as insecurely as
that first ‘writeFile’ example
Examples of Insecure RMI
Apache JMeter
• org.apache.jmeter.engine.RemoteJMeterEngineImpl_Stub
• Open source!
• Download source and review
• Locate classes that implement java.rmi.Remote
Apache JMeter
Apache JMeter
• Looks like anyone can configure this service!
Temis RemoteAdminServer
• com.temis.admin.remote.RemoteAdminServer_Stub
• Unable to locate source code or client jar
• BaRMIe revealed an interesting annotation…
Temis RemoteAdminServer
• Remote methods:
• UserProfile authenticate(String, String)
Temis RemoteAdminServer
• Remote methods:
• UserProfile authenticate(String, String)
Looks like they thought about security?
(UserProfile – could be a session-like object?)
Temis RemoteAdminServer
• Remote methods:
• UserProfile authenticate(String, String)
• boolean configure(Properties)
…or not!
Temis RemoteAdminServer
• Remote methods:
• UserProfile authenticate(String, String)
• boolean configure(Properties)
• String getAdminKey()
Temis RemoteAdminServer
• Remote methods:
• UserProfile authenticate(String, String)
• boolean configure(Properties)
• String getAdminKey()
• int addUser(String, String, String, String)
Temis RemoteAdminServer
• Account takeover?
• List<UserProfile> getAllUserList()
• int changePassword(UserProfile, String)
Temis RemoteAdminServer
• Account takeover?
• List<UserProfile> getAllUserList()
• int changePassword(UserProfile, String)
• UserProfile methods:
• String getPassword()
Temis RemoteAdminServer
• More remote methods:
• String getDatabaseIP()
• String getDatabasePort()
• String getDatabaseName()
• String getDatabaseType()
Temis RemoteAdminServer
• More remote methods:
• String getDatabaseIP()
• String getDatabasePort()
• String getDatabaseName()
• String getDatabaseType()
• String getUsername()
• String getPassword()
RMI: What’s the Problem?
RMI: What’s the Problem?
It gets worse…
Deserialization
Deserialization
• Process of converting data into runtime objects
• Often implemented/used insecurely
• Deserializing untrusted data is usually bad
• RMI is heavily dependent on Java serialization
Adobe ColdFusion
• Most commonly exposed RMI service in my scans
• coldfusion.flex.rmi.DataServicesCFProxyServer_Stub
• No strikingly interesting remote methods
Adobe ColdFusion
• Most commonly exposed RMI service in my scans
• coldfusion.flex.rmi.DataServicesCFProxyServer_Stub
• No strikingly interesting remote methods
• Except…
Adobe ColdFusion
• Most commonly exposed RMI service in my scans
• coldfusion.flex.rmi.DataServicesCFProxyServer_Stub
• No strikingly interesting remote methods
• Except…
Adobe ColdFusion
• Most commonly exposed RMI service in my scans
• coldfusion.flex.rmi.DataServicesCFProxyServer_Stub
• No strikingly interesting remote methods
• Except…
Adobe ColdFusion
• Most commonly exposed RMI service in my scans
• coldfusion.flex.rmi.DataServicesCFProxyServer_Stub
• No strikingly interesting remote methods
• Except…
• Call fill() to deserialize any object…
Demo Time!
• Adobe ColdFusion 2016, fully up-to-date as of 11th September 2017
• Default install except for one setting
• Unauthenticated remote method invocation…
Demo Time!
Deserialization
It’s worse than that…
Java’s Back Door
Java’s Back Door
• Testing some code
• Suddenly realised I’d made a mistake…
• …but the code worked…
Full RMI Proxy
• Successfully proxying RMI registry connections
• RMI registry does not handle method invocations
• Invocation handled by remote objects
• Different port
• Potentially different host
• Built a proxy to MitM method invocations
Proxying RMI
RMI Client
RMI Registry
RMI Object
Proxying RMI
RMI Client
RMI Registry
RMI Object
Registry Proxy
First, we create an RMI registry proxy
Proxying RMI
RMI Client
RMI Registry
RMI Object
Registry Proxy
Which is configured to connect directly to the target RMI registry
Proxying RMI
RMI Client
RMI Registry
RMI Object
Registry Proxy
Our RMI client requests an object via the proxy
Proxying RMI
RMI Client
RMI Registry
RMI Object
Registry Proxy
The object data is intercepted and parsed
Proxying RMI
RMI Client
RMI Registry
RMI Object
Registry Proxy
Object Proxy
3) Creates Object Proxy
The RMI registry proxy then creates an RMI object proxy
Proxying RMI
RMI Client
RMI Registry
RMI Object
Registry Proxy
Object Proxy
3) Creates Object Proxy
Which is configured to connect directly to the RMI object
Proxying RMI
RMI Client
RMI Registry
RMI Object
Registry Proxy
Object Proxy
3) Creates Object Proxy
We modify the object data to point at the new proxy and return it to the client
Proxying RMI
RMI Client
RMI Registry
RMI Object
Registry Proxy
Object Proxy
3) Creates Object Proxy
We can now MitM remote method invocation traffic!
Java’s Back Door
• So, what was that mistake?!
• Experimenting with network-level payload injection and ysoserial
• Called obj.foo(String) in RMI client, rather than obj.foo(Object)
Java’s Back Door
• So, what was that mistake?!
• Experimenting with network-level payload injection and ysoserial
• Called obj.foo(String) in RMI client, rather than obj.foo(Object)
• Proxy replaced the parameter…
Java’s Back Door
• So, what was that mistake?!
• Experimenting with network-level payload injection and ysoserial
• Called obj.foo(String) in RMI client, rather than obj.foo(Object)
• Proxy replaced the parameter…
Poking Java’s Back Door
• Invoking void printString("AAAAAAAAAA") looks like this:
Poking Java’s Back Door
• Invoking void printString("AAAAAAAAAA") looks like this:
• A simple serialized object, new Dummy(), looks like this:
Poking Java’s Back Door
• The proxy did this (with a ysoserial payload):
Poking Java’s Back Door
• The proxy did this (with a ysoserial payload):
• Remotely invoked an illegal method call
Poking Java’s Back Door
• The proxy did this (with a ysoserial payload):
• Remotely invoked an illegal method call
• void printString(new Dummy()):
Poking Java’s Back Door
• The proxy did this (with a ysoserial payload):
• Remotely invoked an illegal method call
• void printString(new Dummy()):
• Server-side exception
• Dummy is not compatible with java.lang.String
Poking Java’s Back Door
• The proxy did this (with a ysoserial payload):
• Remotely invoked an illegal method call
• void printString(new Dummy()):
• Server-side exception
• Dummy is not compatible with java.lang.String
• Payload had already been deserialized
Java’s Back Door
If we invoke a remote method, we can replace parameters with incompatible payloads
Caveat
• Slight caveat, due to Java serialization format/protocol
• Method parameter that we replace must be non-primitive
• int, long, boolean etc cannot be replaced
• Integer, int[], ArrayList, and objects of arbitrary classes can
BaRMIe
BaRMIe
• RMI often exposes legitimate but dangerous methods
• writeFile(), executeQuery()
• Proxy-based attacks can introduce further risk
• Vulnerabilities where there wouldn’t otherwise be a vulnerability
• Requires knowledge of remote classes/method signatures
BaRMIe
• Written a lot of code during this research…
• Enumeration of remote objects (identify classes)
• Attacks for various targets
• Executing legitimate methods
• Deserialization attacks using Object type parameters
• Deserialization attacks through illegal parameter replacement
• BaRMIe is an all-in-one RMI enumeration and attack tool
Conclusion
Conclusion
• RMI lacks maturity
• Often used very insecurely
• Object injection/deserialization attacks are almost always a
possibility
• Old and ‘uninteresting’ technology can be a fun and fruitful
research target!
Questions?
https://nickbloor.co.uk/