-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Cert and private key are created in the directory which is served by default, so an attacker can just download and use them in a MitM attack #3
Comments
Hi Philipp. Thanks for taking the time to look into this. Your points are valid from a general security standpoint, but there's a couple of reasons I think the severity is considerably less for serve. Serve is intended for quick localhost file-serving, among the same use case where you'd fire up No matter if there's a MitM attack or not, the certificate being self-signed and not root valid, will trigger ERR_CERT_AUTHORITY_INVALID and prompt the visitor to manually accept it in any case. Exchanging a fingerprint out-of-channel, of the original certificate solves this in theory, but how do you propose to do this in practice? Does the user extract the cert from his browser session and manually run a sha256 on the file and then compare, with previously shared fingerprint? Seems like a usability nightmare. Personally, I know I wouldn't bother with that, just to serve a few files for a short while and probably trade ease-of-use with the inherent probability of risk. How do you propose to solve this in a user friendly manner? Also, this all comes down to if you're on a trusted network as well. Worst case scenario; you're co-working at your local coffee shop, and you decide to serve files over https across the network to someone else. If evil-barista-network-admin has compromised the network, at link level, yes we're in trouble and we can't trust the validity of the files served. No matter if he has access to our self signed certificate or not. As you say, he can just be the unencrypted middle man, with his own certificate, and we'll be none the wiser. We could put the key and cert in ~/.serve for instance, but due to the above mentioned inherent invalidity of self-signed certificates, it wouldn't really provide any meaningful security, as the client just wouldn't know, whether they're accepting that certificate or a middle-mans. Perhaps just putting up a big disclaimer whenever using https from -2, warning to expect no security difference from standard http, is the way to go? |
Thanks for the quick and extensive reply! I know the issue is not going to affect the average user at all, but some of your assumptions are incorrect I think and even if only very few people are ever affected, if it's network related security where a MitM might happen, this could be a worst case scenario for them. And if there's an easy way to mitigate this, it should be done. Let me elaborate:
If serve was restricted to localhost file serving there would be no issue. But it's not - you're binding to "0.0.0.0", which means anyone can access the service. Now serve might be intended for localhost file serving, maybe even just for localhost web development, but as soon as people realize they can quickly share this 20 MB PDF with their coworker with starting serve temporarily instead of using email or Slack, which would waste cloud storage space, they're going to do that. And now data is flowing through the LAN.
That's by far not the only possible malicious actor. There only needs to be a single malicious piece of software on any device in the network (some malware on a coworkers laptop, some malware on your home security camera or other IoT device) and then it can do ARP poisoning, leading to the traffic between a victim and the gateway now going through the device with the malicious software.
This is not correct. Let's take the example above and a coworker serves a directory with a PDF, but this time it's not just any PDF, it includes the mission details for a secret agent. If his coworker knows the fingerprint of the certificate (sent via WhasApp or some other end-to-end encrypted communication channel), he can now easily check if the server he accesses via web browser is the real one. If evil-barista-network-admin or the hacked security camera had created a new certificate, the fingerprints wouldn't match and the coworker would know that someone's trying to MitM him. The attack vector here is not that the attacker can see and download the PDF, but that he could manipulate it without the client realizing it. Yes, your average user isn't going to be a secret agent :) . But some might still depend on this.
Luckily it's not that complicated:
As mentioned above, I don't think this needs to be included in serve, or I rather even think it shouldn't be included. The secure channel should be a separate one and it should be chosen by the participating parties. And as also mentioned above: yes that limits this security measure to the few people that take this extra step, but at least they have the possibility to do so.
Yes that's one possibility. Or don't save the certificates in a file at all. You see, I wrote the exact same software one year ago, even with exactly the same name (but didn't know about your repository back then), and just recently implemented generating a self signed certificate for HTTPS. I know most Go examples for generating a certificate include writing the certificate and private key to files, but I accidentally found this PR to a repo that contains a Go package for generating self signed certificates: kabukky/httpscerts#1 So this is how I do it:
Maybe you can use parts of that code :) |
In-memory certs sounds reasonable and I guess it would be necessary to echo the fingerprint on launch with -2, so it can be sent to potential clients. I'll leave the issue open until I get around to making the change. 👍 |
As pointed out in #3, storing the generated certificate and key in the same directory as the one you're serving with a file server, makes it possible, by default, to seize them and do a MITM attack. This change makes it so certificates are stored in memory by default instead of on disk. In some cases it might be nice to not have to accept an exception for a new certificate in the browser, every time the server is started up and for that two new flags have been added. --cert-save, --sc and --cert-dir, --cd. These makes it possible to still store the certificate on disk, but defaults to somewhere outside of the folder being served. (~/.serve) This fixes #3.
I'm pretty sure there's a big issue in the current version of serve, but I'm not a security expert so some details in the following description might not be 100% correct.
When running
serve -2
, serve serves the current working directory, and also saves the generated certificate and private key in the same directory. This means everyone can just download both files and use them in a Man-in-the-Middle attack with the following consequences:Usually, while the first part of a MitM attack (routing traffic from a victim via the attacker's computer to the server, leading to seeing all network packets) is easy, the second part (decrypting the packets and having the victim not notice that he's attacked) is very difficult.
Without the certificate and private key the attacker can only generate another self signed certificate. When routing the traffic from the victim via his computer, he can now decrypt the traffic (because the TLS connection is only encrypted between the victim and himself, and a seperate TLS encryption is encrypted between himself and the server), but if the client knows for example the fingerprint of the original server's certificate, he can now tell that the certificate he's shown is different.
So what should be implemented here is two things:
The text was updated successfully, but these errors were encountered: