Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I often use cat on the console to view the contents of files, and every now and then I accidentally cat a binary file which basically produces gibberish and system beeps. However today I've encountered a situation where the output from the cat utility got redirected to the console input so I got stuff like this:

-bash: 2c: command not found
-bash: 1: command not found
-bash: 1: command not found
-bash: 112: command not found
-bash: 112: command not found
-bash: 1: command not found
-bash: 0x1: command not found
-bash: 2c1: command not found
-bash: 2c: command not found
-bash: 1: command not found
-bash: 1: command not found
-bash: 112: command not found
-bash: 112: command not found
-bash: 1: command not found
-bash: 0x1: command not found
-bash: 2c1: command not found
-bash: 2c1: command not found
-bash: 2c1: command not found
-bash: 2c1: command not found

...
...

This made me thinking that a specifically crafted binary file could in such a way create quite a mess on the system?!... Now I do realize using cat recklessly like this is not particularly smart, but I would actually like to know what is going on here. What characters did produce the effect of suddenly dumping the content on standard input...

Note: I was in Mac OS X terminal while doing this, I've actually called diff -a to compare two firmware rom images and print the differences out(I thought there would be just few bytes of differences but there where almost 8 MB od differences printed to the screen) Later I tried on purpose with the cat on one of the files and got the same effect like I've pasted here.

- UPDATE - - UPDATE - - UPDATE -

I've posted this here late at night yesterday and this morning I tried to replicate the behaviour and I can not. Unfortunately I can not be sure if some escape characters caused the gibberish from the binary to be executed on the console automatically or if at the end of the cat I just got a bunch of characters left(as If I've pasted them) on the command line and I've probably pressed enter accidentally to get a clear line...

When I try to cat the file in question now I get this when it completes(scroll right to see):

