A couple of weeks ago, the OSS-security mailinglist got a really interesting thread about the dangers of escape sequences inside a terminal. It didn’t really get a lot of attention back then but the follow-up thread made by Frederico Bento did.
These techniques have been known for many years (especially since escape sequences go way back), but I have to admit – I wasn’t aware of this kind of impact.
How it technically works:
A terminal escape sequence is a special sequence of characters that is printed (like any other text).
If the terminal understands the sequence, it won’t display the character-sequence, but will perform some action.
Escape sequences allow you to do funny things like write blinking commit messages, but there’s a darker side to them as well.
The example below illustrates the real danger of escape sequences.
$ printf '#!/bin/bash\necho doing something evil!\nexit\n\033[2Aecho doing something very nice!\n' > backdoor.sh $ chmod +x backdoor.sh $ cat backdoor.sh #!/bin/bash echo doing something very nice! $ ./backdoor.sh doing something evil!
(if you are going to test this, it’s important to have the printf-line be on a single line, without additional new lines)
Here’s what happened:
- A
cat
of the file did not show all the content in plain text, it interpreted the escape sequences and executed an action. - Executing the file then executed code that did not show up in the cat of that same file.
It’s important to remember: we can’t trust cat
at the command line.
Protecting yourself from malicious escape sequences
While it’s never been safe to just run curl installscript.tld | bash
from any site on the internet, these escape sequences show that downloading the file first and inspecting it with cat
(or more
, head
, tail
, …) can trick even experienced sysadmins.
There are a couple of ways to protect you from this.
cat -v $file
The -v
parameter shows all non-printable characters (which seems like a safe default to have, odd that it isn’t? Update: turns out, not a good idea to have as a default.).
$ cat -v backdoor.sh #!/bin/bash echo doing something evil! exit ^[[2Aecho doing something very nice!
cat $file | xdd
Catting a file and piping it to xxd (a hexdumper) will show you the escape characters as well.
$ cat backdoor.sh | xxd 0000000: 2321 2f62 696e 2f62 6173 680a 6563 686f #!/bin/bash.echo 0000010: 2064 6f69 6e67 2073 6f6d 6574 6869 6e67 doing something 0000020: 2065 7669 6c21 0a65 7869 740a 1b5b 3241 evil!.exit..[2A 0000030: 6563 686f 2064 6f69 6e67 2073 6f6d 6574 echo doing somet 0000040: 6869 6e67 2076 6572 7920 6e69 6365 210a hing very nice!.
less $file
The old saying of “less is more” is true here as well, since less
will show the escape sequences by default.
$ less backdoor.sh #!/bin/bash echo doing something evil! exit ESC[2Aecho doing something very nice! backdoor.sh (END)
Let’s all agree to never trust anything that has been posted on the internet without very thorough inspection. And let’s especially agree to never run an arbitrary command or script found on the internet, without really close inspection.
If you’re up for some more reading, the original oss-security thread has some impressive examples on how to fool diff and gcc compilation as well.