AD5019: UseRestrictSegment¶
Summary¶
| Property | Value |
|---|---|
| ID | AD5019 |
| Name | UseRestrictSegment |
| Category | Security |
| Severity | Note |
| Applies to | Mach-O (macOS, iOS) |
Description¶
The __RESTRICT segment (with __restrict section) provides defense-in-depth against library injection attacks by disabling potentially dangerous dyld environment variables at runtime.
What It Protects Against¶
When the __RESTRICT segment is present, dyld ignores these environment variables:
- DYLD_INSERT_LIBRARIES - Normally allows injecting dynamic libraries
- DYLD_LIBRARY_PATH - Can redirect library loading
- DYLD_FRAMEWORK_PATH - Can redirect framework loading
- Other dyld debugging variables
Why This Matters¶
macOS's dynamic linker (dyld) supports environment variables that allow users to modify library loading behavior. While these features are invaluable for development and debugging, they create a significant attack vector when an adversary can control the environment in which your application runs.
The DYLD Attack Surface¶
The most dangerous dyld environment variables include:
| Variable | Purpose | Attack Use |
|---|---|---|
DYLD_INSERT_LIBRARIES |
Inject libraries before program libraries load | Load malicious code into any process |
DYLD_LIBRARY_PATH |
Override library search paths | Replace legitimate libraries with malicious versions |
DYLD_FRAMEWORK_PATH |
Override framework search paths | Replace system frameworks |
DYLD_PRINT_* |
Debug output | Leak information about process internals |
DYLD_IMAGE_SUFFIX |
Load alternative library versions | Force loading of debug/vulnerable libraries |
Real-World Attack Scenarios¶
Scenario 1: Credential Theft
An attacker creates a malicious dylib that hooks SecItemCopyMatching (Keychain access) and CCCrypt (encryption):
# Attacker's hook logs all keychain queries and encryption keys
DYLD_INSERT_LIBRARIES=./keylogger.dylib /Applications/MyApp.app/Contents/MacOS/MyApp
Every password, API key, and encryption key your application accesses is captured.
Scenario 2: Authentication Bypass
# Replace the Security framework with a modified version
DYLD_FRAMEWORK_PATH=/tmp/evil /Applications/LicensedApp.app/Contents/MacOS/LicensedApp
The fake Security framework makes all signature checks return success, bypassing code signing validation.
Scenario 3: Sandbox Escape
Malware running in a sandbox cannot directly access files outside the sandbox, but if it can launch an unsandboxed helper with controlled environment variables, it can inject code into that helper.
Who Needs This Protection¶
The __RESTRICT segment is essential for:
- Password Managers: Handle the most sensitive credentials users have
- Cryptographic Applications: Encryption keys must never be exposed
- Financial Applications: Banking, trading, and payment apps
- Enterprise Security Tools: VPNs, MDM agents, endpoint protection
- DRM and Licensing: Applications that verify licensing or protect content
- Healthcare Applications: HIPAA-protected health information
- Privileged Helpers: Applications that run with elevated permissions
Defense in Depth¶
The __RESTRICT segment is one layer in a defense-in-depth strategy:
| Protection | What It Stops | Limitation |
|---|---|---|
__RESTRICT segment |
DYLD environment variables | Requires recompilation |
| Hardened Runtime | Library injection + more | Requires code signing |
| Library Validation | Loading unsigned libraries | May break plugins |
| App Sandbox | Broad system access | Limits functionality |
For maximum protection, combine __RESTRICT with Hardened Runtime and Library Validation.
Why This is a "Note" Level Check¶
This check produces a Note rather than a Warning because:
-
Debugging Impact: Developers often use
DYLD_INSERT_LIBRARIESfor debugging, profiling (Instruments), or testing. Restricting this breaks legitimate workflows. -
Plugin Architectures: Some applications intentionally support plugins via library injection.
__RESTRICTwould break this functionality. -
Alternative Protections: Hardened Runtime (enabled via code signing) provides similar protections and is required for notarization anyway.
-
setuid/setgid Binaries: macOS already ignores DYLD variables for setuid binaries, so this protection is redundant for privileged helpers.
-
SIP Protection: System Integrity Protection (SIP) prevents DYLD injection into Apple system binaries, so this primarily matters for third-party software.
Resolution¶
Add the __RESTRICT segment at link time:
Linker Flag¶
Xcode¶
Add to "Other Linker Flags":
CMake¶
set_target_properties(your_target PROPERTIES
LINK_FLAGS "-Wl,-sectcreate,__RESTRICT,__restrict,/dev/null"
)
Alternative: Code Signature¶
For App Store and notarized applications, you can achieve similar protection using hardened runtime:
The hardened runtime also disables DYLD_INSERT_LIBRARIES and related variables.
Verification¶
Check if a binary has the __RESTRICT segment:
Expected output:
Applicability¶
This rule only applies to executable binaries (not dylibs or bundles), as: - Only executables control the initial dyld environment - Libraries cannot restrict their own loading context