D?k(Fli9p?s?HT?78=!g??Ès3?&é??  =??7??K?̓Kü<ö????z(;???????j??>??ö?Ivans-MacBook-Pro:FI9826W-2.11.1.5-20140121 NA ivankovacevic$ 1;2c1;2c1;2;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c;1;1;112;112;1;0x1;2c1;2c;1;1;112;112;1;0x1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c

My actual prompt is:

Ivans-MacBook-Pro:FI9826W-2.11.1.5-20140121 NA ivankovacevic$

Where:

FI9826W-2.11.1.5-20140121 NA

is the current working dir. As you see it was camouflaged in the binary gibberish and I might have pressed enter reflexively or something. This in it self is a bit wrong behaviour of cat because obviously my prompt might have been even better "camouflaged". But it is less serious then I initially thought. Although I'm still not 100% sure that it did not execute automatically last night when I tried, because there was also another peculiar thing that happened last night, before this. I've called cat on another very similar file that caused Terminal app to quit with:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00007fcb9a3ffffa

Now I'm thinking that maybe a combination of these two events have caused the auto execution of gibberish on the console. But I can not replicate that behaviour now again.

The files in question are firmwares for a Foscam IP camera, here are the links:

International site: http://foscam.com/Private/ProductFiles/FI9826W-2.11.1.5-20140120.zip
And then the file inside: FI9826W_app_ver1.11.0.40_OneToAll.bin

calling cat on that one will cause Terminal to quit.

US site: http://foscam.us/downloads/FI9826W-2.11.1.5-20140121%20NA.zip
and then the file: FI9826W_app_ver1.11.0.40_OneToAll_A.bin

cat-ing that one will cause that paste of 1;2c1;2c1;2;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c.... characters on the command line

share|improve this question
3  
Ah, those comforting memories from a time where ANSI bombs where around and widely known... –  PlasmaHH Apr 24 at 8:32

7 Answers 7

up vote 21 down vote accepted
+150

Yes, it's a potential risk, see CVE-2003-0063, or CVE-2008-2383 or CVE-2010-2713, or CVE-2012-3515 or OSVDB 3881, or CVE-2003-0020 or any of the similar ones listed here... Some more in comments below also.

Update it's not just a potential risk, it's a real risk. The current version of a popular terminal emulator has this problem, resulting in user-assisted execution of arbitrary commands simply by invoking cat on a crafted "text" file. (Details withheld at this time for responsible disclosure.) Details below.

Update rxvt-unicode (versions 2.7—9.19, patched in 9.20) allows read/write access to X window properties, this can enable user-assisted execution of arbitrary commands, this issue has been assigned CVE-2014-3121, more details here https://bugzilla.redhat.com/show_bug.cgi?id=1093287 .

This topic also has good coverage here: http://unix.stackexchange.com/questions/73713/how-safe-is-it-to-cat-an-arbitrary-file and a thorough analysis of the underlying problem from Gilles here: http://unix.stackexchange.com/questions/15101/how-to-avoid-escape-sequence-attacks-in-terminals .


Explanation

What you are observing is a side-effect of how certain escape sequences behave: some of them stuff characters (usually also containing escape sequences) directly into the terminal input buffer. All in the name of backward compatibility, of course. The standard xterm escapes which are described using the term "Report <something>" do this. This behaviour permits programs to query/set terminal (or other) properties "in band" rather than via ioctls or some other API.

As if that wasn't bad enough, some such sequences can contain a newline, which means that whatever is reading from the terminal (your shell) will see what appears to be a complete user command.

These sequences can vary by terminal, but for rxvt and derived, the graphics query escape includes a newline (example using bash and $'' strings, see doc/rxvtRef.txt in the source)` :

$ echo $'\eGQ'
$ 0
bash: 0: command not found

This escape sends \033G0\n into the terminal input buffer (or digit 1 instead of 0 if you have a graphics-capable rxvt).

So, combine this escape with other sequences which behave similarly:

echo $'\x05' $'\e[>c' $'\e[6n' $'\e[x' $'\eGQ'

for me this causes 11 attempts to run various commands: 1, 2c82, 20710 (my rxvt version string), 0c5, 3R (5 and 3 were the cursor coords), 112 and 0x0.

Exploitable?

With rxvt and most recent terminal emulators you should "only" be able to create a limited set of mostly numeric sequences. In old terminal emulators it was possible (some CVEs listed above) to access the clipboard, the window icon and titlebar text to construct more malicious strings for invocation (one current slight exception is if you set the answerbackString X resource string, but that cannot be directly set using this method). The flaw then is allowing arbitrary read and write access to something that passes for state or storage within escape sequences that stuff data into the input buffer.

rxvt requires compile time changes to activate, but urxvt helpfully has an -insecure command line option that enables some of the more exciting features:

$ echo $'\e]2;;uptime;\x07' $'\e[21;;t' $'\eGQ' 
bash: l: command not found
17:59:41 up 1448 days,  4:13, 16 users,  load average: 0.49, 0.52, 0.48
bash: 0: command not found

The three sequences are:

  1. \e]2;...\x07 set window title;
  2. \e[21;;t query window title, place in input buffer;
  3. \eGQ query graphics capability, which adds \n to input buffer.

Again, depending on terminal, other features such as font size, colors, terminal size, character set, alternate screen buffers and more may be accessible though escapes. Unintended modification of those is at least an inconvenience, if not an outright security problem. Current versions of xterm restrict potentially problematic features via "Allow*" resources.

CVE-2014-3121

Prior to v9.20, urxvt did not also guard read and write access to X properties (mostly used by window managers). Write access now requires the -insecure option.

$ echo $'\e]3;xyzzy=uptime;date +%s;\x07'
$ xprop -id $WINDOWID xyzzy
xyzzy(UTF8_STRING) = 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x3b, 0x64, 0x61, 0x74, \
0x65, 0x20, 0x2b, 0x25, 0x73, 0x3b

This can be trivially used to stuff arbitrary strings into the terminal input buffer. When the escape sequence to query a property is invoked (along with helpful \eGQ which adds a newline):

 $ echo $'\e]3;?xyzzy\x07' $'\eGQ'
 $ 3;uptime;date +%s;0
 bash: 3: command not found
 17:23:56 up 1474 days,  6:47, 14 users,  load average: 1.02, 1.20, 1.17
 1400603036
 bash: 0: command not found

Multiple commands, preserving whitespace and shell metacharacters. This can be exploited in a variety of ways, starting with cat-ing an untrusted binary of course, further ideas in H.D. Moore's short paper (2003).


Followup

For the escape sequence you ask about: 1;112;112;1;0x1;2 This is: Request Terminal Parameters (DECREQTPARM) and Send Device Attributes :

$ echo $'\e[x' $'\e[0c'
;1;1;112;112;1;0x1;2c

The second one (\e[0c) is the same as ^E (using rxvt). There are some escape sequences in there too. the full sequence written for each is, respectively:

\e[1;1;1;112;112;1;0x
\e[?1;2c
share|improve this answer
1  
Good links! Here are some specific Apple ones cvedetails.com/cve/CVE-2005-1341 or cvedetails.com/cve/CVE-2009-1717 and probably there are more... –  Ivan Kovacevic Apr 22 at 22:45
1  
I found the issue today (while searching for interesting format strings), no names or details until it's coordinated with the authors. –  mr.spuratic Apr 24 at 18:06
1  
Will do. My speculative answer (no OS X machine to hand) on the segfault is withheld for the same reason. –  mr.spuratic Apr 24 at 18:13
1  
Damn, I'm dying of curiosity now for both things. Would a i.imgur.com/eNoBclw.jpg do? :) –  Ivan Kovacevic Apr 24 at 18:24
1  
I am in contact with authors, I will update answer with promised details soon. –  mr.spuratic Apr 30 at 0:15

Yes.

As you seem to be using a modern terminal emulator, some escape sequences could be used to modify Keyboard buffer.

There could be proper shell commands injected.

You could use argument -e of cat for safe operation, see man cat.

  -e     equivalent to -vE

  -E, --show-ends
         display $ at end of each line

  -v, --show-nonprinting
         use ^ and M- notation, except for LFD and TAB

Addendum

In fact, it was possible, but in a very old past... As this became an issue, these kinds of features was quickly removed, but...

When you read command not found, this implies that something was effectively injected.

The main injection feature that was not removed is the sequence indentify yourself, used in many VT-100 encapsulation.

This sequence is Escape Z which will inject the string 1;2c into your keyboard buffer, which means VT-100 (in AVO convention).

Speaking about cat, you could try:

cat <<< $'\033Z'

and on next line prompted, you will see 1;2c (or maybe with another numbers, depending on terminal used) as if you hitted them.

... and

cat -e <<< $'\033Z'
^[Z$

Where -e => -vE, -v transform \033 into ^[ and -E put a $ sign at end of line (and nothing will be put on next line, you keyboard buffer is not affected).

You may find lot of funny things at VT100 User Guide (like: cat <<< $'\033#8' ;)

(They was modern terminal! In some past... )

Trying using

There is a little bash command for flushing keyboard buffer and get his content:

cat <<<$'\033Z';buf='';while read -t .1 -n 1 chr;do buf+="$chr";done;printf "\n>|%q|<\n" $buf

^[[?1;2c
>|$'\E[?1;2c'|<

And a little function to test any chain:

trySeq() {
    printf -v out "$1"
    echo -n "$out"
    buf=""
    while read -t.001 -n1 char
      do buf+="$char"
    done
    [ "$buf" ] && printf "\r|%q|->|%q|<\e[K\n" "$out" "$buf"
}

So I could try:

for i in {0..255};do trySeq "\e[${i}n";done
|$'\E[5n'|->|$'\E[0n'|<
|$'\E[6n'|->|$'\E[21;1R'|<

And now?

From there, unfortunately, there is no standard.

Every virtual terminal implementation could support full ANSI and/or full DEC standard...

But as there are some security issues, many don't...

You could observe some behaviour using one terminal that you wouldn't observe using another...

xterm, linux console, gnome-terminal, konsole, fbterm, Terminal (Mac OS)... the list of terminal emulators is not so short!

And each of them has its own bugs and limitations compared to DEC and ANSI standards.

In pactice, you may find some virtual console that could be more featured than other and where keyboard injection could break your security.

It's one of the reasons because I prefer to use alway same (old) xterm rather than other more featured tools.

share|improve this answer
11  
Oh? Care to share details? To the extent that it's true, this is a critical security vulnerability in the terminal emulator. –  tylerl Apr 22 at 5:49
1  
This is why some of the ANSI escape sequences are generally disabled in modern terminals/emulators. –  keshlam Apr 22 at 7:38
6  
cat -e, good advice! I'm still interested if you could maybe expand your answer with an example of those escape sequences to modify the keyboard buffer which could possibly explain this. –  Ivan Kovacevic Apr 22 at 12:39
1  
When I type man cat all I see is that -e is "equivalent to -vE", but no info is given on -vE... –  anorton Apr 22 at 18:35
2  
The convention is that single character flags can be grouped together, so -vE is the same as -v -E. i.e., the man page is telling you to look at the documentation for the -v and -E flags which mean "show non-printing characters using ^ and M- notation" and "Show line endings as a $ character", respectively. –  Cookyt Apr 22 at 18:42

Typically there is no vulnerability, but obviously if you use it wrong, then you could create one.

Printing the contents of a binary file produces beeps because character 7 is the old terminal command to make the machine beep, and some terminal programs still honor that command. But by design, there's nothing there that can hurt you. In the worst case, simply open up a new terminal window to undo any mess that might have been created.

Now, if you somehow redirected the contents of a file to a command shell, that's another matter. You could do this by piping the output of something to /bin/bash (typically frowned upon from a security perspective) or you could have perhaps inadvertently copied and pasted it into your terminal. Also typically ill-advised.

But as long as you don't run the thing, you're fine.

share|improve this answer
1  
In this case I've just typed: cat <file_name>. So I did not paste some bogus command in the console, but check my update to the question that I've just wrote. –  Ivan Kovacevic Apr 22 at 14:38

"Real" glass terminals had an escape sequence to print the screen to a printer. They did this by running a command and pipeing the current screen contents to the stdin of the print command.

The command could be configured by another escape sequence.

The classic way of exploiting this was to create files with names that embedded the escape sequence to set the printer command and change it to some script of your choice and then have a 2nd file with the print escape sequence in it.

When someone then ran ls in that directory they would end up running your code. Which was nice if they were the root user!

In theory modern terminal emulators shouldn't do that kind of thing any more.

Terminal.app appears to be based on the NextStep nsterm, so it may have all kinds of weirdness in it.

Maybe try narrowing down which exact bytes are producing the command not found messages?

Looks like there are escape sequences to raise and lower the terminal:

http://the.taoofmac.com/space/apps/Terminal

some more info here:

http://invisible-island.net/ncurses/terminfo.src.html#toc-_Apple__Terminal_app

If you want to send content to a program's stdin,

program -para meters < /path/file.ext
share|improve this answer
    
"current screen contents to it's stdin" — screen contents isn't stdin. –  Ruslan Apr 22 at 11:35
    
@Ruslan: He means the stdin of the command to which the screen contents are being piped. –  jwodder Apr 22 at 16:40
    
Then it should be its not it's –  Ruslan Apr 22 at 17:14
    
@JasperWallace: Cool info! Examples: To minimize Terminal.app: echo -e '\x1B[2t' To minimize-maximize echo -e '\x1B[2t\x1B[5t' :) –  Ivan Kovacevic Apr 22 at 22:23

What you are seeing is xterm control sequences.

Control sequences are activated when they are seen in output in the terminal; e.g., when you cat a file with bytes that are non-printable ASCII.

In your example, the control sequence is ESC Z (bytes 1B 5A) which returns the terminal ID -- as a command in the terminal.

You can try it yourself:

echo -e '\x1BZ'

(Alternatively you can write ESC as \e or Z as \x5A).

There are some other fun ones too:

echo -e '\eF' # move the prompt to the bottom of the terminal.
echo -e '\ec' # Reset the terminal
share|improve this answer
    
Actually echo -e '\x1BZ' in my case just prints out an empty line. However echo -e '\x1B[\x1BZ' prints that "1;2c" on the command line which I was getting repeatedly after cat-ing that firmware binary file. That is <ESC> and [ which is known as <CSI> escape sequence, followed by <ESC> Z. However I have no idea what that 1;2c means. Is that the terminal ID?! –  Ivan Kovacevic Apr 22 at 22:18
    
@IvanKovacevic Yes, see my addendum. ( My first answer was too quick. sorry ;) –  F. Hauri Apr 22 at 23:34
1  
@dr jimbob: I was not right, echo -e '\x1BZ' does work, but it has some strange behaviour on Mac OS X. If I issue it for the first time and delete the outputted characters, then press enter to get a clear new prompt(Because echoing that leaves some gibberish in-front of the prompt line also, or on the back, depends how you look at it). Then if I try to recall the last command with the up key, and call it again, it does not work anymore... Just a new-line gets printed. That is why I initially though it was not working, because I've called it already... On Linux it works regardlessly every time. –  Ivan Kovacevic Apr 23 at 2:58
    
And echo -e '\x1B[\x1BZ' also works every time. I suppose the CSI sequence resets it. –  Ivan Kovacevic Apr 23 at 3:02
1  
alias clear="echo -e '\ec'" Finally, a clear in cygwin <3 –  Qix Apr 24 at 0:45

I'm gonna add this info here without actual intention to answer my own question. The characters that can get injected on the command line while printing some other characters, better know as escape sequences, are defined really good on this site(Thanks F. Hauri, for mentioning it):
http://vt100.net/docs/vt100-ug/chapter3.html

Under chapter: Reports


Cursor Position Report

Invoked by ESC [ 6 n
Response is ESC [ Pl ; Pc R
Pl = line number; Pc = column number

Status Report

Invoked by ESC [ 5 n
Response is ESC [ 0 n (terminal ok)
ESC [ 3 n (terminal not ok)

What Are You

Invoked by ESC [ c or ESC [ 0 c
Response is ESC [ ? 1 ; Ps c

Ps is the "option present" parameter with the following meaning:

Ps Meaning
0 Base VT100, no options
1 Processor options (STP)
2 Advanced video option (AVO)
3 AVO and STP
4 Graphics processor option (GPO)
5 GPO and STP
6 GPO and AVO
7 GPO, STP, and AVO

Alternatively invoked by ESC Z (not recommended). Response is the same.


ESC is ASCII decimal 27 or octal 33 or hexadecimal 1B.

So to get for example current cursor position printed out, or better said injected into your existing command line, you would call:

echo -e '\033[6n'

and the output would be something like this:

7;1R

You can move the cursor position with the following escape sequence

echo -e '\033[10;20H'

10 - row 10
20 - column 20

However it's not moving the column position(it does move through rows) because the terminal probably resets it to the beginning of the line. Anyhow, if you query the cursor position right after that it's going to "paste" on the console the set column position:

echo -e '\033[10;20H\033[6n'

output:

0;20R

That's how you can get different outputs injected('pasted') on the console, it is far from any real exploit since this will give only different number combinations that can be outputted, but then again maybe combined with something else. Who knows.

In my case where I've cat-ed the firmware image I got lots of: 1;2c Now I know that it is the "What Are You" report, of what my terminal is, where 2 means: Advanced video option(AVO).

All in all it's definitely better to avoid mindlessly cat-ing any file...
As already suggested(also by F. Hauri), at least use cat -e

share|improve this answer

There are obvious risks in piping a random file to an interpreter of any kind, but unix isn't set up to protect users from their own stupidity. Simply using cat filename may mess up your display but it shouldn't damage anything.

If you are using cat to view files and identify their type I would suggest that you learn about file ( tells you what the file is ) and less which will warn you if you are looking at binary data, and won't dump a 100Mb installer archive to your console. zless will transparently open gzip files.

share|improve this answer
    
Piping a random file to an interpreter(i.e. bash) is, of course, hugely dangerous. But it is not what we are discussing here. Only displaying content, with cat, which as history has shown CAN produce damages. Check the answer from mr.spuratic. –  Ivan Kovacevic Apr 23 at 14:08
    
To add to paul's answer, it has been said lots of times, yet old habits die hard : don't use cat for this, use less or a text editor. –  schaiba Apr 23 at 16:58

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.