Aqua Blog

Threat Actors Using release_agent Container Escape

Threat Actors Using release_agent Container Escape

Earlier this year, Aqua’s Team Nautilus detected a cryptocurrency mining campaign targeting our honeypots. As part of the campaign, the threat actors used a container escape technique that leverages the CGroup release_agent feature. This technique allows an attacker to break out from the container and compromise the host and, potentially, the entire network of an organization. To our knowledge, this is the first time this technique was used in a real-world attack.

Technical analysis

The container image used by the threat actor was built on one of our honeypot’s servers, after the required layers were registered in the Docker service of the server, as we described previously in our analysis of the attack.

The image contained two malicious files:

  • XMRig renamed as nginx (MD5:859fbbedefc95a90d243a0a9b92d1ae9)
  • Shell script named calm.sh (MD5:5e1a4c0202bc28778aa88b6b3e207553)

This container image built on the compromised host was designed to execute the malicious script.

snippet of the "calm.sh" script

The container escape technique in the script calm.sh (in rows 1-5 in the screenshot above) is similar to the one found on a penetration testing website.

snippet of the example code provided by book.hacktricks.xyz

This container escape technique includes the following steps:

  1. Mounting a new CGroup directory
  2. Creating a CGroup in that directory
  3. Defining therelease_agentfor that CGroup.

The release_agent is a script that is executed at the termination of any process on that CGroup. The release agent is invoked from the host, enabling the threat actor to execute malicious code on the host server. However, the container must have the SYS_ADMIN capability (--privileged) to be able to mount a CGroup directory.

The calm.sh script runs a malicious code on the host using the container escape technique, the purpose of which is to terminate any instances of XMRig on the host. Then, calm.sh is designed to execute nginx, which is a cryptominer running in the container.

We assume that the threat actor is creating an ongoing XMRig termination on the host to kill competitors’ cryptomining processes, which otherwise can cause high CPU usage and increase the chances of detection.

Summary and mitigation

This is the first time we’ve observed this container escape technique used in the wild. Although it wasn’t used to execute the main malicious code on the host, the potential impact can be much greater than in other attacks we’ve seen.

To mitigate the risk, organizations should avoid using privileged containers whenever possible.

Aqua’s open source runtime security and forensics eBPF tool, Tracee, detects these kinds of threats and can assist in quick assessment of the incident.

The following JSON event was generated on our attacked honeypots due to the malicious activity spotted by Tracee. It describes the flow of the attack and includes a certain syscall or kernel function invocation and the arguments that were provided in relation to that event. Below, we highlighted the important parts for the detection of this attack.

container escape attack analysis

After this attack, we released a Rego signature designed to detect it using Tracee:

package tracee.TRC_14
import data.tracee.helpers
__rego_metadoc__ := {
“id”: “TRC-14”,
“version”: “0.1.0”,
“name”: “CGroups Release Agent File Modification”,
“description”: “An Attempt to modify CGroups release agent file was detected. CGroups are a Linux kernel feature which allows process’s resources limitations. Adversaries may use this feature for container escaping.”,
“properties”: {
“Severity”: 3,
“MITRE ATT&CK”: “Privilege Escalation: Escape to Host”
}
}
eventSelectors := [
{
“source”: “tracee”,
“name”: “security_file_open”,
“origin”:“container”
}
]
tracee_selected_events[eventSelector] {
eventSelector := eventSelectors[_]
}
tracee_match = res {
input.eventName ==
“security_file_open”
flags = helpers.get_tracee_argument(“flags”)
helpers.is_file_write(flags)pathname := helpers.get_tracee_argument(“pathname”)endswith(pathname

, “/release_agent”)res := {

“File Flags”: flags,
“File Path”: pathname,
}
}

This signature will detect the described attack by identifying modifications of the release_agent file.

Asaf Eitani
Asaf is a Security Researcher at Aqua Nautilus research team. He focuses on researching Linux malware, developing forensics tools, and analyzing new attack vectors in cloud native environments. In his spare time, he likes painting, playing beach volleyball, and carving wood sculptures.