3

To work around a problem with IntelliJ, I have been recommended to configure my local Docker daemon to work on port 2375 without TLS authentication. I am concerned however that a malicious website could connect to the Docker service and launch containers.

I've read mailing list entries from 2015 saying that at some point Chrome will not be permitted to connect to localhost by default but I don't know if this has happened yet.

I've never heard of this attack so perhaps it's not possible. Is there something authoritative I could read to set my mind at rest?

  • Are you binding to localhost:2375 or all interfaces? Binding to all interfaces could lead to someone getting root access to your machine. – rjdkolb Jun 14 '17 at 14:26
  • I'm confused: you want to run Docker on an exposed port, but worried that websites can connect to your local service? How would they do that? You mean, if you were browsing with Chrome to some site, the site could direct your browser to connect to your local service? I'd be more worried about the exposed service and random Internet traffic hitting it. How would you mitigate that, in your understanding? – schroeder Jun 14 '17 at 14:40
  • I'm binding to localhost, not 0.0.0.0 - I should have been clearer. My concern is not about my browser getting redirected but to use javascript to access the socket on localhost. It appears that the websocket header would probably be treated by Docker as a protocol error but it'd be worrying to even get that far - I'd rather that my browser just couldn't connect to Docker at all. – Steve Rukuts Jun 14 '17 at 14:59
  • how would a WWW page know to connect a websocket to localhost and send specific socket packets that would compromise your setup? i suppose it's possible with a targeted attack, but the broad risk has to be minuscule. Obscurity? perhaps, but so are deadbolt keys and they work well enough. – dandavis Jun 14 '17 at 15:45
  • 1
    Potential Malware attack on Windows exposing the api through http. threatpost.com/… – rjdkolb Jul 29 '17 at 9:56
4

In a word, YES, websockets DO represent a security problem to your local machine.

First off, some clarification there is a difference between binding to 127.0.0.1 and 0.0.0.0 ... as one will only allow your computer to connect and the other will allow any computers on your network to connect. BOTH of these are dangerous, however, binding to 127.0.0.1 is slightly more secure.

Most (all?) current web browsers have limitations on what is known as cross site scripting. This means if a page hosted by foo.com attempts to make an ajax request to bar.com it will fail unless it is explicitly allowed via CORS. This said ... websockets are NOT limited by CORS and thus foo.com could theoretically open a websocket connection to 127.0.0.1 ... and take control of your docker service.

I will note that this is not a common attack vector as it requires the target to actively be using a web browser on a device running docker with this option enabled (rare) ... but its still an attack surface.

