As information security professionals, we have to deal with potentially dangerous files practically on daily basis. We run various scripts, PoC code, exploits and other things and we put trust in the utilities that read those files. Can we really trust them? In this article we will have a peak into the world of ANSI/VT escape sequences.

What are the escape sequences?

Quoiting from a relevant mailing list memo by Federico Bento:

A terminal escape sequence is a special sequence of characters that is printed (like any other text). But, if the terminal understands the sequence, it won’t display the character-sequence, but will perform some action.

Escape sequences can do all sorts of things. Besides of changing color of the text, making it bold or making our cursor blink, they can also:

Move cursor in any direction or to any position

Delete or erase arbitrary text

Perform various screen manipulations

Even re-map keys on our keyboard!

In short, escape sequences can adversely change the way how we see things on the terminal.

And it can have really bad consequences:

And it works everywhere and with anything! For instance, here’s an example of escape injection in a Python script on Mac OS:

But wait, I’m safe on Windows!

Unfortunately, you’re not. Since Windows 10 the Windows Terminal emulator also supports ANSI/VT escape sequences. And it is used by both the Command Prompt as well as the PowerShell!

So, this also works on Windows..

So what is going on here?

Welcome to the world of terminal escape injections, or as some folks have called it in the past – The new XSS for Linux sysadmins.

We now know that it’s not just a Linux thing – it affects every platform that uses VT/ANSI compatible terminal.

And it’s nothing new. Terminals have been with us since the dawn of computers.

There are many different terminal emulators out there and each of them can have specific escape sequences on top the common ANSI/VT ones.

When these escape sequences are used in a malicious way (with a malicious intent), it’s called terminal escape injection.

Ok, so what’s the potential impact?

The consequences of falling for this trick could be obviously very serious. Disastrous, if we are running as root / Administrator.

Basically we could be fooled into executing arbitrary code (ACE) on our system and completely compromising ourselves. For instance, an attacker could:

Install backdoor (RAT) on our system

Plant malware or rootkit on our system

Capture keystrokes and record our screen

Practically anything you can imagine really

On top of it, there has been many different vulnerabilities reported throughout the years attributed to escape injections.

Where can we find escape injections?

Apart from planting them into various scripts, they could be also successfully planted into:

Configuration files – potentially with the same impact (ACE)

Log files – as part of detection bypass efforts

So how safe is it to cat an arbitrary file?

As we have already seen, it is not safe at all. But the same can be said about the get-content command in Powershell, or the type command in the Command Prompt.

The problem with these things is that they do not sanitize the output in any way. They merely print out whatever content is there. They don’t care.

So if there is some binary content, they will just print it out and we will see some gibberish.

And if there happens to be some particular byte sequence that the ANSI/VT terminal understands as an escape sequence, then the terminal will simply interpret it.

So this is not really a bug. That’s just how things are with console applications. And as infosec professionals, we should be vigilant about the risks.

How escape injection works?

Let’s consider the following shell script with visibly displayed escape injection:

Now suppose we didn’t use the -v parameter. As the cat command is displaying the content of the script line by line, the escape sequence ( ^[[2A ) will move the cursor 2 lines up – back on the position where the evil code is. And then the code will be rewritten by our benign (Hello World) code.

Note that this is just for demonstration purposes. The escape sequences are powerful enough so that we don’t need to use any benign or fake code. We could simply make the malicious lines disappear, if we wanted to.

How to avoid escape sequence attacks in terminals?

Here’s an actionable advice on how we can protect ourselves from escape injections:

UNIX/Linux

1. On UNIX based systems, beware of the utilities that output raw data. This includes:

cat, head, tail, more

curl, wget

diff

Do not believe their output without thoroughly inspecting it, when it matters.

2. Use cat -v to display non-printable characters or use the less command.

For instance, we should never install software from the Internet just by using curl / wget and piping it into shell. Visual analysis is not enough:

We should always inspect it using cat -v or using the less command to see if there is something fishy going on:

We can clearly see the nastiness there.

3. We can also use text editors such as nano, pico, vim, emacs or any other editor that we prefer.

Windows

1. In Command Prompt we can use the more command instead of the type command. The more command will reveal the escape sequences:

But it doesn’t work in PowerShell.

2. In PowerShell it seems there is no way to sanitize the escape sequences by using some parameter or some other function instead of using the get-content command.

I was only able to come up with the following somewhat clumsy and complicated solutions to reveal the hidden terminal injections:

Solution 1:

gc <file> -encoding Byte | % { [char]$_+" " | write-host -nonewline }

Solution 2:

gc <file> -encoding Byte | % { if ( $_ -lt 32 -or $_ -gt 126 ) { [char]$_+" " } else { [char]$_ } } | write-host -nonewline

They both work and will reveal the hidden escape injections.

3. Best solution on Windows is to always use text editors such as Notepad or WordPad. Do not rely on console utilities.

Test it for yourself

The following snippets provide instructions on how to generate all the examples shown in this article.

You can also find them on our GitHub InfosecMatter dedicated repository.

Shell script escape injection

echo -e '#!/bin/sh



echo "evil!"

exit 0

\033[2Aecho "Hello World!"

' > script.sh chmod a+x script.sh

The resulting script.sh will then work on (has been tested on):

Linux (gnome-terminal, xterm, aterm)

Mac OS (Terminal 2.0, iTerm2)

Cygwin (Windows)

Python script escape injection

echo -e '#!/usr/bin/python



print "evil!";

exit(0);

#\033[2A\033[1Dprint "Hello World!";

' > script.py chmod a+x script.py

The resulting script.py will then work on (has been tested on):

Linux (gnome-terminal, xterm, aterm)

Mac OS (Terminal 2.0, iTerm2)

Cygwin (Windows)

Batch (Command Prompt) escape injection

echo -e '@echo off

\r

\recho evil!\r

::\033[2D \033[A\033[2Decho Hello World!' > script.bat

The resulting script.bat will then work on (has been tested on):

Windows 10 PowerShell

Windows 10 Command Prompt

PS1 (PowerShell) escape injection

echo -e 'write-host "evil!"\r

#\033[A\033[2Dwrite-host "Hello World!"' > script.ps1

The resulting script.ps1 will then work on (has been tested on):

Windows 10 PowerShell

Windows 10 Command Prompt

Conclusion

As we have seen in this article, terminal escape injections affect practically every modern operating system environment and they can be really nasty.

As infosec professionals, we should know about them and keep our guards up when it matters. Hopefully this article provided enough information to stay safe.

Please feel free to let us know in the comment section your thoughts.

References