Skip to content

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:

  1. Password Managers: Handle the most sensitive credentials users have
  2. Cryptographic Applications: Encryption keys must never be exposed
  3. Financial Applications: Banking, trading, and payment apps
  4. Enterprise Security Tools: VPNs, MDM agents, endpoint protection
  5. DRM and Licensing: Applications that verify licensing or protect content
  6. Healthcare Applications: HIPAA-protected health information
  7. 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:

  1. Debugging Impact: Developers often use DYLD_INSERT_LIBRARIES for debugging, profiling (Instruments), or testing. Restricting this breaks legitimate workflows.

  2. Plugin Architectures: Some applications intentionally support plugins via library injection. __RESTRICT would break this functionality.

  3. Alternative Protections: Hardened Runtime (enabled via code signing) provides similar protections and is required for notarization anyway.

  4. setuid/setgid Binaries: macOS already ignores DYLD variables for setuid binaries, so this protection is redundant for privileged helpers.

  5. 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

clang -Wl,-sectcreate,__RESTRICT,__restrict,/dev/null your_code.c -o app

Xcode

Add to "Other Linker Flags":

-Wl,-sectcreate,__RESTRICT,__restrict,/dev/null

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:

codesign --options runtime -s "Developer ID" your_app

The hardened runtime also disables DYLD_INSERT_LIBRARIES and related variables.

Verification

Check if a binary has the __RESTRICT segment:

otool -l /path/to/binary | grep -A2 __RESTRICT

Expected output:

  segname __RESTRICT
   sectname __restrict

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

References