AD5009: DoNotUseWeakDylib¶
Summary¶
| Property | Value |
|---|---|
| ID | AD5009 |
| Name | DoNotUseWeakDylib |
| Category | Security |
| Severity | Warning |
| Applies to | Mach-O (macOS) |
Description¶
Weak dylibs (LC_LOAD_WEAK_DYLIB) are optional at load time. If a weak dylib is not found, the loader continues anyway. This can be exploited by attackers who place a malicious library at the expected location, leading to "dylib hijacking" attacks.
How It Works¶
The rule checks for LC_LOAD_WEAK_DYLIB load commands in the Mach-O binary. These are created when linking with -weak_library or -weak-l flags.
Why This Matters¶
Weak dylibs create a race condition for code execution. If the library doesn't exist at the expected path, an attacker who can write to that location gains automatic code execution with the application's privilegesβa critical vulnerability.
The Dylib Hijacking Attack Chain¶
1. Discovery:
Attacker examines app with otool:
otool -L /Applications/VulnerableApp.app/Contents/MacOS/VulnerableApp
Shows: @rpath/OptionalSDK.framework/OptionalSDK (weak)
2. Verification:
Attacker confirms library doesn't exist:
ls /Library/Frameworks/OptionalSDK.framework
"No such file or directory"
3. Exploitation:
Attacker creates malicious library:
mkdir -p /Library/Frameworks/OptionalSDK.framework/
cp malicious.dylib /Library/Frameworks/OptionalSDK.framework/OptionalSDK
4. Execution:
User runs VulnerableApp
Attacker's code runs with user's privileges
Why Weak Linking Exists¶
| Use Case | Intent |
|---|---|
| Optional features | "Use if available" |
| SDK flexibility | Support multiple SDK versions |
| Backward compat | Run on older macOS |
Attack Surface¶
| Weak Dylib Location | Attacker Access | Risk |
|---|---|---|
| /usr/local/lib | Often writable | High |
| ~/Library/... | User-writable | High |
| @rpath (app bundle) | Needs app write | Medium |
| /System/Library | SIP protected | Low |
Privilege Escalation Path¶
1. Normal user runs admin app (sudo, etc.)
2. App has weak dylib in writable location
3. Attacker (as normal user) plants malicious lib
4. Next time admin runs app:
Malicious code runs with admin privileges
Detection Difficulty¶
| Indicator | Visibility |
|---|---|
| Malicious dylib on disk | Visible if you look |
| Load at runtime | In logs (if enabled) |
| Code execution | Indistinguishable |
Once loaded, malicious code looks legitimate.
Safer Alternatives¶
| Instead Of | Use |
|---|---|
| Weak linking | dlopen() with checks |
| Optional features | Feature detection at runtime |
| SDK flexibility | Bundle required SDKs |
Dylib Hijacking Attack¶
- Application weakly links to
/opt/SomeSDK/lib/helper.dylib - Attacker notices the library doesn't exist on the system
- Attacker creates
/opt/SomeSDK/lib/helper.dylibwith malicious code - Application loads attacker's library with full privileges
Real-World Impact¶
- Privilege escalation: Malicious code runs with app's permissions
- Data theft: Access to app's memory and files
- Persistence: Library loads every time app runs
- Code signing bypass: On older macOS versions
Resolution¶
Use Strong References¶
Before (vulnerable):
After (secure):
Bundle Required Libraries¶
Instead of weak linking, bundle the library with your application:
MyApp.app/
βββ Contents/
β βββ MacOS/
β β βββ MyApp
β βββ Frameworks/
β βββ helper.dylib β Bundle the library
Runtime Loading with Validation¶
If optional library support is needed, load at runtime with validation:
#include <dlfcn.h>
void *handle = dlopen("/path/to/lib.dylib", RTLD_LAZY);
if (handle) {
// Validate the library before using
// Check code signature, etc.
}
Xcode¶
Check Link Binary With Libraries and remove any libraries marked as "Optional".
When to Suppress¶
This rule may be suppressed for:
- Plugin systems: Intentionally optional features
- SDK compatibility: Supporting systems without certain frameworks
- iOS: iOS's strict code signing mitigates this attack
Platform Notes¶
- macOS: Primary concern; attackers can place files
- iOS: Less concerning due to code signing and sandboxing
- Hardened Runtime: Mitigates but doesn't eliminate the risk
Related Rules¶
- AD5006 - Symbol namespace security