Remote Code Execution (RCE) is a general vulnerability that can be exploited in many forms based upon the language and framework of choice. At the basic level, it allows an agent to run arbitrary code operations on the target machine/device. By having the ability to run arbitrary code on the target machine, the execution can assume the same privileges associated with the parent executor of that code, allowing for potential access of critical systems as well as its interconnects.c
Remote Code Execution (RCE) Impact
Remote code execution(RCE), allowing an attacker to run their program on the target device or platform and can have very severe ramifications. Some examples include running malware, exfiltration of sensitive data, carrying out distributed denial of service and destroying infrastructure. Some common RCE exploits use vulnerabilities within code including buffer overflow, deserialization, and type confusion.
Java Specific RCE Fixes
Consider a real-life example of apache struts:
public UserProfile loadUserProfile(Socket socket) {
try(ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
return (UserProfile) ois.readObject();
}
}
by deserializing the socket input stream it allows for RCE. In the struts2-rest-plugin, the toObject
directly calling XStream.fromXML
without sanitizing the data.
Solution: To fix this vulnerability, it’s not possible to sanitize user input but the strategy was to add default permissions to allow types in XStream object. It was able to perform type filtering to allow sane defaults of primitives with the addDefaultPermissions
method:
protected void addDefaultPermissions(ActionInvocation invocation, XStream stream) {
stream.addPermission(new ExplicitTypePermission(new Class[]{invocation.getAction().getClass()}));
if (invocation.getAction() instanceof ModelDriven) {
stream.addPermission(new ExplicitTypePermission(new Class[]{((ModelDriven) invocation.getAction()).getModel().getClass()}));
}
stream.addPermission(NullPermission.NULL);
stream.addPermission(PrimitiveTypePermission.PRIMITIVES);
stream.addPermission(ArrayTypePermission.ARRAYS);
stream.addPermission(CollectionTypePermission.COLLECTIONS);
stream.addPermission(new ExplicitTypePermission(new Class[]{Date.class}));
}
More details can be seen here: Git commit for 2.5.x
As a general rule, audit all java code for execution paths e.g. CreateProcess()
or ProcessBuilder()
, and validate that arguments to these methods are not user-defined or manipulated. In general detection and fixes to RCE are very complex. As a general rule it NOT enough to:
- sanitize user-inputs, either by whitelisting or blacklist inputs/characters
- prevent users from defining file extensions
RCE Tales
Sierra Wireless: RCE in Sierra Wireless AirLink ES450 LTE gateway
Microsoft Excel: RCE in Microsoft’s Excel
Microsoft Server: Microsoft’s Server Message Block (SMB)
WannaCry: WannaCry and Microsoft’s SMB
References
GitHub Cisco-AMP: Remote Code Execution for Java Developers
GitHub Shawn McKinney: How Java Security Manager can prevent RCE
Thanks for reading 🙂