Further Reading:

  • interesting point about SOP+sockets. OP:Can you talk to the localhost socket server using the devtools console from this page? That way, we can know if there's a web-facing threat or not. My thinking is that if your docker's websocket server validates the connection, the risk is pre-mitigated... – dandavis Jun 14 '17 at 16:15
  • 1
    Yeah, I can do it from the devtools console on this page. I wonder if I should contact docker security about this in fact. – Steve Rukuts Jun 14 '17 at 16:16
  • @SteveRukuts: yes, they should validate the origin, otherwise targeted attacks are possible. – dandavis Jun 14 '17 at 16:19
  • I could not get a connection to 127.0.0.1:2375 from my browser (or any of it's URIs) no matter how hard I tried, I would be interested in a practical example using a browser to connect to a docker websocket before alerting docker security. – rjdkolb Jun 15 '17 at 5:09
  • @rjdkolb try websocket.org/echo.html to hit a websocket on your local network ... for whatever reason 127.0.0.1 is not working in the latest versions of chrome or firefox on win10 (still looking for documentation on when this change was made ... because it has worked in the past). I am not sure docker security needs to be alerted being as how I am pretty sure they already know. – CaffeineAddiction Jun 15 '17 at 14:08
1

Update - it seems that there is now a proof of concept attack. It's 100% a security vulnerability. Thanks rjdkolb for spotting that.

Having spent some time with the Chrome console I can see that it's possible to attach to websockets and receive events about containers. I'm not sure what else this API can do as I can't find that much in terms of reference for it, but it's bad enough that you can leak sensitive info about your workstation.

I would strongly recommend that nobody exposes their Docker daemon without TLS authentication. The Docker manual says this is not recommended, and this is a reason why!

  • Would this make every websocket listening for requests vulnerable to malicious Javascript? – rjdkolb Jun 14 '17 at 15:36
  • Yes - it seems that most websocket frameworks have a feature that will check the Origin header to make sure it's coming from an acceptable source but it's on the server and not the client to make sure that this is OK. I'm not really sure why it was implemented like this. – Steve Rukuts Jun 14 '17 at 15:49
  • It seems it is not limited to websockets. A simple get is possible. curl localhost:2375/info – rjdkolb Jun 14 '17 at 16:06
  • 1
    Yes but if you tried to do that in a XHR, your browser would block it due to CORS. – Steve Rukuts Jun 14 '17 at 16:15
-1

Scenario 1: Binding your docker demon to 0.0.0.0:2375 is a really bad idea. An attacker could get root access on your host machine by accessing docker. Dropping to root is a lot harder these days, but rather safe than sorry. Some more info here

Binding to all interfaces allows an attacker to connect to your docker demon from a remote machine. So they can

EXPORT DOCKER_HOST=tcp://YOURIP:2376
docker ps
docker stop

Solution: Adding your user to the docker group is a much better solution to protect yourself.

Scenario 2: Binding to localhost:2375 does not allow your browser to access the port. As reported here: https://threatpost.com/attack-uses-docker-containers-to-hide-persist-plant-malware/126992/ , this may be possible on Windows.

From the link: "The attack is multistage. Step one, involves luring the developer running Docker for Windows to an attacker-controlled webpage that hosts a specially crafted JavaScript. Among other things, the JavaScript is able to bypass a browser’s Same Origin Policy security, a data protection feature found on modern browsers."

In my tests, this is possible:

curl http://localhost:2375/info

This is not:

<!DOCTYPE html>
<html>

<body>
    <button onclick="myFunction()">Click me to get docker info</button>
    <p id="result"></p>

    <script>
function myFunction() {
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open( "GET", 'http://127.0.0.1:2375/info', false ); // false for synchronous request
    xmlHttp.send( null );
    document.getElementById("result").innerHTML = "It did not work";
    document.getElementById("result").innerHTML = xmlHttp.responseText;
}
</script>
</body>
</html>

The browser returns: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:2375/info. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

Accessing the docker daemon from Java

I am guessing you want to run docker as a non root user in a Maven or Gradle plugin like docker-maven-plugin. The best way to do this is add your user to the docker group and then you don't need to bind to the TCP port.

  • the OP didn't say it would be running as root. How/why is there a difference between 0.0.0.0 and localhost? The OP didn't say that it would be bound either way. – schroeder Jun 14 '17 at 14:38
  • I did ask the question but I did not get a reply. I can run my docker client to connect to your docker demon and do a 'docker ps' and docker stop 'your container' etc. I do this for a good reason in our dev environment. – rjdkolb Jun 14 '17 at 14:43
  • I would not be running as 0.0.0.0 but on 127.0.0.1. Regardless a process in my browser might be able to connect to localhost. I've just tried it out in the Chrome console and it seems that I can connect - presumably CORS prevents me from getting further. – Steve Rukuts Jun 14 '17 at 15:03
  • Binding to 127.0.0.1 is pretty safe in my opinion. Someone will need access to your machine to access docker. For production rather use the docker group. – rjdkolb Jun 14 '17 at 15:06
  • @rjdkolb javascript run in the browser is access to the machine, which is steve's whole concern here - it doesn't matter where the binding is – schroeder Jun 14 '17 at 15:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.