Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate dynamic key on vagrant up to better protect VMs #2608

Closed
virtuald opened this issue Dec 9, 2013 · 19 comments · Fixed by #4707
Closed

Generate dynamic key on vagrant up to better protect VMs #2608

virtuald opened this issue Dec 9, 2013 · 19 comments · Fixed by #4707

Comments

@virtuald
Copy link

virtuald commented Dec 9, 2013

All default Vagrant boxes come with the same ssh key and passwords installed. This means anyone who can ssh into your VM, will be able to authenticate to it if they try the vagrant default credentials. Additionally, vagrant boxes come with passwordless sudo privileges, so anyone able to SSH into your box will be able to do whatever they want on it.

When using private networking or no networking, as of Vagrant 1.2.3, for the most part this isn't super important, because you can only access the Vagrant VM from localhost. However, this becomes extremely important if you are using a vagrant box that is on a bridged network. If your VM is on a bridged network, without other controls in place that means anyone who has access to your local network can SSH into your VM and get root access on it. The default configuration on a bridged network is not secure and potentially dangerous.

It would be nice if this was fixed in vagrant core (see below for one solution), but if not, the documentation should explicitly warn users that they are opening the VM up to the outside world via SSH if they are using a public network, and that all boxes generally use the same SSH key for login. I think most people realize that having it on a public network will require security, but I also think most people don't realize that anyone can ssh into their VM because the key is publicly distributed.

One solution

I've created a vagrant plugin (https://github.com/virtuald/vagrant-rekey-ssh -- just run vagrant plugin install vagrant-rekey-ssh to install it) that will address this problem, by replacing the vagrant insecure key on a VM with one that is unique to the host's user. It would be ideal if this functionality was implemented in vagrant core so that it is secure by default, but at the very least there needs to be a warning in the documentation so that users realize what they're getting into.

References

@ryanneufeld
Copy link

This is all documented here: http://docs.vagrantup.com/v2/boxes/base.html

You can already specify your own keys for your own vms, the instructions are there.

@virtuald
Copy link
Author

@ryanneufeld yes, the problems I mentioned are alluded to there (and it appears since the original bug filing that the docs have been updated a bit to mention this problem). However, that doesn't change that when you use public boxes, by default your vagrant machine is open to the world because the default key is insecure. Yes, you could build your own box and such, but that's a pain to do and shouldn't be necessary for a user to use vagrant securely.

Replacing the insecure key when present (such as what my plugin does) mitigates this issue significantly, which is why it should be in vagrant core, and not just a plugin.

@ryanneufeld
Copy link

I'm not the maintainer, so this is purely my opinion, and not his.

I don't see how this is a major security risk. If for some reason you're using Vagrant in a production environment, you should be building your own base box any way. Every project I've worked on with Vagrant has led to be building my own base boxes.

Your box is not automatically open to the world either. The most basic box will only have one interface, the only ports open on that interface are forwarded to the host machine. So unless you're forwarding ports from the internet to your workstation, the box is not available to the entire world but only to your local network.

If your argument is that using a public box is a risk, then you're missing a much larger potential security hole. You're blindly trusting a computer without knowing what software has been installed or how it may have been patched. For all you know it could be keylogging and sending all your data to the NSA. If you're seriously concerned about security, I would advise you to investigate building your own base box. It's really not a lot of work.

@virtuald
Copy link
Author

I agree that there are things one should do to make your vagrant usage more secure, particularly if you're using them for any kind of production use. That is not what this issue is about.

Additionally, you are correct, that by default a box on a private network is not exposed to the outside -- but by looking at the title of this issue, you will note that this is also not what this issue is about. Try using a configuration on a public/bridged network -- by definition, all of its ports are exposed to the outside. Like this one:

Vagrant.configure(2) do |config|
  config.vm.box = "precise64"
  config.vm.network "public_network"
end

A user that uses this configuration without modification will allow anyone on their local network to get root access on their VM. As you point out, there are ways for knowledgable users to mitigate those problems. However, this is arguably a very simple configuration, so we should make sure that it is secure by default if possible.

There is a very easy fix for this -- when the insecure key is detected, replace the key with a randomly generated one. This is straightforward to fix, and thus should be fixed.

@davidjb
Copy link
Contributor

davidjb commented Oct 8, 2014

+1 for at least issuing a warning about an insecure key being present with a public_network VM.

I hadn't realised just how insecure the box formats were (playing only with dev environments) and someone/something on my corporate network hacked a box of mine. Lesson learned now; I've submitted #4601 to document this on the public networking page.

