[EX006] How to exploit CVE-2021-22986 in F5 BIG-IP devices



F5 has just announced some critical vulnerabilities in the web application of Big IP, notably CVE-2021-22986. This vulnerability is in the iControl REST API management interface, which can allow unauthenticated attackers to remote code execution (RCE) with a CVSS score of 9.8.

In this article, we will perform a detailed analysis and how to exploit the vulnerability.

iControl REST interface

Firstly, we identify the handlers of these APIs. The information on the F5’s website shows that these endpoints are prefixed with /mgmt/. The httpd configuration shows that these requests are forwarded to a listening service on localhost at port 8100:

This process is a java servlet application with classes at /usr/share/java/rest:

Vulnerability analysis

We downloaded the jar files in the above path from 2 Big IP Virtual Edition and then decompile to compare the source code in order to identify the vulnerability. Not much has changed in the source code, so noticeable files can be identified quickly:

Quickly observing the change of IAppBundleInstallTaskCollectionWorker class, it's easy to see that the update has patched the command injection. However, after debugging this application, we found that the vulnerability can only be exploited if the request is sent directly to the servlet on localhost. If so, there are quite a few endpoints (features) that can be leveraged to RCE.

Sum ups the iControl architecture, this application uses the RestServer and RestWorker classes as the center. RestServer will use RestWorker to handle requests, including handlers like onPost, onGet, onQuery,... corresponding to HTTP methods and events like onStartCompleted, onPostComplete. The workers when loaded will be registered with a corresponding URI, stored in RestServer.pathToWorkerMap and used to lookup handler. Requests are represented by the RestOperation class. In addition, the workers communicate with each other through requests. Readers need to directly debug the application to better understand these concepts.

Go back to the httpd configuration (/run/conf/httpd.conf):

Last time, we had a BigIP vulnerability analysis related to httpd configuration. However, the application under analysis is a “servlet only”, not tomcat, so bypassing this configuration can be eliminated with the path parameter. Here, httpd requires the user to authenticate (with mod_auth_pam.so) in order to access the iControl REST API endpoints. Thus, it is quite certain that there must be an SSRF vulnerability to be able to execute "real" RCE.

The question is whether there is SSRF from iControl REST itself or from TMUI or other Big IP web applications. Continue analyzing the changes, we identified an SSRF vulnerability in the AuthnWorker class.

The state.loginReference.link value is deserialized from the json post data - data that the user can control. Then an HTTP post request is sent to this URL:

Analysis the hook handler in mod_auth_pam.so shows that the endpoint /mgmt/shared/authn/login is passed back to the iControl servlet handled at AuthnWorker. As such, this is the pre-auth SSRF needed to exploit this vulnerability.


Exploiting the vulnerability is quite difficult because the data sent in the SSRF request is limited by fields in AuthProviderLoginState.

First try

We exploit by exploiting SSRF to send a request directly to the endpoint IappBundleInstallTaskCollectionWorker at /tm/access/bundle-install-tasks but failed because we could not control filePath. After searching with hope for some magic in gson lib … but failed, we pass the RCE intent if there is a possible upload error and write the file to /var/apm/f5-iappslx-agc-usecase-pack/ with random content. validateGzipBundle() will search and get the first file in this directory to assign value to filePath. In linux it is possible to create a file name containing the characters `, | or & capital can be used to exploit OS command injection.

With this in mind, we focus on analyzing the change related to AsmFileTransferWorker. This worker allows to upload files to /ts/var/rest and adds some validators related to the user as well as the filename:

However, after many attempts and failures, we are still unable to exploit in this direction, including finding the same new endpoint to exploit.

Exploit Successfully

While continuing to look for exploitable endpoints with controllable data fields, we saw a tweet by researcher Rich Warren (@buffaloverflow). According to the image in this post, it can be seen that the author created and leaked the token of the user with high authority, this is a huge hint for us to follow.

We conduct the analysis around AuthTokenWorker - the worker in charge of validating and generating tokens.

Basically, tokens are generated and stored in tokenCache before storing with StorageWorker. There are 3 ideas that can be implemented for tokens:

  • Send request directly to AuthTokenWorker to generate token. This way, it is necessary to control the user value in AuthTokenItemState, so it cannot be done.
  • Send a request to StorageWorker to store arbitrary tokens. However, when the token is taken to validate, the json also requires the user value.
  • Hijack a certain thread of execution to generate tokens. We have successfully exploited this idea.

Return to login function at AuthnWorker

When the checkAuth request is successful, which means the user has been authenticated, this worker will call the generateToken function, which makes a request to AuthTokenWorker to generate a token and return to the user as its function.

Can you catch the idea? Here, the request to AuthTokenWorker is set to state.user equal to loginState.userReference (loginState is deserialized from checkAuth's response) just like its feature. So if we can find a certain endpoint so that request checkAuth (SSRF) returns json data containing the controllable userReference key, it is possible to generate tokens for any user. This is perfectly reasonable and feasible since we can control the userReference field.

After reviewing all the workers implementing the onPost method (preferably reviewing the workers using the respective state class that declared "RestReference userReference"), we found a class that could be used as GossipWorker.

After creating and leaking the token, the rest is to use this token to address remote code execution.

Thanks for reading!!

Researcher: Tạ Quang Khánh

VinCSS (a member of Vingroup)

No comments:

Post a Comment