Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Neat! But it's not obviously a bad idea. You have a TLS connection with the site you're downloading from. `curl | bash` is no worse than downloading a .dmg or .deb from the same server would be.


> You have a TLS connection with the site you're downloading from. `curl | bash` is no worse than downloading a .dmg or .deb from the same server would be.

This site's argument is that the software publisher can selectively attack users during a live software install, in a way that they don't stand a chance of detecting by inspection (or of having proof of after the fact).


I mean, I guess I see them making a three-stage argument:

1) Distributing software via bash script is a bad idea

2) Sensible people review the bash scripts they downloaded before running them

3) But haha! Here is a clever trick that evades that review.

And I'm not persuaded by 3) being interesting because I already rejected 1) and 2), and I consider 3) to just be proving my point -- you (for all you!) are not competent to perform a very brief but somehow thorough security review of a shell script that probably has further dependencies you aren't even looking at, and the actual reasoning to apply when deciding to install software this or any way is purely "Do I trust the entity I have this TLS connection open with to run code on my machine?".


I agree with im3w1l's point: if everyone runs the same install script, it's a lot riskier for the publisher to attack everywhere. If people run individualized scripts, it's a lot less risky.

I think there's a difference between trusting an organization's code that is published to the general public, and trusting an organization to send you arbitrary code in a specific moment. Only software distribution methods can enforce this kind of distinction, and curl | bash by itself doesn't, particularly in light of the article's technique.

I tried to discuss this distinction in some of my reproducible builds talks. There's a difference between trusting Debian to publish safe OS packages, and trusting Debian to send you a safe package when you run a package manager if the package could easily be different every time. This is particularly so when someone may be able to compromise the software publisher's infrastructure, or when a government may be able to compel the software publisher to attack one user but other users.

Instead of your (1) and (2) above, how about this?

1) Distributing software via a method that can single out particular users and groups to receive distinctive versions is a bad idea: it increases the chance that some users will actually be attacked via the software publication system.

2) We might think that curl | bash isn't particularly egregious this way, because there are various ways that publishers might get caught selectively providing malicious versions. This is especially so because the publishers can't tell whether a curl connection is going to run the installer or simply save it to disk. That makes the publishers (or other people who could cause this attack to happen) less likely to do it.

3) But haha! Here is a clever trick that restores the publishers' ability to distinguish between running and saving the installer, and in turn breaks the most plausible ways that publishers could get caught doing this.

Edit: Elsewhere in this thread you suggested that the likeliest alternative is something like

curl https://somesite.com/apt.key | sudo apt-key add - && sudo apt-get update && sudo apt-get install some-software

I think I'd agree that this has some of the same problems, although it might have some advantages because of the potential decoupling between the distribution of the signing key and the distribution of the signed package. As another commenter pointed out, you could try to use a different channel to get or verify the key, and some users actually do; also, you'll have a saved copy of the key afterward.


I agree that the distributor having control over offering different artifacts to different individuals is very risky.

I was assuming that the sites that you might `curl | bash` from are third-party sites (i.e. not your Linux distribution) that you don't have an existing trust relationship with, which makes it impossible to avoid this capability. That's the situation people use curl | bash in.

So I think this ability to individualize artifacts would still be present if we were receiving a .deb or apt key instead from that site.

> you'll have a saved copy of the key afterward

Yes, though since dpkg post-install scripts can modify arbitrary files (right?), you can't trust that any files on your disk are the ones that existed before the compromise. So couldn't the malicious key verify the malicious package, which then overwrites the copy of the package and key on-disk with the good versions that were given to everyone else?


> So I think this ability to individualize artifacts would still be present if we were receiving a .deb or apt key instead from that site.

I guess we need some other infrastructure or social practice on top in order to compare what different people see, and/or allow the distributor to commit to particular versions. (Then having the distributor not know whether someone is blindly installing a particular file without verification is necessary, but not sufficient, to deter this kind of attack.)


> This is particularly so when someone may be able to compromise the software publisher's infrastructure

Indeed. While this particular venue wouldn't have worked for:

https://wiki.gentoo.org/wiki/Project:Infrastructure/Incident...

(a compromise of github itself would be needed) - it's easy to imagine one of the many mirrors of Debian to suffer from compromise. But as they just push signed debs, the damage would be limited (not trivial, there could conceivably be bugs in apt/dpkg/gnupg etc).


If you are running the same script as everyone else, then then there is a good chance someone else will notice if something is off. If everyone is potentially given their own personalized script then this safety in numbers strategy doesn't work.

