Show Notes

203 - Pentaho Pre-Auth RCE and Theft by CAN Injection

Code-generator gone bad! And another look at why its important to consider the context of what your escaping data for. In this case synthetics recorder could be used to generate playwright scripts (I think?) to replay a capture interaction. In the code that it would generate when waiting for a navigation to complete it would generate code something like the following:

page.waitForNavigation(/*{ url: 'https://example.com' }*/),

The URL being waited on is controlled by the user, and it simply performs escaping to prevent the url from escaping the quotes…but the context is that it is inside a comment, the quotes don’t matter, you just need to include a */ inside of the URL to escape the comment, and start injecting arbitrary JavaScript. It does take an attacker in a privileged position to be recording a session and visit a hostile web application with such a malciious URL, but there are some contexts where this could be exploited.

Code-generator gone bad! And another look at why its important to consider the context of what your escaping data for. In this case synthetics recorder could be used to generate playwright scripts (I think?) to replay a capture interaction. In the code that it would generate when waiting for a navigation to complete it would generate code something like the following:

page.waitForNavigation(/*{ url: 'https://example.com' }*/),

The URL being waited on is controlled by the user, and it simply performs escaping to prevent the url from escaping the quotes…but the context is that it is inside a comment, the quotes don’t matter, you just need to include a */ inside of the URL to escape the comment, and start injecting arbitrary JavaScript. It does take an attacker in a privileged position to be recording a session and visit a hostile web application with such a malciious URL, but there are some contexts where this could be exploited.

A stupid auth bypass (for the app, great find by the researcher), and a service-side template injection in Pentaho. Starting with the SSTI, Pentaho has a few endpoints to configure and test LDAP connections, to do so it creates an XML-based bean definition and properties file containing all the user-provided data. As this is administrative functionality the input is just trusted, and as such Thymeleaf templates can be included in the properties that will be parsed and executed. As you’d expect these templates can call arbitrary Java, such as invoking the java.lang.Runtime class and .getRuntime().exec(...) methods for arbitrary code execution.

http://127.0.0.1:8080/pentaho/api/ldap/config/ldapTreeNodeChildren/?url=%23{T(java.lang.Runtime).getRuntime().exec('notepad.exe')}&mgrDn=a&pwd=a

Pretty straight forward code execution, but privileged off.

In come the the authorization bypass. Pentaho has various authorization checks, but for unauthenticated access, the primary control is a set of regular expressions which define the allowed endpoints. The regex allows any path ending with /require.js to be access by an unauthenticated user. For most of the application’s endpoints, just adding /require.js would break the routing and not actually lead to accessing any sensitive endpoints. One endpoint that would still be correctly resolved is the previously mentioned api/ldap/config/ldapTreeNodeChildren endpoint.

At its core, this is pretty easy to understand, and isn’t especially novel, but it is an interesting area, stealing cars so worth covering. The core problem is simply that inside of a modern vehicle you have the Controller Area Network Bus (CAN Bus). All of the various Electronic Control Units (ECUs) in the vehicle are connected to this bus and can send messages to each other. So the Smart key might send out a message to the Door Control ECU indicating the key was pressed to unlock the door.

The problem is that on many vehicles there is no authentication checking, it is assumed that if a message is recieved it is legitimate. Of course, this is a rather closed off network so its not an insane idea that any device communicating on it is supposed to be there, its also difficult to implement meaningful authentication with disparate control units being included in any vehicle (and considering support support for aftermarket devices). None the less, messages are trusted, so an attacker who can find a way to hook into the network and send messages, can impersonate existing devices and send the appropiate commands to unlock and start a vehicle.

Nothing to crazy here, its well known that if someone can compromise something running within an AWS Elastic Kubernetes Service (EKS) pod, they can use that access to hit the AWS EC2 Metadata Service and gain the machine’s IAM token. There has been some prior research about performing a denial of service by removing a network interface with that token, but the author An Trinh here takes a look at going for a more significant privilege escalation.

The path they discovered, was that you can go from pod -> metadata -> IAM token as per normal. The IAM token can be exchanged back with Kubernetes for a token with the system:node role within the Kubernetes cluster. If, as is the case in many instances, the cluster randomly assigns pods to nodes, there is the possibility for a privileged pod to be running on the same node as the compromised pod (and the one you have system:node on). If there is one running, the system:node token can be used to impersonate the privileged pod and potentially gain cluster-admin privileged (if that was what the privileged pod had). This does depend on there not being any separate if privileges and what nodes privileged pods run on, but it should work in a fair number of situations so its worth being aware of.

The author also notes a persistence technique, EKS is able to faciliate mapping between AWS identities and EKS privileges. This works by hooking into the Kubernated API and calls teh AWS STS endpoint with the EKS token. Calling STS will identify the token, and there is a configuration mapping to make the AWS role ARNs to Kubernetes roles. As such one could plant a user into the configuration mapping with high privileges. These privileges exist independently of the privileges actually held within AWS so even removing all permissions from the user would not remove their cluster-admin access within Kubernetes.