I don't think this is the same vulnerability. You don't even need to rebind DNS to do it, I believe: just make an XmlHTTPRequest. Your GET is considered code. The browser will get back a request that doesn't have a cors header and so not let you read it, but your code still executes. So there's no reason to be on the same origin, so DNS rebinding is unnecessary
Is this an issue with Guile, or is this an issue with browsers? It seems like allowing sites to query localhost is a vulnerability that could affect a wide variety of development tools. Maybe I'm not thinking of some use case, but it seems to me that we would only ever want requests to localhost to come from local sources, no?
This is a webpage with an origin outside your host, it is only supposed to have implicit access to the same origin in a sandbox imposed by the local browser. Unfortunately the nature of that policy is broken by not going bellow resolved names, most especially for non-http where the service isn't sent the hostname the client used to resolve it.
So, it is most certainly appropriate for a browser to block local networks (including localhost) from being in foreign domains AFA sanboxing. I also don't want a website attacking my (id)iot router via this broken sandbox.
But don't they update DNS so that the origin for the (presumably sub) domain is now pointing at your localhost? Perhaps the solution is to track the DNS state. Any external to localhost changes should be blocked. And any communication between parent/sub domains should never cross the localhost boundary no matter what DNS might say.
Of course this would interfere with development so it would need to be something you could toggle. But I'm 100% sure there's something I haven't thought of that depends on this behavior.
It's not only a DNS rebind attack. I'm pretty sure in this case even a GET could get rce , so you don't even need to check the cors headers. You can just XHR.
Dropbox and Github both use it to talk to their installed desktop clients from the website. It's very useful as it by just installing an app, a website can get more access to the local machine's hardware without having to resort to browser-specific plugins.
In our case, we're using it to read data from a barcode scanner to use it on a web application. All a user needs to do is to install the application an once that's done it works in all browsers.
Potentially, yes. In our case we're doing a bit of additional work to prevent this from happening though. Other sites would get access to the built-in web server, but they wouldn't get anything apart from a 403 error.
> Dropbox and Github both use it to talk to their installed desktop clients from the website. It's very useful as it by just installing an app, a website can get more access to the local machine's hardware without having to resort to browser-specific plugins.
Okay, but from a user's perspective this is exactly what I would NOT want--it's unintuitive to me that going onto GitHub would give them access to my machine's hardware just because I have the app installed.
The program should serve the user, not GitHub or DropBox.
The site is not querying localhost, the browser is.
I find it strange that we consider the error to lie in guile or redis or memcached or elastic search when clearly the browser is the security hole.
Why is it so?
Its only in combination with DNS that a browser can be tricked into sending requests where it didnt intend - but thats a problem of DNS.
So libnss or whatever library the browser uses sees lists.gnu.org and resolves that to 208.118.235.17 so browser initiates connection to that IP, but on subsequent requests, the name lists.gnu.org is changed to 127.0.0.1, how would a web-browser notice this, shouldnt the dns-library warn about this or just use a cache?
Quite simple. I don't think it is a good idea to allow querying sites from the locale network if the visited site is hosted on the public internet.
Let's say I visit google.com and it resolves to google's public Webserver. Your browser should be able to see whether the IP is in the public range (if I'm not mistaken you just checking that the IP is not an A, B, or C class IP, but don't quote me on that). If it is not a local IP (e.g. localhost, LAN, WAN), the browser should disallow all request to local IP addresses (Ajax queries, HTML frames, form requests) initiated by the initial page (google or whatever). It should work the other way around of course and I have never seen a use case where a public webpage relies on being able to query or send a request to my local network if this page is from the internet.
A normal HTTP redirect could be allowed because I think some routers rely on that to give the user a way to configure it (they tell the user to start configuring their router by going to config.manufacture.tld which displays some information and then issues a normal redirect to the default router IP).
Post request directly sent to the local network should be strictly forbidden, though. Why would I ever want to do that?
I'm not sure I follow. How are routing tabels related to knowing if the IP address is within one of the following ranges: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8 and if it is the case, just not let the request get though (Adblock does that already).
My original though as well. But eventually I prefer the DNS resolver to just forward whatever the DNS server says.
Therefore, the issue can be said to lie in the DNS protocol.
But still, whatever the protocol, the browser is the program that does something privacy sensitive by basically being used as a remote code execution tool, and it should not trust whatever information from whatever source, including name resolution regardless of the protocol. Therefore the browser trusting DNS when something obviously shady is going on (such as a resource ip changing to 127.0.0.1) is a bug in the browser, I think.
I would feel safer, for instance, if the same origin policy would apply to the same TCP connection for instance, so that no amount of name or IP spoofing could work. Of course internet giants would not like it, but that would be their problem not mine, and really not so hard to solve.
Both. Browsers shouldn't allow requests to localhost or 127.0.0.0/8 from anything other than localhost, but guile also shouldn't listen on a port on localhost by default.
Even HN has enough access to your machine. Your browser is showing you this page, the page may contain javascript (probably does, feh), and the javascript can retrieve http://localhost:43278/this/that.
Although for the good stuff you want POST. With POST and an error-tolerant SMTP server you can send mail, I imagine other kinds of servers might be equally accommodating.
Their suggested methods (Unix sockets and named pipes) both use Unix filesystem ACLs which means they're resilient to this problem.
This is the main reason I've never liked binding to 127.0.0.1 rather than just using a socket -- you lose the access control you could have if you used sockets.
I know it works on GNU/Linux, and I'm fairly sure it works on illumos (Solaris). I don't really use any of the BSDs, so I can't comment on that. Sounds like a nasty kernel bug though -- Linux implements AF_UNIX sockets as actual filesystem objects (so you go through VFS implicitly to interact with them).
It wasn't a bug, though - just a questionable design (POSIX still doesn't mandate how filesystem permissions interact with connect() on AF_UNIX sockets AFAICS).
There is https://github.com/monsanto/nreplds but it requires some native code, and obviously isn't a solution for those on Windows. I'm not sure how vulnerable nRepl is to http attacks as I don't think either of its default transports would accept or filter out http commands.
I'm not so sure, certainly one of the two socket protocols is vulnerable (the "tty" one) judging by what the regular repl does with '' GET /%20(println"hello") HTTP/1.0 '' and it's somewhat likely that you could get through the bencode transport too.
This is actually a vulnerability in any language that provides a networked REPL.
I'm glad that Guile kept the option to run a REPL via a port, because that's really useful for debugging nonlocal servers (investigating production issues, etc.).
48 comments
[ 3.6 ms ] story [ 128 ms ] threadhttp://bouk.co/blog/hacking-developers/
I think we're only scratching the surface on the number of vulnerabilities exposed.
So, it is most certainly appropriate for a browser to block local networks (including localhost) from being in foreign domains AFA sanboxing. I also don't want a website attacking my (id)iot router via this broken sandbox.
Of course this would interfere with development so it would need to be something you could toggle. But I'm 100% sure there's something I haven't thought of that depends on this behavior.
In our case, we're using it to read data from a barcode scanner to use it on a web application. All a user needs to do is to install the application an once that's done it works in all browsers.
Okay, but from a user's perspective this is exactly what I would NOT want--it's unintuitive to me that going onto GitHub would give them access to my machine's hardware just because I have the app installed.
The program should serve the user, not GitHub or DropBox.
Its only in combination with DNS that a browser can be tricked into sending requests where it didnt intend - but thats a problem of DNS.
So libnss or whatever library the browser uses sees lists.gnu.org and resolves that to 208.118.235.17 so browser initiates connection to that IP, but on subsequent requests, the name lists.gnu.org is changed to 127.0.0.1, how would a web-browser notice this, shouldnt the dns-library warn about this or just use a cache?
In any case, you can prevent it like this
iptables -A OUTPUT -d 127.0.0.0/8 -p tcp -m owner --uid-owner $YOUR_USER_ID_OF_BROWSER -m tcp -j REJECT --reject-with-tcp-reset
that is, if you run the browser under its own uid.
Let's say I visit google.com and it resolves to google's public Webserver. Your browser should be able to see whether the IP is in the public range (if I'm not mistaken you just checking that the IP is not an A, B, or C class IP, but don't quote me on that). If it is not a local IP (e.g. localhost, LAN, WAN), the browser should disallow all request to local IP addresses (Ajax queries, HTML frames, form requests) initiated by the initial page (google or whatever). It should work the other way around of course and I have never seen a use case where a public webpage relies on being able to query or send a request to my local network if this page is from the internet.
A normal HTTP redirect could be allowed because I think some routers rely on that to give the user a way to configure it (they tell the user to start configuring their router by going to config.manufacture.tld which displays some information and then issues a normal redirect to the default router IP).
Post request directly sent to the local network should be strictly forbidden, though. Why would I ever want to do that?
But still, whatever the protocol, the browser is the program that does something privacy sensitive by basically being used as a remote code execution tool, and it should not trust whatever information from whatever source, including name resolution regardless of the protocol. Therefore the browser trusting DNS when something obviously shady is going on (such as a resource ip changing to 127.0.0.1) is a bug in the browser, I think. I would feel safer, for instance, if the same origin policy would apply to the same TCP connection for instance, so that no amount of name or IP spoofing could work. Of course internet giants would not like it, but that would be their problem not mine, and really not so hard to solve.
127.0.0.1 accesses local servers that might be running code which is typically in development and insecure. There's nothing confusing about this.
Why is there even a presumption that all local users are equally trusted?
Although for the good stuff you want POST. With POST and an error-tolerant SMTP server you can send mail, I imagine other kinds of servers might be equally accommodating.
This is the main reason I've never liked binding to 127.0.0.1 rather than just using a socket -- you lose the access control you could have if you used sockets.
It wasn't a bug, though - just a questionable design (POSIX still doesn't mandate how filesystem permissions interact with connect() on AF_UNIX sockets AFAICS).
I'm glad that Guile kept the option to run a REPL via a port, because that's really useful for debugging nonlocal servers (investigating production issues, etc.).
https://debian-administration.org/users/dkg/weblog/68