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.
s/party/hack like it's 1999
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
catof 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.
Comments
Jeremy Chadwick Friday, September 25, 2015 at 05:42 -
With regards to this comment: “The -v parameter shows all non-printable characters (which seems like a safe default to have, odd that it isn’t?).”
No, the -v parameter SHOULD NOT be the default. It IS NOT a safe default. Anyone who says otherwise is wrong. No wiggle room: flat out wrong. Please consider the implications of making -v the default; consider situations like the below, which are *incredibly* common and are common convention/operation in the *IX and UNIX world and have been for ~40 years:
Please think about what would happen if -v was the default in that scenario.
This whole debacle was already covered back in 1983 as well: http://harmful.cat-v.org/cat-v/
It seems to me that escape sequences and “general terminal behaviour” (and understanding ptys/ttys) is something of a “dying art”, meaning *IX users today seem to think that terminals are some kind of “black magic” and that certain behaviours that are absolutely expected/normal should be changed or inhibited because of their lack of knowledge of history or the “whys” of said decisions long ago. My gut feeling is that these, and several other aspects, of terminals and ptys/ttys were never fully passed on to younger *IX users by senior sysadmins like myself, including the nuances of use of things like GNU screen and the caveats of such (terminal-wise). For that I apologise, although I do regularly pass on terminal and escape sequence knowledge every chance I get; for example: http://lists.freebsd.org/pipermail/freebsd-stable/2011-June/063052.html
Random footnote: xxd is not available on all *IX systems. Alternates may include hexdump (also not available on every *IX), hd (also not available on every *IX*), and od (octal dump — yes, you can use this on things like classic Solaris, but not available on other *IX).
Mattias Geniar Friday, September 25, 2015 at 08:56 -
Hi Jeremy,
You make a valid point, one I hadn’t considered before – thanks for replying!
Mattias
frank Friday, September 25, 2015 at 21:02 -
Wrt/ the tar | ssh example: uuoc I’d say.
Mattias Geniar Friday, September 25, 2015 at 21:09 -
More acronyms! More! ;-)
Jeremy Chadwick Saturday, September 26, 2015 at 00:48 -
uuoc stands for “Useless Use Of Cat”. But in this case, it’s not useless. You need something that reads from stdin and outputs to stdout. I was unable to get the equivalent of “while read ; do echo >> file ; done” to work either. So if this is UUOC, then I’d love to know how to do it without cat and across multiple flavours of *IX.
Frank Monday, September 28, 2015 at 19:33 -
Hm… I can’t find it anymore but I thought there was something about a race condition when using cat like that. Anyway you could argue that it’s still not useless but dangerous, so I guess I have to take back my above argument…
Francis Kim Friday, September 25, 2015 at 15:24 -
Some great insight in this article – thank you, I’ll be forwarding this to my sysadmin friends :)
Mattias Geniar Friday, September 25, 2015 at 15:33 -
The more the merrier, everyone should be made aware if you ask me. :-)
Thanks for sharing!
Joseph Scott Tuesday, September 29, 2015 at 21:57 -
Same problem, new environment. This was a problem for many back in the MS-DOS days, with ANSI.SYS allowing your do similar attacks. Things like remapping the return key to delete the C drive.
Everything old is new again :-)
Hanno Saturday, November 14, 2015 at 19:58 -
Actually I’m not sure less is exactly the best tool to investigate suspicious content.
In most linux distros less will pass the input through a script called lesspipe that will – depending on the extension – run all kinds of tools that will try to interpret it in some way.
I’ve tried to start an effort to get some of these tools to be more resilient against attacks (actually this was one of the motivating factors to start the Fuzzing Project), but many of them were simply unmaintained and for some the fixing process took extremely long.
I once had the idea to create a “safer” version of lesspipe that would only include tools that were thoroughly tested with fuzzing, but never got to implement it.
Inbound links
- Links 12/10/2015: Linux 4.3 RC5, Parsix GNU/Linux 8.0 Reviewed | Techrights
- issue #3 | Cron Weekly: a weekly newsletter with the latest linux news & tools