Maybe I’m just being paranoid here, but I’m starting to get a little worried that RubyGems could be a nasty attack vector, given certain combinations of malice and stupidity.
Six months ago, the
picked up some collaborators with way more Ruby-savvy than I have, and in
short order they moved it to RubyForge and
made it into a Gem.
Which means that anyone who uses RubyGems, i.e. every Ruby developer
in the world, can type
sudo gem install ape
then when they type
ape_server, there’s a mongrel and a handy
local Ape running on port 4000. What’s not to like?
Well, I eventually came to wonder, where is
/usr/bin, it turns out. Which is in root’s path on OS X,
GNU/Linux, and Solaris. OK then, so if gem routinely dumps programs in
/usr/bin, who’s entitled to create Gems? Anyone with a RubyForge
account, it seems. So, how do you get one of those? Well, by going to
rubyforge.org and clicking on “New
Am I being paranoid, or is this maybe a problem?
Scenario: J. Evil Hacker creates a
naked_celebrity_video gem and
announces it to the world. Installing it, as a side-effect, creates
/usr/bin/ls. Or, J.E.H. submits some good patches to a
well-known gem and eventually gets blessed as a committer:
/usr/bin/ls. Or, J.E.H. manages to get access to a logged-on
computer belonging to a well-known gem maintainer; someone who knows what
they’re doing, given about fifteen minutes:
OK... once you’ve typed
on your computer, you’ve offered up the keys to your kingdom and arguably lost the right to complain. But you know, I have this feeling that it might be a good idea, as Ruby becomes more and more mainstream, if there were a few warning fenceposts put up around the
gem command. And if anyone’s thinking of a synaptic-like
RubyGems GUI, let’s please make sure people know what they’re doing.
And if (unlikely) there are any gem maintainers who hadn’t thought about
this... be careful.
Comment feed for ongoing:
From: Hongli Lai (Aug 31 2008, at 14:44)
This is no different from pretty much any other software installation method. They can all become attack vectors. You can't stop someone from publishing a .deb, .tar.gz, .rpm or whatever which installs itself to /usr/bin, so what difference will RubyGems make?
Telling the user that an action may be dangerous and asking him whether he's sure has proven to be useless. Most people these days click "Yes" because they don't understand the question, and think that by clicking "Yes" they will get what they want. They want to see $CELEBRITY naked, and once they've decided, warning them that the content may be malicious won't change their minds.
Now, programmers are more tech savvy, but asking whether he's sure won't do him any good. Suppose that I found a "fix_all_bugs_for_me" gem and I want to try it. I don't know whether it's malicious, so the computer asking me won't do me any good. The question is useless.
At first, warning the user if the gem contains binaries that have the same name as ones in /bin or /sbin *might* appear useful. However, I think that such a security measure would only give a false sense of security:
- RubyGems is able to run arbitrary code code upon installation (extconf.rb).
- We're talking about Ruby libraries here. An attacker can put arbitrary code in the library, which will get executed as soon as it's used.
Furthermore, not installing to /usr/bin leads to a lot of confusion. Debian modified RubyGems binaries to install to /var/gems/1.8, which isn't in PATH by default. One of the most often asked questions on Ruby on Rails support places is "I typed 'gem install rails' and 'rails foobar', but I get 'rails: command not found' -- hellp!!!!"
From: Matt Moriarity (Aug 31 2008, at 14:46)
This is true of ANY package manager. Of course you should know what you're installing before you run the command! The sudo is there for a reason: the average idiot shouldn't be able to do it.
Research something before you install it. That has always been true, even before rubygems.
From: Chris (Aug 31 2008, at 15:43)
While not a true solution, I've always preferred to keep RubyGems in user land - no need to sudo.
A post explaining how to do this is here: http://ozmm.org/posts/local_gems.html
From: Rudd-O (Aug 31 2008, at 16:42)
<blockquote>This is no different from pretty much any other software installation method.</blockquote>
This is patently false. Take RPM for example. You cannot replace binaries on the system using RPM, because RPM will warn ahead of you. Granted, /usr/bin/ls is not a replace-file type of attack, but the gem installer certainly CAN execute that type of attack.
RPM can also let you verify the integrity of the files, and finally, as an additional precaution, you can list installed files, which should let you at least BE AWARE that the rogue /usr/bin/ls is present.
From: Pete (Aug 31 2008, at 17:02)
Just alter your gem path to something nondestructive if that's what you're worried about. Simple.
By the way, other Mac users out there who use MacPorts have this already, so you're fine.
From: Tony Fisk (Aug 31 2008, at 17:21)
<i>Most people these days click "Yes" because they don't understand the question</i>
I would say that most people click "Yes" because that is the default, they're in a hurry, and they never even read the question in the place (I call it the pavlovian mouse response, although I daresay some of the resident gurus have a fancier term)
Getting folk to respond to an important and irreversible question by actually typing "Yes" is more productive. So is making the default option "Cancel Action".
(But, "Yes" is the default, programmers are in a hurry, and they never stop to consider what people will do...)
From: thomas (Aug 31 2008, at 18:01)
How about this solution:
- Do not use gems.
From: manveru (Aug 31 2008, at 18:47)
Keeping gems at home is just about the advice i found in this regard, I'm using that way since around a year and haven't had problems with it so far, it also makes modifying your gems easier, in case you want to debug or patch, no more editing as root.
But the hole in extconf.rb should still be closed (using fakeroot?)
From: dak (Aug 31 2008, at 18:56)
The other comments miss the point. All package managers require you to trust the package repository, but most actually earn (some of) that trust by vetting the packages they distribute.
From: Ryan Lowe (Aug 31 2008, at 19:25)
There are also gem dependencies to consider as an attack vector for something similar to a trojan horse.
Let's say you carefully research a useful and benign gem A and determine that it's source is OK. You install it via "sudo gem..." and continue to update it via "sudo gem update".
Somewhere down the line gem A requires malicious gem B as a dependency and installs it during a gem update. If you aren't watching the "sudo gem update" output, you could easily overlook this.
Even if "sudo gem update" asks for confirmation input "Y", people could still quickly confirm without checking carefully -- or they could use the "-y" option, which skips the confirmation entirely.
So in terms of that specific attack vector, how secure are the gemspec files that determine which gems A depends on? Are they susceptible to man-in-the-middle attacks? What is the attack risk of a malicious gem piggybacking on a benign gem using gem dependencies?
Thank you for bringing this issue up, Tim. Ruby's community has been friendly -- and perhaps a little too reliant on other people behaving well. As Ruby becomes popular it will become more of a target and now's a good time to start thinking about this.
From: Not A. Spammer (Aug 31 2008, at 20:08)
"You can't stop someone from publishing a .deb, .tar.gz, .rpm or whatever which installs itself to /usr/bin, so what difference will RubyGems make?"
It's a lot harder to become a Debian maintainer than it is to get a Rubyforge account. If Debian has a security problem with a package, the security team will be all over it fast. Finally, Debian has releases, so if you run Debian stable, you're using packages which have been around long enough not to make 'ls' mail somebody your password file.
Rubyforge (and hence, Gems) have none of these features.
Debian still has the same attack vector, but you basically have to willingly tell it "let me do scary stuff" (e.g., add a line to /etc/apt/sources.list, switch to "unstable", etc.). That's not to say it's safe, but it's a lot harder to hurt yourself with Debian packages than with Ruby Gems.
From: Erik Hetzner (Aug 31 2008, at 23:01)
I have to agree with Tim here.
gems are not like, say, debian packages. They are required to be signed. Debian packages & maintainers are vetted.
This is more like CPAN. But CPAN (as I recall) installs into /usr/local/bin.
I think that Hongli Lai is right that moving things to /usr/local/bin would be something of a false sense of a security. The real problem is that we encourage users to type: sudo gem install rails, and this looks as safe as sudo apt-get install rails. But it is not, because rubyforge does not vet its packages. It does no good to suggest to the user that they are responsible for checking the source of every gem out there to insure that it does exactly what it says, and only that. Or are you really going to pretend that all of you do that?
From: Andreas Schipplock (Sep 01 2008, at 06:24)
@Matt Moriarity: "sudo" IS for the average idiot :).
From: vz (Sep 01 2008, at 06:29)
You're very right. Gems are being used like toys often. They could be easily used for a lot of nasty things.
From: Chad Woolley (Sep 01 2008, at 13:45)
There is active work going on in RubyGems trunk to install RubyGems into ~/.gem/ruby/1.8 by default, and then issue a warning if you don't have ~/.gem/ruby/1.8/bin on your path.
This should eliminate the need for typing sudo, or for having the gem binaries installed in /usr/bin or other common locations.
And, as other people have said, this is a problem with any package manager - the only difference is the ease and accessibility of publishing rubygems. Also, it is hard to think of a scenario where someone would release a gem that is both useful AND malicious - the only scenario where this could affect a significant number of people would be an established, popular gem which suddenly allows a malicious person to have admin/publish access. If this DID happen, I think that it would be an isolated scenario which would quickly be remedied (for example, by RubyGems admins forcing a republish of the prior non-malicious version with a higher version number).
Regardless, if you make it a habit to use root access to install unknown gems, or newer versions of gems, especially on production systems, without adequately investigating and testing on dev/staging boxes - well, you get whatcha deserve :)
I try to make it a practice to use GemInstaller (shameless plug) to lock down all my gem versions using an "=" spec, not a ">=". This means I have to explicitly increment to new versions, and these versions go through a full "QA" cycle of being installed on my (and everyone elses) dev boxes, and on demo/staging, before they ever make it to prod. If I happened to get a malicious gem by this method, I think I would hear about it or notice something awry. Or, at least, I'm willing to take the risk, because the benefits of the open an accessible RubyGems ecosystem far outweigh any risks in my opinion.
From: Dalibor Topic (Sep 02 2008, at 05:37)
From a security POV, language-specific 'packaging' solutions increase the attack surface quite a bit, since one now has to verify that the security policies of the language-specific solution are adequate.
For example, if I can go to RailConfEU and set up a wireless beacon that pretends to be the ruby gems archive - do I get to overwrite items in your / if I let you download trojaned binaries as if they were the real gems? If I do, then the system is really badly flawed in an age of easy DNS exploits.
From: Ryan Lowe (Sep 02 2008, at 05:43)
Chad Woolley: "... if you make it a habit to use root access ...well, you get whatcha deserve :)"
When the Ruby or Rails communities tout easy of installation and development, this is the part they don't mention.
There are a lot of unwritten security rules of Ruby, package management and IT deployment in general. When you get burned because you don't know security, you are the idiot and you got what was coming to you by being ignorant. I disagree with that entire premise when it comes to Ruby.
The *majority* of regular programmers don't have a sufficient appreciation for security. People that use Ruby and/or Rails for anything but a large or super-secure deployment shouldn't have to know a lot about security. They should be able to be willfully ignorant or inexperienced when they are installing it on their development machines because it's higher level software. This is not C/C++.
This is exacerbated by the de-facto weblog and wiki-based documentation Ruby and/or Rails references (outside of the official API), where people use "sudo..." all of the time in the name of ease of installation, not just with gem.
Do we need to put a disclaimer on these blog posts saying "don't use sudo in situation A,B or C"? Or does the RubyGems package manager need to be changed so this becomes moot?
If it isn't possible to change gem, how can we educate people that use Ruby and Rails about security issues? We are a community and their problems are our problems. If someone's Ruby software gets hacked, it makes the whole community look bad - no matter who's to blame for it.
Perhaps we can protect people better from ignorance of security education instead of leaving them with a pat on the back and a "good luck mate - don't fuck up or you will be p0wn3d". Open source software is beyond that now.
From: Paul W. Homer (Sep 02 2008, at 09:16)
With all of these auto-magic updaters we're creating one huge dangerously malleable computer that spans the planet. Were way past the point of just asking for trouble, now were happily piling the cards as high as we can, just to see how they crumble. Will the biggest disaster in the 21st century be entirely computer related?
From: Aristotle Pagaltzis (Sep 02 2008, at 11:30)
> Getting folk to respond to an important and irreversible question by actually typing “Yes” is more productive. So is making the default option “Cancel Action”.
No, that doesn’t help. It makes the procedure more irritating, and may prevent a few mistakes (whose number will be indistinguishable from zero), but won’t actually save anyone from themselves. The problem is that users are being asked questions that they are in position to understand, let alone answer. Every time you add an “are you sure” dialog to an app you are failing your future users.