112

You should never paste from web to your terminal. Instead, you should paste to your text editor, check the command and then paste to the terminal.

That's OK, but what if Vim is my text editor? Could one forge a content that switches Vim to command mode and executes the malicious command?

  • 2
    @ryekayo I know how to run command in background. The question is more about if it is possible to switch vim from insert mode to command mode and then execute anything – Adam Trhon Apr 3 '17 at 13:17
  • 3
    Recent versions of Vim have bracketed paste, which is supposed to prevent this kind of attacks. – Satō Katsura Apr 3 '17 at 13:39
  • 2
    @EmilJeřábek The link in the post gives you enough reasons to run for the hills rather than do that. – Satō Katsura Apr 3 '17 at 17:04
  • 1
    @EmilJeřábek As you can forge hidden text with Escape character, I assume you can also forge text with EOF. Then the hidden text could contain something as /bin/bash ; EOF rm -rf ~. When pasted into terminal it would start bash, terminate it and then delete your home. When pasted into cat, it would let cat print the command, end cat and delete your home. – Adam Trhon Apr 3 '17 at 17:23
  • 3
106

Short answer: In many situations, Vim is vulnerable to this kind of attack (when pasting text in Insert mode).

Proof of concept

Using the linked article as a starting point, I was able to quickly create a web page with the following code, using HTML span elements and CSS to hide the middle part of the text so that only ls -la is visible to the casual viewer (not viewing the source). Note: the ^[ is the Escape character and the ^M is the carriage return character. Stack Exchange sanitises user input and protects against hiding of content using CSS so I’ve uploaded the proof of concept.

ls ^[:echom "This could be a silent command."^Mi -la

If you were in Insert mode and pasted this text into terminal Vim (with some qualifiers, see below) you would see ls -la but if you run the :messages command, you can see the results of the hidden Vim command.

Defence

To defend against this attack it’s best to stay in Normal mode and to paste using "*p or "+p. In Normal mode, when putting text from a register, the full text (including the hidden part) is pasted. This same doesn’t happen in Insert mode (even if :set paste) has been set.

Bracketed paste mode

Recent versions of Vim support bracketed paste mode that mitigate this type of copy-paste attack. Sato Katsura has clarified that “Support for bracketed paste appeared in Vim 8.0.210, and was most recently fixed in version 8.0.303 (released on 2nd February 2017)”.

Note: As I understand it, versions of Vim with support for bracketed paste mode should protect you when pasting using Ctrl-Shift-V (most GNU/Linux desktop environments), Ctrl-V (MS Windows), Command-V (Mac OS X), Shift-Insert or a mouse middle-click.

Testing

I did some testing from a Lubuntu 16.04 desktop machine later but my results were confusing and inconclusive. I’ve since realised that this is because I always use GNU screen but it turns out that screen filters the escape sequence used to enable/disable the bracketed paste mode (there is a patch but it looks like it was submitted at a time when the project was not being actively maintained). In my testing, the proof of concept always works when running Vim via GNU screen, regardless of whether Vim or the terminal emulator support bracketed paste mode.

Further testing would be useful but, so far, I found that support for bracketed paste mode by the terminal emulator block my Proof of Concept – as long as GNU screen isn’t blocking the relevant escape sequences. However, user nneonneo reports that careful crafting of escape sequences may be used to exit bracketed paste mode.

Note that even with an up-to-date version of Vim, the Proof of Concept always works if the user pastes from the * register while in Insert mode by typing (Ctrl-R*). This also applies to GVim which can differentiate between typed and pasted input. In this case, Vim leaves it to the user to trust the contents of their register contents. So don’t ever use this method when pasting from an untrusted source (it’s something I often do – but I’ve now started training myself not to).

Related links

Conclusion

Use Normal mode when pasting text (from the + or * registers).

… or use Emacs. I hear it’s a decent operating system. :)

  • 2
    You're supposed to enable paste mode (:set paste) before pasting in Vim. Then bracketed paste should take effect, provided that your terminal also supports it. Your proof of concept doesn't work when paste mode is enabled. – Satō Katsura Apr 3 '17 at 16:01
  • 1
    I don't see how bracketed paste mode is safe. If the attacker knows you're using bracketed paste, they'll just stick a \e[201~ sequence in the paste command to exit bracketed paste mode, and proceed to pwn you anyway. (Unless I missed some detail on how bracketed paste works?) – nneonneo Apr 3 '17 at 18:00
  • 2
    @SatoKatsura: I tried it on Vim 8.0.540, which wasn't vulnerable to the original attack. After adding \x1b[201~, the exploit functioned as before (i.e. only ls -la was written to the buffer and the echom command was executed). Therefore, I think that bracketed paste is still vulnerable to a targeted attack, and is not a strong enough solution. (Indeed, any form of in-band signalling is vulnerable!) – nneonneo Apr 3 '17 at 18:18
  • 2
    I tried it both with and without :set paste - the exploit still works. To be perfectly clear, I pasted the following (base64-encoded) blob: bHMgG1syMDF+GzplY2hvbSAiVGhpcyBjb3VsZCBiZSBhIHNpbGVudCBjb21tYW5kLiIKaSAtbGE=. On OS X, you can copy that, run pbpaste | base64 -D | pbcopy to get a raw version to paste to vim. – nneonneo Apr 3 '17 at 18:21
  • 1
    To be even more clear, I'm testing with an SSH connection to an Ubuntu 16.04 box, using the macOS Terminal.app. If your terminal emulator is stripping the escape sequence on paste, you could probably nest the sequence (e.g. \x1b\x1b[201~[201~) or something to fool the filter. – nneonneo Apr 3 '17 at 18:24
0

If you're using the X11 clipboard feature, or a platform-specific equivalent, and you use middle-button paste with mouse support enabled or a vim paste command and not any terminal paste command (shift-middle-button or whatever shortcuts the terminal offers) then you might be safe.

If not, then if you have a terminal emulator that supports bracketed-paste mode, and you've enabled that in your terminal and in vim, and that terminal emulator implements protection against the injection of the escape sequence that ends bracketed-paste mode, then you might be safe.

If not, then you might be vulnerable to the attack described here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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