@mitchellh
Copy link
Contributor

Thanks @davidjb. I think this will cover our use case since there is nothing else we can really do here other than warn the user.

@virtuald
Copy link
Author

Given that the plugin exists, doesn't break compatibility, and provides a secure-by-default solution, I'd say that there is something one can do -- eg, include the re-keying functionality in Vagrant by default.

I'm happy to continue maintaining the plugin to do this, but it really belongs in core.

@mitchellh
Copy link
Contributor

@virtuald Agreed, lets get this in. I'm going to reopen and rename this issue for it.

@mitchellh mitchellh reopened this Oct 24, 2014
@mitchellh mitchellh changed the title Running Vagrant VMs on bridged networks is a security problem Generate dynamic key on vagrant up to better protect VMs Oct 24, 2014
@virtuald
Copy link
Author

I'd be happy to assist with integrating the plugin into core, but I'm afraid my ruby-fu is rather poor. There are two problems related to integration that someone with a better knowledge of Vagrant core would be better suited at solving than I:

  • My plugin doesn't cause ssh_config to output the correct config, because I couldn't find the right hook point (related: ssh-config command cannot be hooked by plugins #2797)
  • Someone had problems with the ansible provisioner, because it obtained the key before the plugin was able to switch it out from underneath it. I suspect there are other provisioners that could have similar problems -- but once again, I suspect someone who knows Vagrant's internals better than I could easily solve the problem.

@mitchellh
Copy link
Contributor

@virtuald I think we already support it here: https://github.com/mitchellh/vagrant/blob/cc01f016846ba4b0f7852725a425ba1698397290/plugins/communicators/ssh/communicator.rb#L145

I think we just need to update that method to generate a key, and a way to store a private key in the data directory.

@mitchellh
Copy link
Contributor

Done with #4707 :D

@virtuald
Copy link
Author

Excellent, thanks!

@mboersma
Copy link

@virtuald said:

I suspect there are other provisioners that could have similar problems...

Yes, this breaks our development workflow, see deis/deis#2727. What's done is done and we will have to work around this.

(I would suggest that using the default key as a special signal meaning "generate a new key" is magical, non-intuitive behavior. It's been possible for a long time to use a secure key with vagrant; maybe an in-your-face warning message when seeing the default insecure key would have been enough here.)

@mitchellh
Copy link
Contributor

@mboersma Sorry about that, but you shouldn't have to "work around it" too much, you can just disable the dynamic key insertion.

@virtuald
Copy link
Author

@mboersma I agree that it is a bit magical, but it is secure by default, which is arguably better, and I'm not quite sure how else one might do this and allow generic boxes to be distributed.

It does appear that there's a directive 'config.ssh.insert_key' which allows you to disable the key insertion.

@mbrodala
Copy link
Contributor

What's the suggested workflow for using exactly one existing keypair for all machines?

@LucianU
Copy link

LucianU commented Dec 17, 2014

Btw, I'm using Vagrant 1.7.1 and experiencing the issue with the Ansible provisioner mentioned earlier. That is, on vagrant up Ansible fails because of an SSH error, so I need to run vagrant provision after that.

@felnne
Copy link

felnne commented Dec 17, 2014

Hi i'm also keen to know how to get ansible (as an example) working with this change,

I quite like the idea of randomising the key but would it possible to use the same random key across the various machines within a Vagrantfile?

Otherwise I don't see (other than disabling the feature completely) how anything that works with machines in parallel can work.

@gildegoma
Copy link
Collaborator

What's the suggested workflow for using exactly one existing keypair for all machines?

@mbrodala for now you can config.ssh.insert_key = false to come back to pre-1.7 behaviour.

I quite like the idea of randomising the key but would it possible to use the same random key across the various machines within a Vagrantfile?

@mbrodala @felnne See discussion started in #5005.

That is, on vagrant up Ansible fails because of an SSH error, so I need to run vagrant provision after that.

@LucianU It seems that you're affected by another integration issue of the ansible provisioner, see #4860 (comment) (ansible ssh timeout when using custom inventory and an additional virtual network). But Note also that there is indeed an other open issue when using ansible to inject an additional key after a bootsrap phase that relies on the vagrant insecure key: #4967.


@sethvargo @mitchellh I propose to lock this issue and invite to follow discussions in specific issues (new ones, or #5005, #4967, etc.). Feel free to unlock if you disagree.

@hashicorp hashicorp locked and limited conversation to collaborators Dec 18, 2014
brookingcharlie added a commit to brookingcharlie/ansible-demo that referenced this issue May 24, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants