Some time ago I read a tweet about hunting so-called “sticky-keys backdoors”, referencing a presentation at DEFCON 24, https://www.youtube.com/watch?v=EAYtRQKfna0 In addition to the presentation, the team released a tool called “Sticky Keys Slayer” that is publicly available on GitHub, https://github.com/linuz/Sticky-Keys-Slayer/
The sticky-keys backdoor is using a simple trick. On a Windows system, it is possible to enable accessibility features and sticky keys even on the login screen, i.e. before performing a successful login. Those features run an executable as NT AUTHORITY\SYSTEM. There are two executables, sethc.exe and utilman.exe. Both can be replaced by other executables if one has sufficient rights on the system. Say you replace them by cmd.exe and you will be able to run a high privileged shell on the machine without being authenticated. Another option, a bit stealthier is to set cmd.exe as the debugger for sethc.exe, ending up with a high privileged shell as well. The registry change required would look similar to:
REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe" /t REG_SZ /v Debugger /d “C:\windows\system32\cmd.exe” /f
A simplified, high-level overview of the “Sticky Keys Slayer” tool, that tries to detect the backdoors mentioned above, is as follows:
- Open a RDP session to the server with an invalid user to stay on login screen,
- Take a first screenshot of the session,
- Send the keys Shift Shift Shift Shift Shift,
- Send the keys Windows+U,
- Take a second screenshot of the session,
- Compare both screenshots to see if a command-line window has been opened by checking the difference of black pixels,
- Save the screenshot in a directory if the test is positive, in another one otherwise.
Being interested in this, I quickly pulled off a list of all Swiss IPs having port 3389 open from shodan.io using the following query:
This gave me 9450 hosts to test. I used the provided tools with minor modifications to make it work on my usual test machine and was good to go. The full scan took several hours to complete and gathered about 500 MBytes worth of screenshots.
After the scan, a quick visual check of the screenshot was done to rule out false positives and some false-negatives as well. The final count is as follows:
The high error count is mostly due to the fact that lots of the IPs with the RDP port being open were residential connections with a DHCP assigned public IP. The data from shodan being not real-time accurate makes it probable that many IPs were reassigned before our tests. It also means that more backdoored systems could be found in this gray area.
Among the backdoored systems were mostly end-users DHCP connections (80 out of 113). Then enterprises of all kinds, mostly small and medium ones, and a few big companies as well. In addition, some other things were to be found on the screenshots:
- All versions of Windows are present from XP/2000 to 2016 as well as some RDP client for Linux and Mac OS
- Information disclosure with an extensive bginfo background, https://docs.microsoft.com/en-us/sysinternals/downloads/bginfo
- Nice green-, yellow-, orange- or even pink-colored background instead of the default Windows blue
- Login through face recognition over webcam instead of a username and password
- Custom binary run instead of cmd.exe that first asks for a password instead of directly giving a shell
- Open root access on a Linux server with someone being busy installing a Monero coin miner :-)
All the vulnerable IPs were promptly reported either to Swisscom through their bug bounty / responsible disclosure program or to MELANI for all the IP’s that do not belong to Swisscom’s network ranges. Swisscom immediately forwarded the information to whomever was impacted and awarded a CHF 500 bounty since two of the backdoored servers were in the scope for the bug bounty.
What can a sysadmin do if he is presented with such a finding, “your server has been backdoored and is easily accessible for anyone on the Internet”? The immediate remediation for the sticky key backdoor is obvious. Replacing the malicious executable by the original Microsoft binary and/or removing the registry key will remove the backdoor. But how to determine who planted the backdoor, how did this person first got administrative access to the server and how to prevent it from happening again? This is a typical case where forensic investigation comes into play. There is no easy tips here but some preparation can be done in advance to maximize the likelihood of such an investigation to be successful, have a look at one of our previous post https://blog.compass-security.com/2017/06/forensic-readiness/
For some reason , on a windows server 2016 I can not get the hack to work (for demonstration purposes). Further more, I could not even act on the system32 folders without basically breaking the permissions chain (I’m sure hackers are not caring about that). I had to take ownership on the windows Dir and give the local admin ownership and full control just to move the executables around, and still, overwriting the “setch” file with “cmd” did nothing. Afterwords, when pressing the shift key 5 times, the sticky keys dialog would still appear.
Most other how to’s on this make no mention of having to modify the registry
I meant “sethc” exe
On Windows 2016, Utilman.exe and sethc. exe have restrictions by default. They are owned by TrustedInstaller and you cannot modify the files, even as NT AUTHORITY\SYSTEM. This is why you had to take ownership of the file and modify the permissions to replace it. However, it is still possible (and much easier) to modify the registry as explained in the blog post. I just tested it on a Windows Server 2016, it works, and you don’t need to change the permissions.
One more thing you must be cautious with is NLA. If NLA is enabled you cannot use this backdoor since you first have to authenticate on a network level (and thus cannot enter keys on the login prompt).
Good luck with your demo !