Back in April, I disclosed two vulnerabilities in Cloud Foundry UAA (User Account and Authentication Server) to the Cloud Foundry security team, which assigned them CVE-2019-11268 and CVE-2019-11270. In my last post I went over CVE-2019-11268, an SQL injection which allowed information exposure across UAA identity zones.
I couldn’t discuss CVE-2019-11270 up until last week (1-8-19) when CF publicly addressed it and released a patched version – UAA v73.7. CVE-2019-11270 is a high-severity privilege escalation vulnerability in UAA’s implementation of the clients.write scope (i.e. permission). A malicious client possessing the vulnerable scope could create new clients with arbitrary scopes and gain up to full control over the UAA server and the applications it governs (e.g. CF deployments).
If you either use UAA as a standalone Oauth2 server or in a CF deployment I highly recommend you read the ‘Was I Affected?’ section at the end. It includes a few simple commands that will identify if the vulnerability was exploited in your environment.
Cloud Foundry UAA (User Account and Authentication) is an Oauth2 server providing identity management and access control. It can be used as an Oauth2 server in any environment, including outside of CF deployments.
In my previous post I partly touched on UAA concepts like access tokens, clients and scopes. Nevertheless, let’s revisit them with some illustrations as understanding them is key to understanding both basic Oauth2 flows and the vulnerability.
The UAA server implements the widely used Oauth2 authorization protocol. Most of you have probably used Oauth based authorization, for example when signing up to a website like eBay using your Facebook account, and authorizing the website to have some permission over the account, like reading your email address or posting on your behalf.
Simplifying a bit, an Oauth2 authorization flow generally consists of the following steps:
Let’s review the pieces in the image above:
Resource Servers and Access tokens
Resource servers are defined as any entity that respects access tokens issued by the UAA, effectively allowing the UAA to govern access to its resources. A resource server can be a database, an API endpoint, or even the Oauth2 server itself.
An access token allows access based on the scopes (basically permissions) encoded in it. Scopes are arbitrary strings that resource servers can decide to attach meaning to. For example, a database app can decide that any client that presents an access token with the db.read scope is allowed to read from it, while other apps might not attach any meaning to that scope.
Clients and Users
Clients represent applications that require access to resource servers governed by the UAA. Clients have two sets of permissions – scopes, and authorities.
A user normally represents a live person. Users have permission in the form of group memberships, for example a user who is a member of the db.read group. Users cannot directly act on their permissions, though, and can only authorize clients to act on their behalf.
UAA Access Token Grant
The UAA server grants access tokens to clients as a form of authorization. Tokens are granted in two scenarios:
- When a client is acting on behalf of a user (similar to the Facebook example and the image below it).
Here the access token authorizes the client to act based on the intersection of the client’s scopes and the user’s group memberships (e.g. a client with the db.read scope and a user who is a member of the db.read group). The user can also choose to approve or deny the scopes requested by the client.
- When a client acts on its own. The access token authorizes the client to act based on the clients’ authorities.
In both cases the client can present the granted access token to a resource server and act based on the scopes encoded in the token.
As demonstrated above, some clients can act on their own without the need for user approval, according to a set of permissions called authorities. These are useful for resources which aren’t related to users. In the Facebook example, eBay could have the ‘advertise.put’ authority, allowing it to push ads to Facebook or other sites governed by it.
UAA management scopes
Several scopes referred to as ‘UAA scopes’ allow managing the UAA server itself. For example, after a client with the “groups.update” authority authenticates against the UAA server and receives an access token, he can present that access token to the UAA and is then allowed to modify existing UAA groups. In the case of UAA management scopes, the UAA also plays the role of the resource server.
That’s it for the Oauth2 & UAA background, now to the juicy details
CVE-2019-11270 – Privilege escalation via the clients.write scope
clients.write is one of the UAA management scopes I mentioned earlier, and is a more narrowly bound version of clients.admin. Like clients.admin, clients.write allows creating and modifying clients, but imposes several restrictions on the created clients. ‘clients.write’ is documented as follows:
“This scope is required to create and modify clients. The scopes are prefixed with the scope holder’s client ID. For example, id:testclient, authorities:client.write gives the ability to create a client that has scopes with the testclient. prefix. Authorities are limited to uaa.resource.”
So created clients are only allowed to have scopes prefixed with the id of the creating client. For example, a client with id:’app123’ and authorities:clients.write can only register new clients with scopes prefixed with app123. (e.g app123.read or app123.admin).
These restrictions are expected to deny a client with the clients.write scope from creating clients with privileged UAA management scopes (such as uaa.admin) and escalate his privileges.
‘Client.write’ use case
The clients.write scope is handy for managing a resource server. In order to manage a database app, the UAA admin can create a client with id ‘db’ and give him the clients.write authority. The ‘db’ client can now create new clients and give them scopes prefixed with db. like db.read, db.create or db.admin. The ‘db’ client is effectively the administrative client for the database app and can create other clients with fine-grained permissions to the app.
Since the created clients can only be registered with scopes, not authorities, they all require a user to authorize them in order to receive an access token (as illustrated above in ‘Access token grant’). In a production environment, the ‘db’ client can be given the scim.write and scim.read authorities so he’ll be able to create users with appropriate group memberships (e.g. db.read) so they could authorize the new clients.
Examining the UAA code that enforces the aforementioned restrictions, specifically ClientAdminEndpointValidator’s validate function, it appears that the clients.write scope isn’t implemented as documented. In the code below, ‘caller’ refers to the creating client (i.e. the client possessing the clients.write scope), and ‘client’ refers to the created client.
You can see that beside allowing scopes prefixed with the creating client id (as documented), the function also allows scopes prefixed with the created client id. This implementation flaw allows the caller to create clients with arbitrary scopes, since he also controls the created client id. A malicious client which has the clients.write authority can, for example, create a client with id:‘zones’ and therefore with any scope prefixed with zones., such as zones.uaa.admin, a scope that enables full administrative control over the UAA server.
The clients.write scope purpose is to allow fine-grained control over a specific resource server (as explained in the use-case section above). By exploiting this vulnerability, a malicious client can gain administrative control over the UAA server and all the resource servers, applications, and users managed by it.
As a side note, at line #182 you can see that the creating client can also assign any of his own scopes. This makes sense as the creating client already has those scopes, so giving them to the new client doesn’t elevate his privileges.
As stated earlier, clients wishing to act on their scopes require a user with matching group memberships to authorize them. An attacker which exploited the vulnerability to create a client with id: ’zones’ and scopes: zones.write, for example, will need a user who is a member of the zones.write group to authorize the new ‘zones’ client.
If that attacker controls such a user, the attack becomes trivial. The same is true if the attacker has scim privileges, i.e. scim.write and scim.read, which give him the ability him to create the required user. This attack is demonstrated in the video below, where the ‘evil’ client exploits the vulnerability to obtain an access token with the clients.admin scope, gaining full control over the UAA server.
This is the best-case scenario for the attacker though, where besides having the vulnerable clients.write scope, he also has access to users who can approve clients created with the vulnerability.
Let’s limit our attacker a bit, what can he do with only the vulnerable scope? Is the vulnerability useless in this case?
Fortunately for our limited attacker, the clients.write scope also allows using UAA’s auto-approve feature, which is as sketchy as it sounds. Normally when a user authorizes a client to act on his behalf, he is presented with an option to approve or deny the scopes request by the client.
As seen in the image above, the user chose to only approve the database.read scope.
If one of the client’s scopes was set to auto-approved though, the scope is automatically without the user’s knowledge or consent. In the image above for example, the database.admin scope is automatically approved, and you can see the user has no indication of that.
As I stated earlier, the clients.write scope allows setting the scopes of the created clients as auto-approved. Let’s see how an attacker can utilize this feature to gain full control over a CF deployment in a scenario that emulates a real production environment.
In the previous exploit video, the attacker had access to the clients.write scope in the form of a client with the clients.write authority. For this scenario, the attacker has access to the clients.write scope through a classic Oauth2 user-client pair:
- The ‘twist’ user which is a member of the clients.write scope
- The ‘evil’ client which has the clients.write scope, alongside the some.arbitrary scope (will be explained soon)
Here are the other actors of our production environment:
- The ‘some-fake’ app – a resource server which trusts UAA access tokens to govern access to its resources. It requires the token to contain the some.arbitrary scope.
- The ‘victim’ user – a member of the some.arbitrary and cloud_controller.admin groups.
Our ‘victim’ user regularly approves the ‘evil’ client to use the some.arbitrary scope and access the ‘some-fake’ app on his behalf.
The attacker’s goal is to exploit the vulnerability in order to add the ‘cloud_controller.admin’ scope to the ‘evil’ client and set it as auto-approved.
If you’re not sure how the attacker managed to execute one of the steps below, you can probably get some clarifications in the Vulnerability chapter.
- To start the attack, the attacker uses the ‘twist’ user and ‘evil’ client to obtain an access token with the vulnerable clients.write scope. He then exploits the vulnerability to create a client named ’cloud_contoller’ and gives him the cloud_contoller.admin scope.
The attacker also gives the ‘cloud_contoller’ client all of evil’s scopes.
- Next, the attacker uses the ‘twist’ user and ‘cloud_contoller’ client to modify the ‘evil’ client to have the cloud_controller.admin scope, and also sets it as auto-approved.
- The next time ‘victim’ authorizes the ‘evil’ client to use the some.arbitrary scope, the cloud_controller.admin scope will be automatically approved as well without the victim’s consent (!) :
This attack is successfully executed in the video below:
After executing the attack, the ‘evil’ client has administrative control over the cloud_controller, which means full control over the CF deployment
In the video I used uaac, a CLI for the UAA server. In a real attack scenario, the ‘evil’ client will likely have a web interface, and the ‘victim’ user will be redirected from it to the UAA authentication and authorization pages.
Am I Affected?
Below are a couple of uaac (uaa CLI) commands to check if CVE-2019-11270 was exploited in your environment.
Keep in mind that the attacker could have deleted the clients he created with this vulnerability, so you might want to check your UAA logs as well.
I hope this post helped you understand the vulnerability, its exploitation techniques, and impact.
If you are using either Cloud Foundry Application Runtime or UAA, don’t forget to update to the latest patched version.
Feel free to reach out with any questions you may have through email or @TwistlockLabs.