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
local network container access vulnerability #14041
Comments
I wouldn't classify this as a vulnerability. For some users, it's a feature. Personally, I assign each Docker host a CIDR and use OSPF to create routes to containers directly. I admit, however, this is not necessarily obvious to users and the concerns with ip_forwarding extend beyond access to containers, and in fact, I believe access to containers is the least worrisome issue with ip_forwarding. I would not be keen to have a solution which always configures these iptables rules by default. For some history, I had already written up some thoughts 2 years ago on this, although the software has changed quite a bit since then: In part, at that time, I felt that we should configure iptables for users, by at the very least communicate the risk. A big problem we had was that (then) Docker was dependent on LXC, which was already enabling ip_forwarding without installing iptables rules. As a result, I think it was expected that anyone using LXC (and thus Docker) would need to be aware of this and configure their iptables as a best-practice. The problem was more or less punted as a result. Ultimately, however, many developers, not sysadmins are using Docker and it's important that we enforce best-practices, rather than simply encourage them. This is especially true now that Docker is no longer dependent on LXC and finally has network plugins on the horizon. Finally, I agree we need to have a network configuration option which is more secure out of the box for how most users use Docker out of the box. This should include a means of securing ip_forwarding, and configuring ip_forwarding according to the practice of least-privilege (i.e. only configure the minimum interfaces necessary). |
The reason why I would classify this as a vulnerability is because I might be running a container on my host which should not be exposed. Maybe it's being used for development of a new product or contains some secret information. If I take my laptop to an untrusted network, these containers can be accessed. This is not obvious as the whole point of exposing ports is to make containers accessible outside the host. I do not think one would expect their container to be publicly accessible without exposing the ports for it. |
@phemmer It's certainly worthy as a bug. In your example you're describing an insecure host configuration, but that doesn't necessarily mean there is a vulnerability in Docker. In many environments this behavior is not insecure and is preferable. I agree we should do more to make sure users don't configure their host insecurely, or use Docker insecurely. An option to configure a filter as you describe may be reasonable. |
Maybe if forwarding was off and docker is enabling it we should make the iptables changes to drop. |
To me, this is a serious vulnerability as this broken default contradicts the documentation, UX and security model as it is explained... Above all, this also breaks any suggestion that an n-tier network can help you secure your docker installation. I'm surprised so many people spotted this (#11508, #3416, ...) as it's a non-intuitive thing to try, but nonetheless important... So, maybe Docker should set FORWARD to DROP by default and only then allow routing on a per exposed service basis? Otherwise I think it just makes it harder / more obscure for everyone to secure their installation. |
Wouldn't something like the following work for most IPv4 context? I'm basically saying, if you're coming through the external default route interface for the an IP other than that interface IP, you're out.
What do you think? Anyone sees an issue with this? |
When will this issue be addressed, @thaJeztah? |
Oh, bit of a delayed response, but something that just didn't click in my brain until now:
This is incorrect. The default configuration of the system is secure. Docker is the one altering the kernel state (changing the sysctl flag) and causing the system to become insecure, not the user.
Yes, this is what I'm proposing here. The system default is |
@phemmer: We installed two VMs, based on CentOs 7 with firewalld disabled; VM1 with docker-engine installed (tried version 1.7.0 and 1.11.2), and added a route from VM2 to VM1 as described in your report. We suspect that additional filtering is done by digital ocean, blocking the traffic both in the public and private network. Any suggestions on how we can reproduce this issue? Background info: With docker 1.7.0 we have the following iptables output on VM1:
Ip forwarding is enabled on VM1:
|
@WillemElbers I've never used Digital Ocean, but most cloud providers' networks operate very different from physical networks in that they don't do real layer 2 switching, but emulate it instead. I was able to do this successfully with the following
I installed docker on node1 and started a container with a service listening (netcat). The container ended up with IP 172.18.0.2. I then ran the following on node2: |
@WillemElbers I think it won't work if your machines have proper routed ipv4 address (as on Digital Ocean), only if it has an rfc 1918 addresses, as the docker networks are also rfc 1918 addresses that won't be routed onto the internet regardless of routes you create. So it will only happen for example with laptops on a private net, or some cloud providers who internally provide rfc 1918 addresses. |
The IP address has no bearing. It's whether the network supports layer 2 switching. In my example, when node 2 sends the packet to 172.18.0.2, it sends it out to the network with the MAC address of node 1. Node 1 then receives the packet, looks at the destination (172.18.0.2) and then routes it to the container. |
@phemmer Thanks for the clarification, we have been able to reproduce the issue on a layer 2 network as you described. As far as we have been able to test, changing the iptables FORWARD policy to DROP ( It seems straightforward to set the FORWARD policy to DROP as the default when running the docker daemon. Maybe include a parameter to make this configurable. |
@phemmer @WillemElbers this issue came up recently in an internal discussion, I don't recall the outcome, but perhaps @mrjana can kick in on this |
Are there any updates to this yet? |
Very short recap of the issue I am facing which is not exactly the descibed issue here. But we also faced the problem that to access to a host is restricted in the INPUT chain preventing outside access, due to the FORWARD rules placed by docker access is granted to everyone to containers with mapped ports. I would suggest that is a secure environment users are responsible for setting the correct rules in the FORWARD chain and docker would never touch only those rules. This way you can restrict access of traffic going to the DOCKER chain and use the portmapping voodoo of docker. In version 1.11.1 Docker still wants to control the FORWARD chain as the DOCKER and DOCKER-ISOLATION chain leaving the user with no abillity at all to restrict access. We have now two options:
For me it would be ideal to see a third option Last option would give the user a posiblity to control access and benifit from dockers ability to control the DOCKER chain. |
Yeah, there are seperate issues. But I guess the solution for both problems might be the same. Makes it a little harder to distinguish between both. |
@phemmer The other one is not about docker overriding rules, it's about docker injecting rules such that custom rules are ignored. |
@GameScripting I don't think they would be the same at all. But even if they might be the same, that doesn't mean they should be merged. What if the resolutions aren't the same. Then we have no issue to track whichever issue wasn't solved. @cpuguy83 That's what I mean. If you put in a custom FORWARD rule to peform an action, and then docker injects it's own rule which causes your rule to be ignored, then it's overridden. This issue has nothing to do with custom rules. This issue is about docker changing |
Yeah, right. Two seperate issues:
Possible solutions might be:
@cpuguy83 What do you think? (Why) do you think both issues are same? |
@GameScripting On the upside the iptables configuration itself works like a charm, it is only just messed up at a restart of docker. |
full diff: moby/libnetwork@92d1fbe...96bcc0d changes included: - moby/libnetwork#2429 Updating IPAM config with results from HNS create network call - addresses moby#38358 - moby/libnetwork#2450 Always configure iptables forward policy - related to moby#14041 and moby/libnetwork#1526 Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
full diff: moby/libnetwork@92d1fbe...96bcc0d changes included: - moby/libnetwork#2429 Updating IPAM config with results from HNS create network call - addresses moby/moby#38358 - moby/libnetwork#2450 Always configure iptables forward policy - related to moby/moby#14041 and moby/libnetwork#1526 Signed-off-by: Sebastiaan van Stijn <github@gone.nl> Upstream-commit: 75477f0b3c77f2108a6b5586dbc246c52b479941 Component: engine
full diff: moby/libnetwork@92d1fbe...96bcc0d changes included: - moby/libnetwork#2429 Updating IPAM config with results from HNS create network call - addresses moby#38358 - moby/libnetwork#2450 Always configure iptables forward policy - related to moby#14041 and moby/libnetwork#1526 Signed-off-by: Sebastiaan van Stijn <github@gone.nl> (cherry picked from commit 75477f0) Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
full diff: moby/libnetwork@92d1fbe...96bcc0d changes included: - moby/libnetwork#2429 Updating IPAM config with results from HNS create network call - addresses moby/moby#38358 - moby/libnetwork#2450 Always configure iptables forward policy - related to moby/moby#14041 and moby/libnetwork#1526 Signed-off-by: Sebastiaan van Stijn <github@gone.nl> (cherry picked from commit 75477f0b3c77f2108a6b5586dbc246c52b479941) Signed-off-by: Sebastiaan van Stijn <github@gone.nl> Upstream-commit: 559be42fc26048f4069de64f84202803a113413a Component: engine
full diff: moby/libnetwork@92d1fbe...96bcc0d changes included: - moby/libnetwork#2429 Updating IPAM config with results from HNS create network call - addresses moby#38358 - moby/libnetwork#2450 Always configure iptables forward policy - related to moby#14041 and moby/libnetwork#1526 Signed-off-by: Sebastiaan van Stijn <github@gone.nl> Signed-off-by: zach <Zachary.Joyner@linux.com>
That vulnerability still can be exploited when binding like 127.0.0.1:HOST_PORT:CONTAINER_PORT is used.
The second rule will accept connections that are actually from external hosts. |
Not quite the same 😅
Thus the attack surface is not as wide, but probably warrants it's own issue
Possible MitigationI am not sure if this introduces regressions, but # Avoid appyling DNAT rules too early when destination is `127.0.0.1` (delay until OUTPUT chain):
# https://askubuntu.com/questions/579231/whats-the-difference-between-prerouting-and-forward-in-iptables/579242#579242
iptables -t nat -D PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER ! -d 127.0.0.1 To prevent connecting to ports at container IPs that were published, I am not familiar with the |
I have already commented on #22054 (comment) but it seems to me that this vulnerability can be prevented by running Docker inside a VM, am I right? Obviously it’s not a proper solution but if your environment allows this (e.g. you’re a developer with root access to your local machine), then perhaps it’s easier and more reliable to run Docker in a VM instead of trying to monkeypatch the iptables rules yourself… |
I produced it with two VM guests running Docker in one: #45610 So not really. Depends on your network configuration. You can use firewalld to avoid it, UFW doesn't seem to have the equivalent protection but I'm not too experienced with configuring that. See my comment prior to yours or the linked issue for more info. |
@polarathene what I meant was isolating the Docker environment inside the vm so that it is not accessible outside the VM host. This is different from running two vms on the same network. |
@polarathene AFAIK your example simply simulates two machines on a single network so the fact that they're vms is not important. What I meant was that using a vm isolates the Docker environment and the VM host's firewall acts as an external firewall against attackers on the same network as the VM host. Edit: if you have two hosts on the same network (e.g. host A and host B), and then set up docker inside a VM that is running inside host A, then my assumption is that you wouldn’t be able to access Docker containers running in a VM inside host A by initiating requests from host B. |
👍
The vulnerability requires the network shared between the Docker host and the Attacker host to support Layer 2 network switching. The link references AWS docs to opt in to such functionality, while in my issue that capability was default on a Vultr VPC network. It's not my area of expertise. AFAIK, the two hosts need to belong to the same network to route as shown with
|
@polarathene thank you for your write-up! My understanding here though is that if host A (the one hosting the VM) does not have IP forwarding enabled, it should not be possible for a same-network attacker to forward packets to the VM running inside host A. I have easily reproduced the vulnerability by running two Multipass VMs with Docker in one of them and connecting them to the same host-only network. I’m curious to try my suggested setup though. This requires running a nested VM inside of the VMs so it might be tricky but it should be doable. I’ll see what I can do. To my understanding, though, the real troublemaker here is IP forwarding and if it's disabled on host A, the packets should not be routed. Because Docker is contained inside a VM, the firewall of host A remains simple and has no custom routing rules set up by Docker. The way I see this is host A acts like a router firewall that protects the nested Docker host VM from outside attackers. |
I have have sent several emails about this issue to security@docker.com without receiving a reply (the earliest being 3 months ago), so I'm opening the issue here.
There is a vulnerability that allows anyone on the same network as a docker host to access containers running on that host, regardless of exposed ports.
When docker starts, it enables
net.ipv4.ip_forward
without changing the iptablesFORWARD
chain default policy toDROP
. This means that another machine on the same network as the docker host can add a route to their routing table, and directly address any containers running on that docker host.For example, if the
docker0
subnet is172.17.0.0/16
(the default subnet), and the docker host's IP address is192.168.0.10
, from another host on the network run:The above will scan for containers running on the host, and report IP addresses & running services found.
To fix this, docker needs to set the
FORWARD
policy toDROP
when it enables thenet.ipv4.ip_forward
sysctl parameter.This issue is verified still present in docker 1.7.0
See also #11508.
The text was updated successfully, but these errors were encountered: