I just ran into the host check “feature” where syncthing, when it’s GUI listener is bound to localhost, will try to make sure the incoming connection is actually sending the host string “localhost” or “127.0.0.1”.
This might seem to be a security measure, but the host header string is totally under the control of the remote connection. It is trivial to massage it to make the host string say it’s going one place but have the connection actually go to another.
I would suggest this feature can only possibly serve to impede honest people from honestly forwarding ports. And worse, it gives a warm fuzzy that there is a protection in place that simply isn’t there.
DNS rebinding is a complex issue, and can be a problem. In this case, though, I think syncthing’s current actions make it worse. The current error message serves only to notify the attacker that a rebind was successful and gives the attacker instructions on how to finish the job, and syncthing then waits patiently for the attacker to do just that. The only value added action by syncthing in this situation is to make this a shutdown event with loud log messages. It should write a “SYNCTHING_SHUTDOWN_BECAUSE_OF_REBIND_PROTECTION” file in the config directory and refuse to start up again if its present. A blurb inside it educating the user a little on how to mitigate would not go awry.
I think the feature should just be removed, or defaulted to off because as it stands now in the best case it’s ineffective and in the worst case it makes it worse. If the insistence is to retain it, then please make it a shutdown trigger.
Yup, the host header cannot be changed from within a JavaScript context (fetch API) because it’s one of the forbidden headers. This is precisely why the check protects from browser-based DNS rebind attacks.
The same javascript running on the client’s likely open source browser? The one that anyone with the technical knowhow to execute a rebinding attack would be using to carry out the attack with? Is it that browser’s javascript we’re speaking of here?
It’s running client-side. It can set the host to be anything it wants.
Can you provide some reference for this being the case, because it goes against what I believe to be the common understanding of the client side JavaScript security model.
Do I really need to write a proof of concept? This should be self evident.
The host header was never intended as a security mechanism. It’s a client-side setting to tell the server what aspect of the host it wants and is intended to be 100% independent of the IP address. There is no checking on it because that defeats its purpose.
Current browser javascript standards make the javascript settings for host restricted inside the script engine, but that script engine is itself 100% client side. The client controls setting that header. I could alter that header by:
Altering the javascript engine on the browser
Writing a little http proxy mangle script in LUA for squid or python on mitmproxy or .net with fiddler
I could probably wizard up some clever awk or sed and have it stream edit the raw http output for me using something like socat to handle the sockets.
No client-side header is a security feature to begin with, and currently syncthing is giving away the fact that it’s using it as a security feature and then letting the perp try again after telling them what they are doing wrong.
None of those things are available to a remote site attacker. Your incredulous and abrasive tone notwithstanding I think you’re operating on a misunderstanding of what this check is and what it’s intended to protect against.