Latency Fingerprinting
Background
In order to optimize a web application for speed, it's crucial to be able to accurately measure the performance characteristics of the web application. JavaScript-based mechanisms have existed for a long time. They are, however, unable to provide a complete or detailed end-to-end latency picture. For example, the following JavaScript shows a naive attempt to measure the time it takes to fully load a web page:
HTML
<html>
<head>
<script type="text/javascript">
var start = new Date().getTime();
function onLoad() {
var now = new Date().getTime();
var latency = now - start;
alert("page loading time: " + latency);
}
</script>
</head>
<body onload="onLoad()">
<!- Main page body goes from here. -->
</body>
</html>
The script above correctly calculates the time it takes to load the page after the first bit of JavaScript in the head is executed, however it does not provide any information about the time it takes to get the page from the server, or the initialization lifecycle of the page. Latency measurements, which is a single element of a broader range of performance elements, can be useful as a device fingerprint.
How It Works
Latency can be used to determine how far away a user is from the web server. If you know the client IP, the latency should be within a certain range. This data point is very useful for detecting miscreants on proxy servers, that may be proxing through your client machines and connecting to your system as the client. In cases where a proxy is deployed between the user agent and the web server, the time interval between the connectStart and the connectEnd attributes indicates the delay between the user agent and the proxy instead of the web server. With that, the web server can potentially infer the existence of the proxy. For SOCKS proxy, this time interval includes the proxy authentication time and the time the proxy takes to connect to the web server, which obfuscate the proxy detection. In case of an HTTP proxy, the user agent might not have any knowledge about the proxy server at all so it's not always feasible to mitigate this attack.
The following figure illustrates the timing attributes defined by the PerformanceTiming interface and the PerformanceNavigation interface with or without redirect, respectively. Attributes underlined may not be available in navigation involving documents from different origins. User agents may perform internal processing in between timings, which allow for non-normative intervals between timings.
Entropy Estimate: 4.3 bits
Code
The javascript function below fingerprints the browser languages.
Source Code
function fingerprint_latency() {
"use strict";
var strOnError, perfData, networkLatency;
strOnError = "Error";
perfData = null;
networkLatency = null;
try {
// supported by a number of modern browsers
perfData = window.performance.timing;
networkLatency = perfData.ConnectEnd - perfData.ConnectStart;
return networkLatency;
} catch (err) {
return strOnError;
}
}
Reference
Navigation Timing. (n.d.). In W3C. Retrieved September 04, 2017, from http://www.w3.org/TR/navigation-timing/
PerformanceTiming. (August 15, 2017). In MDM Web Docs. Retrieved September 16, 2017, from https://developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming