On the application layer, your browser has no notion of internal and external IP addresses. So any website can simply tell your browser to request a resource from your internal network. This wouldn't get blocked since for the browser it's just an ordinary cross-origin request. Note that the requesting site won't be able to read anything, it could just conclude that something is there.
For example, a website could try to find out if your router has a web interface at 192.168.1.1
by using a snippet like this:
<img src="http://192.168.1.1/favicon.ico" onload="alert('Yay')" onerror="alert('No')">`
Similarly, a website can make you request resources from internal IP addresses (and at almost arbitrary ports) and measure the response times to conclude that there is a service running: E.g., if a request to http://localhost:8080
has a short response time, you might be running a local proxy or similar.
If you cascade such requests, you can somewhat make the browser conduct a basic network scan and infer about existing IPs, hostnames and services.
This idea is also used for actual attacks. Even if your router interface isn't accessible from outside, an external attacker could execute an attack like the recent Netgear router arbitrary code execution exploit by tricking you into visiting a prepared website that makes you conduct the attack yourself by issuing a specially crafted request to the router interface. (Essentially a CSRF attack on the intranet.)
One way to mitigate the risk of intranet access is the ABE (Application Boundaries Enforcer) module of the NoScript extension that can be configured to block particular hosts.
Can an attacker really not read any content?
Often they can read the content of an intranet site by conducting a DNS rebinding attack. Say, your router interface is accessible at 192.168.1.1/info.cgi
. In a DNS rebinding attack, the attacker makes you visit attacker.com
which they first point to their own server's IP, load some Javascript, and then point it to 192.168.1.1
. When the Javascript then requests attacker.com/info.cgi
, it's instead resolved to you router interface and the script is able to read the response content. This doesn't violate the same-origin policy because all requests are on the same origin (the domain attacker.com
), although the DNS entry switches in the background. (As a countermeasure, sites should verify that the Host
header contains either the IP or the intranet name. But lots of routers don't do that.)