Every point in the article is obvious. As a script kiddie pasting stuff from the internet (including stuff from the victim's website) back in the day, I was acutely aware of the fact that you can't paste something and hit enter anywhere ever (unless you strip out ', but even that isn't very reassuring given that the shell probably has undocumented edge cases as well as other problems at other layers such as the terminal [1]).
Anyway, shells are dumb and dangerous. A real interactive language should simply have a text box for text. I guess I could write a usual 10 paragraph rant on this but it really is that simple.
the thing is, it gets executed when enclosed in single quote too. that's what worried me. as i had been quoting urls within single quotes in shell commands and had been feeling relatively safe -- till now.
i noticed the single quote. know how it gets escaped from the quote. the point is : we that work on command line use single quote to enclose urls as parameter to curl/wget. and that's not safe if you don't char-by-char escape the url.
No it is not. The single quote example is wrong because the evaluation part $(...) is unquoted.
Take a closer look. The first single quote part ends after the first semicolon right before the $(
It's not wrong, it's just demonstrating that slapping single quotes around a string is not sufficient to make it safe. You need to escape the string properly. Guess how many people do that.
Writing '...' switches from "writing shell code" to "writing a single-quoted string". It does not switch to "writing arbitrary text" (since that would give us no way to end the string!). You should always convert arbitrary text to "single-quoted string" format: most of the time it will stay the same, e.g. "google.com"; sometimes it needs escaping to prevent benign corruption, e.g. "I'm a little teapot"; in this case it needs escaping to prevent malicious code injection.
Everyone pastes into their terminal, but you do have to be pretty naive to ever paste something blindly into your terminal (full depth of understanding of each mechanics isn't a requirement but basic understanding of high-level obvious components of the line being pasted should absolutely be).
There is literally no way to secure against people being hacked if the scenario is a user blindly following instructions without looking at / thinking about them.
(reply to sibling comment from unixbane which is [dead] for some reason:)
> tell me the specific way you check your stuff before pasting so I can tell you how it's either broken or you're the 0.001% user and nobody else does that.
I'm no 0.001% user, I'm not a shell expert and I can't catch everything but in the context of this particular post:
- I know how string quoting in programming languages broadly works (no need to know if ' or " escapes or not - just know that if there's any quotes inside the string it deserves a closer look)
- I know that $ in bash (& some other languages) precedes something dynamic (maybe variable substitution, maybe inline code, no need to know about stuff in any detail, just enough to be suspicious)
- I know pipe chars in shells generally separate commands (no need to understand io redirection in any detail here)
- I know that URLs tend to follow boring conventions - if it's not domain/alphanum/alphanum?alphanum=etc then it's suspect and needs further attention (URLs can contain many weird chars but normal ones tend not to).
The above bullets are pretty basic imo - you don't need to be a bash wizard to grok that much. If you know these, you'd never run the one-liner shown in the OP.
Extra:
- if it's a one-liner crossing scroll boundaries, that's too long (excepting very long URLs maybe if they're super-simple)
As a counter-example, here's the type of stuff most people copypaste into shells all the time:
curl http://example.com/simple/path | bash
That's interesting here for two reasons:
1. as an inline threat, it's clearly harmless - the URL has no unusual special chars or $ and the command is very short - it can be read & grokked at a glance.
2. as a general threat, this is very dangerous because (a) it's unencryped/MITM-able and (b) you may or may not trust the hosted script being downloaded and eval-ed on your machine.
My overall point here is: there's plenty of valid & dangerous social engineering threats in your terminal; plainly obvious inline quoting problems ain't it.
Usually its https nowadays but other than that there's methods a hostile webserver can detect whether the content is piped or not (IIRC I/O speed). It can decide to inject different commands based on whether it is piped or not. So you need to end up writing to a file with redirect or tee. Or by using a hash of the script. We do that with binaries, why not with scripts? If its complex enough, a shell script should be considered source code.
Please tell me the specific way you check your stuff before pasting so I can tell you how it's either broken or you're the 0.001% user and nobody else does that. I've always just pasted into a text editor and recopied it from there (and even that may not be safe). On one hand, UN*X is not meant to have paste so you should just never use it. On the other hand, if you're using webshit you have to copy from it because there's no UN*X way to get at the data as the page has to be accessed in a proprietary way. On the other hand, I could just use a real OS that doesn't have deep reaching problems in the most basic things
and even worse: if you find a snippey of code online, once you read it carefully and you understand that it is safe to run - you might be lazy enough to copy it from the browser and paste it in the terminal. And it can be altered with JS before you copy it so you paste something different from what you have inspected. Of course you can use a buffer (say, a text editor) or even re-type that snippet yourself - but are you sure you'll never forget to do that?
> the copy-replace trick is harder to do if you use native copy (keyboard or mouse menu) & avoid "Copy" icons pages provide
Pretty sure that's not true. CSS allows you to choose both what's visible to the user, and also what's included in copy/paste. There's _some_ limitations on that, but it's flexible enough to have a lot of room to be extremely scary.
You can also have a lot of fun with fonts, something that looks like "cp a b" could actually, in text, be "rm a b"
You can do it via CSS trickery, or you can even do keyboard/mouse event detection and swap out via window.getSelection(), but both are much more involved & less reliable than via a button.
Pasting directly into a terminal or even a script is one step removed from blindly running eval(…) with arbitrary user input.
If you’re lucky it works. If you’re somewhat less lucky but still on the positive side, it doesn’t work with some syntax error that doesn’t corrupt anything.
There’s no excuse for not reviewing what is being executed before actually running it.
Reminder that copying text from a Web page is also vulnerable to "pastejacking", where the string going into the clipboard isn't the same as the user sees (e.g. adding a malicious prefix, made invisible with CSS)
Automating might actually make it safer, my typical idiom is `while read -r url; do wget "$url"; done < ./urls` (or `tail -zf ./urls|while…` to make it an url downloader daemon =P)
Not really though. How often do you paste code that's long enough to hide stuff like this from sources that you don't trust? Probably very rarely.
The real risk of this sort of thing is basically Bash injection - people who have bash scripts as part of their infrastructure that process public data. Sounds insane, yes. But there's a scary number of people who think Bash scripting is a sane thing to do.
Clever, but I really hope nobody is going to blindly copy-paste-go! a URL like that. Especially if you're technical enough to use a terminal, you should know better.
Lots of legit projects encourage this practice. Especially with quotes, it's a reasonable expectation that you're getting a literal. Conversely, it's unreasonable to expect that everyone can parse shell escape strings in their brains.
Now this example wasn't exactly well camouflaged, but I'd not be surprised if you can make it much more innocent looking.
People go nuts about curl | bash but then grab random packages off pip/gem/npm/brew/VimPlug/packages.el/VS Code without so much as a second look and they can all run arbitrary code too.
If you curl | bash from http, you may get MITM'd because you're not checking the checksum. Most modern package managers at least check that what was downloaded is indeed what the original developer intended, so it's slightly better.
How is it possible to be so wrong on so many levels in just two sentences?
1. Your epistemic reasoning capabilities are broken (as in, why do you think people should know better?)
2. You are just adopting an ad-hoc philosophy based on how shells work. If interactive languages had separate text inputs instead of just parsing a stream of text from stdin, pasting would always be safe. One may be tempted to call this "UN*X braindamage".
3. You appear to possibly believe in checking a URL before opening it type voodoo as well, regardless of shell issues
If a carpenter chops his fingers off, it's not the fault of the saw. People who use programs should be expected to know what's safe to put in and out. Having a base level expectation of competence for operators is normal.
A separate text input is just stdin by another name.
Yes, I believe people who paste URLs into the terminal should examine those URLs - you generally have to trim some stuff, quote, or rewrite things to make them useful. If you believe in wildly flinging data everywhere, good on you, I'd rather deal with easily avoidable problems such as demonstrated in TFA.
> If a carpenter chops his fingers off, it's not the fault of the saw.
That would be an effective argument, but this vile shit has existed for decades without being fixed, for no good reason. This saw is specifically designed to slice fingers off, rather than do useful work, for no reason.
> Having a base level expectation of competence for operators is normal.
UNIX expects perfection, while providing none of its own.
> A separate text input is just stdin by another name.
No, nitwit, it prevents in-band signalling, which is the entire problem here.
Anyway, I use Emacs for everything, and don't have these issues. With wget, I use -i - to enter multiple URLs at once, but it would also defeat this.
Because zsh has usually the url-quote-magic feature enabled which automatically escapes all special characters typed or pasted if the current argument is identified as URL.
After I wrapped it in quotes to workaround zsh safety mechanisms:
% curl 'http://example.com/;'$(gt=$(perl$IFS-E$IFS's//62/;s/62/chr/e;say');eval$IFS''cowsay$IFS''pwned$IFS$gt/dev/tty)';cowsay$IFS''pwned'
zsh: no such file or directory: perl \t\n
zsh: no such file or directory: eval \t\n
<!doctype html>
<html>
...
Single quote disables shell expansions. This input contains single quotes. I have yet to see a programming language with a "raw strings mode" that wouldn't end at the next suitable marker.
iTerm2 has a 'Advanced Paste' dialog which allows you to escape special shell characters, among other things. You can invoke it with Opt-Cmd-V. I discovered this feature a couple of days ago and wondered then under what circumstances it might be useful. Now I know.
SUSv4 requires that "if an operand resolves to the root directory, rm shall write a diagnostic message to standard error and do nothing more with such operands":