AD5003: EnableStackProtectorMachO¶
Summary¶
| Property | Value |
|---|---|
| ID | AD5003 |
| Name | EnableStackProtectorMachO |
| Category | Security |
| Severity | Error |
| Applies to | Mach-O (macOS/iOS) |
Description¶
Stack protector adds a 'canary' value between local variables and the return address on the stack. If a buffer overflow overwrites the canary, the program will detect this and abort before the corrupted return address is used.
Enable this protection by compiling with -fstack-protector-strong or -fstack-protector-all.
How It Works¶
The rule checks for the presence of stack canary symbols:
__stack_chk_fail__stack_chk_guard___stack_chk_fail___stack_chk_guard
These symbols indicate stack protector is enabled and linked.
Why This Matters¶
Stack canaries are one of the most effective and widely-deployed exploit mitigations on Apple platforms. They detect stack buffer overflows before the attacker can hijack control flow, converting potential code execution into a controlled crash.
How Stack Canaries Work on macOS¶
Stack Layout with Canary:
┌─────────────────┐ High address
│ Return Address │ ← Attacker target
├─────────────────┤
│ Saved RBP │
├─────────────────┤
│ CANARY VALUE │ ← Random, checked on return
├─────────────────┤
│ Local buffer │ ← Overflow starts here
└─────────────────┘ Low address
Overflow must corrupt canary to reach return address.
Canary mismatch = __stack_chk_fail = abort()
Protection Levels¶
| Flag | Protection | Overhead | Recommendation |
|---|---|---|---|
-fstack-protector |
Functions with buffers | Low | Legacy |
-fstack-protector-strong |
More functions | Low | Recommended |
-fstack-protector-all |
All functions | Higher | High security |
Apple Defaults¶
| Platform | Default |
|---|---|
| Xcode iOS | -fstack-protector-strong |
| Xcode macOS | -fstack-protector-strong |
| Command line | Must specify |
Canary Implementation¶
macOS uses __stack_chk_guard:
__stack_chk_guard:
- Random value at process start
- Contains terminator bytes (\0, \n, etc.)
- Hard to include in overflow payload
Attack Difficulty¶
| Scenario | Without Canary | With Canary |
|---|---|---|
| strcpy overflow | Code execution | Crash |
| sprintf overflow | Code execution | Crash |
| Off-by-one | May succeed | Usually crash |
| Info leak needed | No | Yes (to bypass) |
Performance¶
| Level | Overhead |
|---|---|
| -fstack-protector | <1% |
| -fstack-protector-strong | ~1% |
| -fstack-protector-all | 2-5% |
- Buffer overflow detection: Catches stack smashing at runtime
- Controlled abort: Crashes safely instead of executing attacker code
- Low overhead: Minimal performance impact with
-fstack-protector-strong - Apple default: Enabled by default in Xcode for most project types
Resolution¶
Xcode¶
Stack protector is enabled by default. Ensure it hasn't been disabled:
- Select your target in Xcode
- Go to Build Settings → Apple Clang - Code Generation
- Ensure Enable Stack Canaries is set to Yes
Command Line (Clang)¶
# Recommended - protects most vulnerable functions
clang -fstack-protector-strong source.c -o binary
# Maximum protection - all functions
clang -fstack-protector-all source.c -o binary
CMake¶
When to Suppress¶
This rule may be suppressed for:
- Performance-critical code: After profiling shows significant impact
- Freestanding code: Kernel extensions without libc
- Swift-only code: Swift has its own memory safety guarantees