 Thank you. Well, this is more people than I expected actually. Thank you for coming to my talk. It's all, it's very great to see you all. I'm very excited to present my research. Your clocks have ears, timing base, browser base, local network, port scanner. Before we begin, let me introduce myself. My name is Donnie Kim. I'm a security, IT security expert at Security Office. We are based in Sweden and South Korea, and we are part of the TRUSA group. If you have any questions or comments, feel free to reach out and feel free to leave a comment on over Twitter and or X or whatever it's gonna be called in the next few hours. In May 2020, it was revealed that eBay and other prominent companies were port scanning their visitors' computers via their websites. The culprit behind the whole saga was called Threatmetrics, a firm which prides itself on tracking 1.4 billion users online and who's too sweet to include it to port scanning. The implications of browser-based port scanning is twofold. One is privacy. It can be used to fingerprint visitors, tracking them with characteristics unique to each user, browser, and hardware setup. The other is security. It can be used to uncover internet services, which are great footholds for performing subsequent attacks like XSS or CSRF. Various techniques have been circulating for some time. The earliest research I found goes back to 2006, which utilized the image and iframe tags. Later research added the script tag and newer exploits employed webRTC and websocket to achieve comparable results. Browser vendors have implemented mitigations making the mentioned techniques more or less ineffective. In this presentation, I'll put my focus on timing-based techniques for browser-based port scanning. Before we get into the specifics, let's take a look at how the Fetch API is employed in measuring the timing of a network request. You can see from the function at line three, we set up a timer. At line five, we measure the time. At line seven, we start the fetch. At line 13, we measure the time again. Finally, the elapsed time in microseconds is returned at line 17. What we can observe using this function is only the elapsed time of a fetch request due to the restrictions imposed by browsers and web specifications. We cannot observe any other metadata, such as any of the response data, including TCP, TLS, HTTP information, any of the request data, except for the scheme IP port, plus any of the error data, except for the generic type error, failed to fetch error string. Now, we can imagine at least four components that are each responsible for a part of a round-trip time of a network request, browser, firewall, TCP, and TLS plus HTTP. Then we can think of three possible states of a port and then hypothesize which components would take up the observed round-trip time. Firstly, if the port is closed and the firewall drops packets or the host is unreachable, the observed time would be theoretically infinite, but typically an arbitrary timeout would be enforced. Secondly, if the port is closed and the firewall rejects packets, the browser and the firewall would take up the observed time. Finally, if the port is open and the process is listening, the browser, the firewall, and the TCP and the TLS plus HTTP would take up the observed time. Looking at the hypotheses, we can expect distinct timing differences depending on the state of a port. Equipped with this knowledge, let's move on to the actual timing-based techniques. We'll try finding open ports on the local host, then we'll try finding the router, and finally, we'll try finding open ports on all of the LAN clients. First, finding open ports on the local host. Now, there are two things to note about local host. One, the firewall always rejects packets when the port is closed, and two, the host is always reachable. Keeping them in mind, we can rule out the first state since it's simply not possible. For the remaining possible states, if the observed time is fast enough, the port is closed and the firewall rejects packets, and the observed time is slow enough, the port is open and the process is listening. So the algorithm looks like this. Firstly, make multiple fetches to the port two, a port that is generally closed, and calculate the average timing as a control. When a thousand measurements are plotted to a graph, it looks like this. Secondly, if a fetch takes a similar time as the control, the port can be considered closed. We do the same measurement to the local host, port 65535. You can see from the graph, the two lines are very similar. Finally, if a fetch takes a significantly more time than the control, the port can be considered open. We do the same measurement to the local host, port 8000, where an HTTP server is running. As you can see from the graph, there is a clear difference. Repeat the algorithm against the various ports of interest, then we get a list of open ports. Next, finding the router on the LAN. In this case, we only care if the host is responsive or not, regardless of the port state. If the host is responsive, we found a live host. So, if an arbitrary timeout is enforced, we can simply say the host is unresponsive. If the observed time is fast enough so that the port is closed, the firewall rejects packets or slow enough so that the port is open and the process is listening, we can conclude that the host is responsive. So the algorithm goes like this. Firstly, if a fetch times out, the host can be considered unresponsive. When we do the measurement against the potential but non-existent router IP, 10.0.0.1. As you can see from the graph, there are all above the timeout which is 50 milliseconds. Secondly, if a fetch ends before the timeout, the host can be considered responsive. When we do the measurement against the live router IP, 192.168.0.1, as the graph shows, there are mostly below the timeout. Repeat the algorithm against the list of potential router IPs and ports, then we have a list of the live routers. Next, finding open ports on the LAN clients. Here, we will make an observation on one more thing. There is this new web standard called private network access. On Chrome, by default, requests to private network resources are allowed only from HTTPS web pages, meaning for HTTP requests to any client on the LAN to any local IP from an HTTP web page would return a CRS error. Below is what it looks like when the error is returned. Access to fetch at HTTP, this address, from origin HTTP, this address has been blocked by CRS policy. The error string itself is still the generic type error failed to fetch. Let's look at how the CRS error gets returned at the specification level. 3.1.1, secure context restriction. 5, the HTTP network fetch algorithm is amended to add three new steps. At 5.2, there is a private network access check, then 5.3 returns it if the result is a network error. But there is something strange. If you read point 5 very carefully, the HTTP network fetch algorithm is amended to add three new steps right after checking that the newly obtained connection is not failure. This means the CRS check happens after the connection is established and the CRS error happens only when the TCP connection is successful, when the port is open. With this knowledge, we can think of new states and hypotheses. When fetching HTTP local IP from an HTTP web page, if the port is open and the process is listening, the browser and the firewall and the TCP would take up the observed time. A CRS error is returned, but we can't observe that as we discussed previously. On the other hand, when fetching HTTPS local IP from an HTTP web page on the same port, the browser, the firewall, the TCP and the TLS plus HTTP would take up the observed time. So this is how we find open ports on the LAN clients. From an HTTP web page, we take a measurement using HTTP, then we take another measurement using HTTPS. If there is a difference between the two observed times, we can say the port is open and the process is listening. The algorithm goes like this. If an HTTPS fetch takes a similar time as an HTTP fetch, the port can be considered closed and the firewall rejects packets. One line is measurements against HTTP 10.0.10.7 port 80 and the other line is against the same port, but with HTTPS. As you can see, the two lines are indistinguishable. However, if an HTTPS fetch is significantly slower than an HTTP fetch, the port can be considered open and the process is listening. The line above is measurements against HTTPS 10.0.10.12 445 and the one below, almost zero, is against the same port, but with HTTP. The graph shows there is about 20 milliseconds of difference. I've created a proof of concept called your LAN.js which utilizes all the three techniques. Let me show you demo. The video has been sped up, but you can see the actual time it took on the screen. First, we tried finding open ports on the local host. It takes about two and a half minutes and it's found AirPlay, Discord, an HTTP server, line, Steam, and Logi options plus. Next, we tried finding the router. It took about 10 seconds and the first choice of the possible light piece was the one. Next, we tried finding open ports on all these LAN clients. We searched the whole subnet against ports of interest. It takes about 40 minutes and you can see there are many IoT devices on the LAN. AirPlay, Google Cast, LG Smart Device, Dyson, SMB, Homebridge, etc. Finally, let's explore some of the found ports. The first one is a router interface. The next one returns HP470 for some reason. Next one is 404. Next one says nothing to see here. The next one is an actual home bridge. And the last one is a Philips Hue light bulb. In conclusion, a website can scan your local network, your local host, your router, and your clients on the LAN. There are some limitations on this research. Due to the nature of a timing-based attack, there can be false positives and false negatives. While we have simplified the states into three or four, in actuality, there exist many other complicated scenarios. Also, the proof of concept needs further optimization to speed up the scanning process. Lastly, I'd like to end the talk with takeaways. It's always best to use Tor browser for privacy and security. Related to this research, Tor browser simply declines any request to local host and local IPs. Also use ad blockers to avoid malicious tracking scripts. Finally, VPNs can be a mitigation as long as they allow access to the user's local network. And that's it. I'd like to thank Oscar, Hansol, Luis, Sun, and the ASAC group for helping out and Betty for editing. Thank you very much for listening.