If you know you are running the standard scripts that everyone runs, then it also makes a post-breach investigation more easy. You know the exact scripts you ran as opposed to knowing "well I curl | bashed from these sites so one of them might be bad".


There's nothing stopping people from being served different content with packages. Hell, n users could receive n different packages which all pass the GPG check. And since you're getting your checksum from the same site it would look like it had the right checksum too. You would have to find other people you trust to compare it to but since everything appears to be above board why would you even think to do that?

Either you trust the entity you're downloading software from or you don't.


Linux/BSD distribution mirrors don't control the package signing keys, maintainers do. Similarly, Google doesn't possess the ability to push out updates for third-party apps, without fundamentally redesigning the OS with a platform update, because the signing keys are owned by the app developers, and the existing OS rejects updates signed with different keys. In both of these situations, the key owners lack the ability to selectively push out signed updates, unless they also control the distribution infrastructure.


The argument is predicated in the assumption that some subset of people are checking the installer before running it, whether that installer be a shell script or a binary package.

With the binary packages you don’t have any way to tell if the consumer is going to inspect it or not, so even if you send the malicious code to only a subset of people, there is a risk of detection.

The technique in the post allows you to distribute the malicious code only to people who aren’t inspecting it with a much higher success rate.

Personally I’m dubious that anyone is inspecting any installers with enough expertise and scrutiny to protect the rest of us, so the differences between the install methods in this regard are negligible.


>in a way that they don't stand a chance of detecting by inspection (or of having proof of after the fact)

What do you mean? They could `tee` curl output to a file (or elsewhere, for archives). They could also suspend passing the output to bash until they've verified the output (perhaps they would run a hash function and compare the result).


Then that wouldn't be 'curl | bash'.


curl | ... bash


The point of the article is apparently that the server can distinguish "curl | ... | bash" from "curl | bash".


Alice and Bob are both installing something on their computers. It is available as both a .deb and via "curl | bash". It is not malicious...but it does turn out to have a serious bug.

They both install, and both hit the bug and find that it has completely and utterly broken their network configurations bad enough that they have no network access at all.

Alice installed via the .deb. She can look at the scripts in the .deb and see what it was messing with, which gives her a big head start on figuring out how to fix it at least enough to connect to the network backup server and fully restore her network configuration.

Bob installed via "curl | bash". Bob is now left using find to look for recently changed configuration files, and paging through the out of date O'Reilly books he has from the old days when programmers owned physical books, trying to remember enough about network configuration to recognize what is wrong.

Trustworthy sites do not serve you malicious code. They often will, however, serve you buggy code.


Or Bob just curls the file again and reads it?


How does Bob curl the file again without network access? :-)

Remember, I said that the bug in the file broke the network configuration so that Alice and Bob lost all network access.


From another computer? This situation sounds so contrived as-is. Don't tell me they also can't use another system?


The difference is that you can inspect it before you run it if you download it. If you pipe it into bash you don’t know what you’re getting, even if you previously inspected the data provided by that URL.


I don't feel the need to review the source code for every install script I run.

I don't read the source code for almost any of the code on my machine today. In most cases where I see `curl | bash`, I'd probably already be screwed even if I review it. Most install scripts and up doing "hit website, install thing" anyways - am I reviewing the second stage install script also?


That’s fair. It’s probably not an important difference.


That's a way in which "curl | bash" distributed software is better than .deb/.dmg distributed software, right? Because you have the potential to inspect the script first, if you have some kind of ridiculous confidence in your ability to perform security review of an entire software product in the moments before you decide to install it.

But it's never presented in that way, as a feature. It's presented as a terrible way to distribute software.


It doesn't take ridiculous confidence to analyze shell scripts. In the hundreds of scripts I have read, few were more than 100 lines long. It shouldn't take more than 60 seconds (probably 30 or less) to mentally build a list of all possible operations a short script can perform. Bourne shell scripts don't have much room to hide surprising behavior, and when they do, it immediately stands out. If they are permanently installed, and invoked later by other parts of the system, then they may need more probing, but we're talking about installation scripts.

.deb and .dmg can be easily extracted. The former is just an `ar` archive containing tarballs, which you can (and should) extract to read the install scripts. (.dmg specifics escape me, since I only dealt with them one time, years ago.)

