I don't think that's nearly as clever a counter-argument against curl|bash as they appear to.
A few points of the shortcomings of curl|bash vs RPM and others:
* curl|bash is not transactional. If you have an install/upgrade process in a different tab, and you close your terminal accidentally, how do you know if the install/upgrade completed?
* There's no obvious uninstall method, and you need to read the docs to see what, if anything, you should remove outside the main directory.
* There's no way of verifying if files have been tampered with post installation. This has negative security and operational consequences.
* It's much more vulnerable to MiTM attacks - a proxy with a successfully faked certificate can trivially modify a bash script on the wire and add a malicious command to it. This is hard for a user to detect. Packages are (on most distros) installed via package managers that verify GPG signing keys, making in-flight modification very very greatly more difficult.
* Packages are much more auditable - I can download a package and inspect it, and know that it will run the same actions on every machine it's deployed to. curl|bash can trivially serve different instructions to different requests, based on whatever secret criteria the server operator decides.
If you're going to try and argue that instead of doing what the generally accepted $good_thing is, and instead use $quick_and_easy solution that's widely perceived to be insecure, when you argue in defence of your position, you need to make very sure that you're not just trying to justify laziness. I don't think sandstorm have really thought about this hard enough.
I think the many discussions about this conflates two things:
1. "curl|bash" vs "curl >install.sh; sh install.sh"
2. install scripts vs package managers
The OP talks about how to detect a streaming execution of a script and exploit it. This proof of concept exploit aims at discouraging the the use of curl|bash as a means to installing code, and instead promotes that at least you should save the script (and review it) (i.e. the "curl >install.sh; sh install.sh").
All of the points you mentioned are valid and important pain points that affect any arbitrary executable install script (not verified cryptographically using a side channel). Deciding whether to use an install script or a packaging system is really a tradeoff.
The "obvious" problem the OP was talking about was that smell you feel when you see piping code to bash. I think OP made an excellent job showing how you can make it harder for people to spot and audit malicious code and how this is pretty serious downside for piping code into bash; It's more like: "I have a gut feeling this is horrible, so let's think about a way to prove that gut feeling", and the proof is insightful and non obvious.
(almost) all of your points are fair, but slightly tangential to their article: they want to put the "curl | bash is _insecure_" myth to rest. They explicitly acknowledge that it is worse than package managers in many ways.
Perhaps they should have said: "however, the following non-security arguments are valid, and there are more we didn't list." Agreed.
But, at the end of the day, they're right: it's not _less secure_ than, e.g., npm.
PS: In your list; "It's much more vulnerable to MiTM attacks" --- that's essentially the PGP vs HTTPS argument in disguise. Which they also cover, and acknowledge to be true; the argument is essentially "curl https:.. | bash is not less secure than any HTTPS based method, including npm, .isos, etc."
EDIT: and because this is such a hot topic, I just want to emphasize: I'm not arguing in favor of curl | bash. This is only a counter-argument to "curl | bash is less secure than other https- based install methods".
Many of my points have a security element to them. Such as inability to verify if files have been tampered with, inability to audit beforehand what the script will do and ease of MiTM attacks.
My point with the PGP argument is that you can indeed go through all those steps to verify their install script with GPG (although note that on top of the steps they run, you should ideally also verify the script against a known hash that you verified elsewhere to make sure that the contents of the script is what you expect, as well as the authors).
But the manual GPG verification process will be ignored by almost all users, who will decide they can't be bothered. My point about package managers is that they do this automatically, without requiring the user to jump through extra hoops. Which is much better than the 8 additional steps that almost no-one will bother with, in practice.
Also saying that it's not less secure than npm isn't a great benchmark - npm is really bad too. See the recent left-pad issues, for example. So yeah - it's not really much worse than other things which are also bad. But it's a lot worse than doing it properly, with a signed RPM repository.
> verify their install script with GPG (although note that on top of the steps they run, you should ideally also verify the script against a known hash that you verified elsewhere to make sure that the contents of the script is what you expect, as well as the authors).
If you've verified the script with GPG, the extra step of a hash is wholly unnecessary. Any change to the script's contents would immediately invalidate the GPG signature.
if you want to audit the script before you run it, you can just save it into a file first and then run it.
The point of this oneliners is to allow anybody to install it. It's insecure as hell, but whether you're piping it directly to bash or downloading an installer file and then executing it (like a great deal if not most of the software is still distributed to the general public anyway) makes not a big difference.
That's why the linked article is interesting; it shows that in fact there is a difference between piping to bash or downloading an installer. The difference is important and concerns the auditability. Any people who cares to audit the script might not notice anything suspicious but people who blindly pipe it to bash can potentially run code that is not the same that audtors see.
What's basically happening is the either a malicious software publisher, or a MiTM, fools auditors. And fooling auditors is bad because a lot of people rely on the community to signal this kind of abuse.
What an auditor could do to detect this kind of malware distribution is:
curl https://foo/bar.sh | tee >(md5sum)| sh
If she gets a different hash than by fingerprinting a saved download, it's an indication that the server is tampering with the installer.
However, people who follow good practices and want to audit the script are not affected by the problem in the first place, because they will just save the script and they will know how to execute it after having read it.
People who don't know how to audit the installer in the first place might not even know how to verify the download with GPG as well. Or worse, they won't bother and might deem the software to be too hard to install and choose to use something worse.
That's why sandstorm offers PGP-verified installs for those who know what they're doing and show how to use keybase to solve the web of trust issue.
(I'm not affiliated with sandstorm, but they seem a very reasonable and competent bunch to me)
> I don't think sandstorm have really thought about this hard enough.
I suspect we've spent far more time thinking about this than most people. We've heard every argument many times. The referenced blog post specifically addresses the security argument (hence the title) because that's the one we feel is most misleading.
I absolutely agree that curl|bash is ugly compared to package managers, but there are some serious shortcomings of package managers too, and it's a trade-off. With deb or rpm, we are tied to the release schedules of the distros, which is unreasonably slow -- Sandstorm does a release every week whereas most distros don't release any more often than twice a year.
We can perhaps convince people to add our own servers as an apt source or whatever, but now the MITM attack possibility is back. Yes, packages are signed, but you'd have to get the signing key from us, probably over HTTPS. No one wants to do the web of trust thing in our experience (I know because we actually offer this option, as described in the blog post, and sadly, almost no one takes it).
The Sandstorm installer actually goes to great lengths to be portable and avoid creating a mess. It self-containerizes under /opt/sandstorm and doesn't touch anything else on your system. This actually means that Sandstorm is likely to work on every distro (given a new enough kernel, which the installer checks for). If we instead tried to fit into package managers, we'd need to maintain half a dozen different package formats and actually test that they install and work on a dozen distros -- it would get pretty hard to do that for every weekly release. (Incidentally, Sandstorm auto-updates, and it does check signatures when downloading updates.)
So, yeah, it's pretty complicated, and we're constantly re-evaluating whether our current solution is really the best answer, but for now it seems like what we have is the best trade-off.
What happens if your webhost is hacked and someone installs a malicious install.sh? Without a published signature to verify against, there's no way to detect it.
We do provide a signature. But of course if you're going to check the signature, you need to get our public key from somewhere. You can't just get it from our server, because then you have the same problem: if someone hacked our server then they could replace the key file with their own. We publish instructions to actually verify the key here: https://docs.sandstorm.io/en/latest/install/#option-3-pgp-ve... But as you can see, it's complicated, and most people aren't going to do it. If you're not going to go through the whole process, then checking a signature at all is pointless.
Note that distributing Sandstorm as .debs or .rpms wouldn't solve this, because we'd still be distributing them from our own server, and you'd still need to get our key from somewhere to check the signature.
A few points of the shortcomings of curl|bash vs RPM and others:
* curl|bash is not transactional. If you have an install/upgrade process in a different tab, and you close your terminal accidentally, how do you know if the install/upgrade completed?
* There's no obvious uninstall method, and you need to read the docs to see what, if anything, you should remove outside the main directory.
* There's no way of verifying if files have been tampered with post installation. This has negative security and operational consequences.
* It's much more vulnerable to MiTM attacks - a proxy with a successfully faked certificate can trivially modify a bash script on the wire and add a malicious command to it. This is hard for a user to detect. Packages are (on most distros) installed via package managers that verify GPG signing keys, making in-flight modification very very greatly more difficult.
* Packages are much more auditable - I can download a package and inspect it, and know that it will run the same actions on every machine it's deployed to. curl|bash can trivially serve different instructions to different requests, based on whatever secret criteria the server operator decides.
If you're going to try and argue that instead of doing what the generally accepted $good_thing is, and instead use $quick_and_easy solution that's widely perceived to be insecure, when you argue in defence of your position, you need to make very sure that you're not just trying to justify laziness. I don't think sandstorm have really thought about this hard enough.