In my daily life of sysadmin, I copy-paste many chunk of text (commands, IP addresses, URLs, file paths, whole scripts or file contents sometimes because it's easier to copy-paste them rather than to scp them). I usually copy them from other servers or from my company's internal documentation (trusted sources). However, I may sometimes follow howtos or read Stackoverflow answers and copy text and commands from those less trusted websites.
I want to talk about how easy one could trick you by replacing copied text in your clipboard or inserting terminal escape sequences so that your shell will run additional and potentially malicious commands. And how I protecting myself against these tricks.
Tricks I have identified
Here is a list of tricks an attacker can use to fool you and make you paste a malicious command in your terminal.
Replacing copied text with Javascript
Dylan Ayrey demonstrates that with a few lines of Javascript, a malicious website can alter your clipboard content. The code runs on key release event (keyboard shortcut or right click) and override clipboard content with the malicious code the attacker wants you to execute.
Obviously this attack doesn't work if you disable Javascript on unstrusted websites, which is by the way always a good idea.
Hiding malicious code with CSS
But even with Javascript disabled it's easy for an attacker to put hidden text
in your clipboard. The idea is to put the malicious code in the middle of the
displayed command in a <span />
element and apply different
CSS properties on it, so that the malicious code isn't visible for the user. For
instance make it float and move it away from the viewport, make it transparent,
with no height or width…
Here is an interesting article about this attack. It also show how to hide the malicious code once pasted in the victim's terminal so that the victim can't even known he has been p0wned.
What about disabling CSS then?
Inserting non-printable characters
That's no enough since you could have non-printable characters (like backspaces) in raw text. Here is an example (the whole thread is an interesting reading by the way). Basically, the idea is to insert extra characters and a backspace character after each of them to make the code appear inoffensive.
How I protect myself
So what next? What solutions I use to protect myself against those attacks?
Pasting into a text editor: the bad idea
In most shell, I can easily start $EDITOR
with ^X^E
to edit the current
command. But that's totally ineffective since the pasted text can contain
^ESC:!<malicious code>
which will work in vim, or simply send the right
shortcut to close the editor and get back to the shell.
Shell's bracketed paste mode
This is an elegant solution. Bash (actually readline) can configure the terminal to enclose the pasted text between paste sequences (hence the bracketed paste mode):
enable-bracketed-paste (Off) When set to On, readline will configure the terminal in a way that will enable it to insert each paste into the editing buffer as a single string of charac‐ ters, instead of treating each character as if it had been read from the key‐ board. This can prevent pasted characters from being interpreted as editing commands.
To enable it:
$ echo "set enable-bracketed-paste on" >>~/.inputrc
If you then try to paste multi-lines commands in your terminal, the commands won't be executed unless you press enter. You have a chance to review and edit them before their execution.
But it has two main drawbacks:
- obviously enabling bracketed paste mode will work on your own computer only, unless you enable it on all your remote servers as well.
- you may still be vulnerable to code injection if the pasted text contains the bracketed-paste-mode end sequence, whether your terminal automatically filter this sequence or not.
You can test this here.
confirm-paste plugin in URxvt
URxvt has a nice plugin called paste-confirm. It is shipped with URxvt and can be found in its plugin directory (/usr/lib/urxvt/perl/). Once loaded, the plugin will detect multi-lines pastes and will ask you whether to really paste it to the shell or not.
To enable it, simply add it to the plugin list in your ~/.Xdefaults:
URxvt.perl-ext-common: […],confirm-paste
Print your clipboard content before you paste
It's always a good idea to double-check your clipboard content before pasting it somewhere. I sometimes don't remember or I'm not sure about what was my previous selection, and I remember pasting whole file content into my terminal a couple of times…
I now use clipster for my cliboard manager with roficlip. Thus with a simple shortcut I can quickly double-check and select the previous entries in my clipboard.