Binary code isn't inscrutable. Some good tools for this are, among many, many more, IDA, Hopper, and radare2. How long this takes depends on what your goals are, how comprehensive you are, and the program complexity. I don't think I've yet spent years on one project, fortunately, but the months-long efforts, for undoing some once-prominent copyright protection systems, were pretty brutal. Smaller programs have taken me just several hours to appropriately examine.


If inspecting a script is a good way to avoid evil software, bugs would not exist.


deb/rpm is better because it's usually signed by maintainer with GPG keys. I think that it's harder to steal keys from maintainer than to infiltrate web server.


We came up with a way to do gpg verified curl | bash for ZeroTier. It still works without gpg too. Scroll down to Linux.

https://zerotier.com/download.shtml


Quote(trying to fit it to narrow widt, for others on mobile):

  curl -s \
  'https://pgp.mit.edu/pks/lookup?op=get&search=0x1657198823E52A61'
  | gpg --import \
  && if z=$(curl -s 'https://install.zerotier.com/' | gpg);
  then echo "$z"
  | sudo bash;
  fi
It's interesting - it tries to import a given gpg key from keyserver, then grabs a gpg armored text file with a bash header - with the gpg header wrapped in a here-document:

  #!/bin/bash
  <<ENDOFSIGSTART=
  -----BEGIN PGP SIGNED MESSAGE-----
  Hash: SHA256

  ENDOFSIGSTART=
  
I'm unsure, but I think you could just stick your malicious code before the signature?

  #!/bin/bash
  sudo much_evil
  <<ENDOFSIGSTART=
  -----BEGIN PGP SIGNED MESSAGE-----
  Hash: SHA256

  ENDOFSIGSTART=
So it really isn't any better, as far as I can tell. There's also a trade-off between scripts that can be typed (curl https://i.com.com) and need copy-pasting - as copy-pasting also isn't safe - even if that's a somewhat different attack vector (compromising the web site, altering js depending on visitor).


Putting malicious code before the signature doesn't work because gpg chops it out. It only outputs the verified part.

It is definitely a kludge though.


So the shebang is redundant, except for testing during development? [ed: and for allowing the daring to just do curl|bash, I guess]


It's not strictly necessary, no.


They could be. dpkg and rpm will still install unsigned packages by default. That's one problem.

Another problem is that people are being trained to get software [directly] from software developers.


For the most part you receive the GPG keys over the same TLS connection, though.


Not sure what you mean. I don’t think apt-get install foo involves transferring GPG keys.


We're comparing the security properties of

`curl https://somesite.com/foo.sh | bash`

with

`curl https://somesite.com/foo.deb`

and

`curl https://somesite.com/apt.key | sudo apt-key add - && sudo apt-get update && sudo apt-get install some-software`

I don't think there are very meaningful differences in the security properties -- I don't think it's more difficult to become compromised by one than by one of the others.


No, you're deliberately choosing a bad way to get a key to try to prove your point. You shouldn't be fetching a key from the site that might be compromised.


> You shouldn't be fetching a key from the site that might be compromised.

You shouldn't, but people do, and are being directed to do so increasingly as Linux becomes more popular. Software developers want to be software publishers so bad that they're just going to keep pushing, and therein lies the risk: If people get the impression that packages are somehow more secure than shell scripts, then these kinds of attacks will simply become more prevalent.

To you it's obvious that packages aren't more secure, it's how you get them that makes their normal use more secure. That's apparently too subtle a point for even big companies like Microsoft.

https://pydio.com/en/docs/v8/ed-debianubuntu-systems

https://docs.docker.com/install/linux/docker-ce/ubuntu/#inst...

https://www.spotify.com/uk/download/linux/

https://www.elastic.co/guide/en/apm/server/current/setup-rep...

https://ring.cx/en/download/gnu-linux

http://docs.grafana.org/installation/debian/

https://support.plex.tv/articles/235974187-enable-repository...

https://stack-of-tasks.github.io/pinocchio/download.html

http://download.mantidproject.org/ubuntu.html

https://docs.microsoft.com/en-us/cli/azure/install-azure-cli... (!!!)


I've always said the same, but what's the solution here?


There's three that I can see:

1. Walled Garden: Developers don't self-publish. Call it an app store, call it everything-in-apt.

2. Encapsulate everything so that developers can't do anything. Don't use anything unless it comes in a docker instance. Or a FreeBSD jail. Or something else. Qubes maybe.

3. Smarter users. Good luck with that one.


No, there's no effective difference between those examples, apart from maybe post mortem analysis. It's also a poor method of key discovery, as hueving said.


GPG's trust model is outside the transport layer, via signatures.

Not foolproof, but it answers your objection.


That's an antipattern, should use keyservers.


Where do you get the keyserver ID? From the website? You're back to square one, because anyone can upload anything to a keyserver. If they can modify the website (change files, etc) they can also change the keyserver ID they're telling people to use.

The "antipattern" is letting/expecting software developers also be software publishers.


This is a good point, which should be brought up more. Although you probably meant key id or key fingerprint, not keyserver ID, which would imply something else.

You're supposed to do additional verification of PGP keys, either through attending key signing parties (who does that in 2018?), checking the signatures of people you already trust, or comparing as much out-of-band information as you can.

It's not terribly hard to create a plausibly trusted keyring from scratch that depends on only 1 of 3 websites being legitimate. For example:

    kernel.org: ABAF11C65A2970B130ABE3C479BE3E4300411886 Linus Torvalds <torvalds@kernel.org>
    marc.info:  647F28654894E3BD457199BE38DBBDC86092693E Greg Kroah-Hartman <gregkh@kernel.org>
    thunk.org:  3AB057B7E78D945C8C5591FBD36F769BC11804F0 Theodore Ts'o <tytso@mit.edu>
All keys are cross signed as shown by gpg2 --list-signatures.

If this sounds like a pain in the ass, it's because it is, and GPG could be so much better.

Ironically, if you can't acquire the developer's public signing key, it might be best to install software directly from their website, if no trusted repositories are available. If you can acquire their signing key, it's probably best to not install software directly from their website, in order to avoid selective distribution attacks. Sort of unintuitive.


Public keyservers are well-known, and in a different security domain than the download server. Without breaking in, a rogue party can't delete or replace keys from the keyservers.


Aren't keyserver lookups usually keyed off a 32-bit key ID though? (Whose space isn't big enough to avoid someone brute-force generating a key with a certain key ID s.t. you think you got the right key.) You're supposed to check the fingerprint, but you need to get the fingerprint, and for that you need a secure channel, and you're right back to square one.

For that matter, where did you get the key ID.


Still not safe.

Verify key signatures.

And I really wish GPG had a negative trust signature.


Yeah, if there are signatures then it doesn't matter. But often both are a miss.

Eg the key from https://docs.docker.com/install/linux/docker-ce/ubuntu/#set-... doesn't have signatures, and isn't on the keyservers.

Of course an unsigned key missing from the keyservers still has the advantage that on subsequent installs/updates, the previously downloaded key persists. And you can keep the initially downloaded key in your CI configs.


Verify it against what?


See what keys have signed a given key. See Debian maintainer keys as an example.

This is ... not everything that it could be, and is approaching 30 years old, technology built for a vastly different world.

But this is the basis of the GPG / PGP Web of Trust.

https://en.wikipedia.org/wiki/Web_of_trust

http://www.pgpi.org/doc/pgpintro/

http://www.rubin.ch/pgp/weboftrust.en.html

(I've addressed this point ... a distressing number of times on HN: https://hn.algolia.com/?query=dredmorbius%20web%20of%20trust... 0


Have you contacted maintainers if they're willing to do this? Is there a way to configure apt to verify chain of trust?


Downloading a .dmg is not running any code, which makes it 100% better at preventing malware installation than curl | bash.


dpkg/packages have sanity checks to make sure that files aren't being overwritten, and things are generally in a sane state.

curl|bash involves no checks, and no system integration whatsoever.


dpkg doesn't stop you overwriting system files in a post-install shell script, as far as I know? Which is the way that a malicious package would choose to do it. I don't think dpkg performs any meaningful security review in the way you describe.


Would you like me to craft you a .deb/.rpm which totally trashes your system? Packages can and very often do leverage the ability to run arbitrary scripts but nothing says I can't do serious damage even without that.


%post

rm -rf —no-preserve-root / 2>&1 > /dev/null

Oh, yeah - good luck getting the average layperson or even many sysadmins to inspect this - because very few people actually know how to review scriptlets in an RPM (rpm -qp —scripts package.rpm, isn’t this nice and obvious?). Nobody bothers for packages distributed via yum repositories either, because manually downloading packages to review them defeats the purpose, right?

Yeah, everything is vulnerable at the end of the day - but at least with packages one is less likely to get seriously messed with, just not impervious to it.


Obviously its possible, but if somebody is being malicious all bets are off.

deb is still a more structured format that is less likely to result in accidental collateral damage.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: