<table><caption>**Table 3.3.** – Duration of a tick, using `performance.rdtsc()`.</caption><thead><tr><th>Browser</th><th>Average tick<br>duration<br>[cycles]</th><th>Standard<br>Deviation<br>[cycles]</th></tr></thead><tbody><tr><td>Firefox 81</td><td>200</td><td>10</td></tr><tr><td>Unjittered Firefox 81</td><td>100</td><td>9</td></tr><tr><td>Chrome 84</td><td>150</td><td>9</td></tr></tbody></table>

to 80 (2020) and Chrome 48 (2016) to 84 (2020)<fnref n="5" />. We used Selenium WebDriver [sel20] and Python to automate tests. New versions of said browsers can easily be included in the test routine to see the evolution of timers without a deep dive in documentation and source code. Our scripts access test pages hosted on a local server, each page containing our JavaScript benchmark code. Our scripts also handle browser evolution, e.g., the different flags required by the use of `SharedArrayBuffer`, or the eventual activation of COOP/COEP.

### 3.4.2. Longitudinal study of `performance.now()` interpolation

#### 3.4.2.1. Simple interpolation

**Resolution** We seek to measure the resolution of the `performance.now()` method when interpolated. Two factors influence this resolution: (1) the duration of a tick, and (2) the jitter.

The shorter the duration of a tick, the higher the resolution. Table 3.3 illustrates the duration of a tick on different browsers and versions. It is important to note that while the increment part of the tick has a relatively steady computation time through browser versions, the computation time of the call to `performance.now()` varies a lot depending on the version. For instance, on Firefox 81, a call lasts around 200 `performance.rdtsc()` cycles, while it only takes 100 cycles on an unjittered version. At this scale, the jitter is indeed a time-consuming operation as the browser uses a hash function to compute a random midpoint.

To understand the impact of resolution and jitter on measurements, we measure the number of ticks between two clock edges. This is equivalent to measuring no event with a `performance.now()` interpolation-based clock. Without any jitter, the number of ticks is always the same. Since the standard deviation is low, an accurate timing can be retrieved [SMGM17]. With jitter, the story is obviously different. If the resolution of `performance.now()` is low, the time between two clock edges increases, so the number of ticks increases. If the jitter is high, the number of ticks will be spread on a wide range of values between measurements, and therefore the standard deviation increases. Table 3.4 illustrates this evolution by showing statistics about the average number of ticks between two clock edges. As a reminder, a tick is composed of an increment as well as a call to `performance.now()`. The results were computed using 100 000 samples. We see that jittered versions often have a high variance to average ratio, e.g., on Firefox 81 without COOP/COEP, the standard deviation is half of the average.

<footnote n="5">⁵Some releases of Chrome (versions 65 to 6) were unavailable on our system. We replaced them with the equivalent Chromium version. To our knowledge, the timer implementations are the same on both browsers.</footnote>

<footnote n="6">⁶Without COOP/COEP for Firefox 81 and later.</footnote>

<footnote n="7">⁷Versions 58 and 59 experienced many timer changes and do not appear here.</footnote>
<table><caption>**Table 3.4.** – Comparison of the average number of ticks per browser. The duration of a tick can vary according to the browser or the presence of jitter.</caption><thead><tr><th>Browser</th><th>Average number of ticks</th><th>Standard Deviation</th><th>Announced resolution</th><th>Jitter</th></tr></thead><tbody><tr><td>Firefox 81-latest + COOP/COEP</td><td>300</td><td>40</td><td>20 µs</td><td>○</td></tr><tr><td>Firefox 60-latest<sup>6</sup></td><td>3310</td><td>1510</td><td>1 ms</td><td>●</td></tr><tr><td>Firefox 41-57<sup>7</sup></td><td>70</td><td>10</td><td>5 µs</td><td>○</td></tr><tr><td>Chrome 72 and later</td><td>12</td><td>7</td><td>5 µs</td><td>●</td></tr><tr><td>Chrome 64-71</td><td>400</td><td>200</td><td>100 µs</td><td>●</td></tr><tr><td>Chrome 64 and former</td><td>10</td><td>2.5</td><td>20 µs</td><td>○</td></tr></tbody></table>

Figure 3.2a and Figure 3.2b illustrate the variation of the number of ticks in a single clock period for Firefox 81 and Chrome 84 respectively. The data follows a triangle distribution, with the top value at around 3300 and 12 ticks respectively. A precise timestamp can be clamped to a certain value if the timestamp is smaller than the clamped value but higher than the random midpoint, or if the timestamp is higher than the clamped value but lower than the random midpoint. As both midpoints are computed following a uniform distribution, the result of the sum of these two distributions is a triangle distribution. On the contrary, as can be seen on Figure 3.2c, the behavior of an unjittered Firefox is very different. The distribution of ticks in a clock period is grouped between 280 and 320 and does not follow a triangle distribution. The difference in the number of ticks stems from the different base resolutions and jitters. Knowing the distribution of the number of ticks in a single clock period means that an attacker can gather more information from a single measurement.

The resolution for the different versions varies drastically between browsers. Figure 3.3 illustrates the timings for cache misses and cache hits by using `performance.now()` interpolation on Firefox 81 with COOP/COEP and Chrome 84. Distributions must be differentiated in order to implement cache attacks. Note that, contrary to what we expect, hit timings are higher to miss timings on this graph. This is because `performance.now()` interpolation measures the time between the end of the event and the end of the clock edge. This means that a long event will yield a short interpolated time, whereas a quick event will yield a long interpolated time. The lack of jitter on Firefox has an impact on the histogram, where the difference between cache hits and cache misses is clearer.

On Firefox 81 without COOP/COEP, an attacker has a 30% error rate on distinguishing cache hits from cache misses when targeting a sub-100 ns resolution. On Chrome 84, regardless of COOP/COEP, the error rate stands at 20%. This makes for a highly unreliable clock, and drastically hinders the development of attacks. On Firefox 81 with COOP/COEP, the lack of jitter drops this error rate to only 11%.

The lower the error rate, the more threatening timing attacks with this timer are. This means that, with interpolation alone, timers based on `performance.now()` on Firefox 81 with COOP/COEP offer the best timer in terms of resolution, as they allow to implement cache-based timing attacks with a relatively low error rate. Error rates of Chrome 84 and Firefox 81 without COOP/COEP are too error-prone to implement attacks that require high precision.
<figure><img src="image_26.png" /><figcaption>(a) Firefox 81 without COOP/COEP (jitter).</figcaption></figure>

<figure><img src="image_27.png" /><figcaption>(b) Chrome 84 (jitter).</figcaption></figure>

<figure><img src="image_28.png" /><figcaption>(c) Firefox 81 with COOP/COEP (no jitter).</figcaption></figure>

**Figure 3.2.** – Distribution of the number of ticks in a single clock edge.

**Measurement overhead** We now evaluate the measurement overhead on Firefox 81 and Chrome 84. We use our custom `performance.rdtsc()` to retrieve the timestamp before and after the measurement of an empty event with `performance.now()` interpolated. We found that, on Firefox 81 without COOP/COEP, the measurement overhead averages around 1.8 million cycles. On our 1.60 GHz CPU, this represents around 1.1 ms. This is coherent with the announced resolution, 1 ms, as the measurement always takes at least this time between two clock edges. On Chrome 84, a measurement using interpolation takes 9,000 cycles, corresponding to 5.5 µs with our average frequency. On Firefox 81 with COOP/COEP, a measurement using interpolation takes 35,000 cycles, averaging to 21 µs on our system. The slight difference may come from the potential change in CPU frequency under a lot of calculations and noise.

With interpolation alone, Chrome 84 has the shorter measurement overhead, which allows implementing attacks that run faster. Namely, a cache covert channel built with this timer could ideally retrieve a resolution of 180 kbit/s, against 50 kbit/s for Firefox with COOP/COEP and 900 bit/s for Firefox without COOP/COEP. However, the ideal bit rate does not
<figure><img src="image_29.png" /><figcaption>**Figure 3.3.** – Histogram for cache hits and cache misses.</figcaption></figure>

take into account the different error rates between browsers.

**Conclusion** Although Chrome 84 offers the best base resolution with `performance.now()` interpolation, the jitter causes a high error rate for high-resolution attacks. This error rate would slow, if not prevent, the implementation of attacks using interpolation alone. Due to the lack of jitter, Firefox 81, with COOP/COEP enabled, offers the lowest error rate with interpolation. It could be used to build error-tolerant cache attacks, such as a covert channel. Firefox 81 without COOP/COEP has a high error rate (30%) and a high measurement time, rendering it inefficient for timing attacks.

With interpolation alone, Firefox 81 with COOP/COEP is the only browser where an attacker can build clocks based on `performance.now()` that can efficiently run timing attacks.

### 3.4.2.2. Interpolation and amplification

The jitter being longer than most of the events we wish to time, it is not possible to simply use clock interpolation to retrieve a high resolution. To get a more accurate timer, an attacker therefore needs to reduce the impact of the pseudo-random jitter. On both Chrome and Firefox, the jitter is deterministically defined by computing a random midpoint between the highest and lowest clamped values. However, the time of a jittered clock edge follows a triangle distribution around the precise timing value. This means that each measurement has a slight tendency towards the real value. By repeating the measurement several times, an attacker can, therefore, achieve a higher precision.
<figure><img src="image_30.png" /><figcaption>**Figure 3.4.** – Hit / miss error rate in function of repetitions, using `performance.now()` interpolation on Firefox 81 without COOP/COEP and Chrome 84.</figcaption></figure>

**Resolution** To evaluate the impact of amplification on the resolution, we repeated the measurements and computed each time the average error rate on cache hit/miss discrimination. Figure 3.4 illustrates the results for Firefox 81 without COOP/COEP and Chrome 84. The error rate follows a logarithmic decrease with repetitions for both browsers. An attacker can reach a 5% error rate by repeating the measurements 15 times on Firefox 81 without COOP/COEP and 8 times for Chrome 84. On Firefox 81 with COOP, a mere 2 repetitions grant a 4% error rate. Comparatively, on an older version of Chrome, namely version 71, an attacker needed 12 repetitions in order to reach the 5% error rate.

**Measurement overhead** A single measurement without amplification takes at least the duration of a clock edge. That is, on average, 1 ms for Firefox 81 and 5 µs for Chrome 84. In the best scenario, repeating the measurement *n* times will increase the measurement time by *n*.

Specifically, repeating the measurement 15 times on Firefox 81 without COOP/COEP takes 29 million cycles on average. This represents a measurement overhead of 18 ms on our 1.60 GHz CPU. This means that building a covert channel using this timer as a receiver yields, at best, an ideal bit rate of 60 bit/s.

On Chrome 84, repeating the measurement 8 times grant a measurement overhead of 72 000 custom `performance.rdtsc()` cycles, or around 45 µs. This would grant an ideal bit rate of 22 kbit/s.

On Firefox 81 with COOP/COEP, with amplification, the measurement time would be 70 000 custom `performance.rdtsc()` cycles, granting as well an ideal bit rate of 22 kbit/s.

**Conclusion** The introduction of non-timer-based countermeasures, specifically site isolation for Chrome and COOP/COEP for Firefox have led browser vendors to take a step backward on timer-based countermeasures. Lowering the resolution and the jitter has an impact on the measurement overhead, hence on real-world attack time. Starting from Chrome 72, the resolution of `performance.now()` has been set to 5 µs with jitter. Starting from Firefox 79, when COOP/COEP are set, the resolution of `performance.now()` is set to 20 µs without jitter.

A cache covert channel based on `performance.now()` amplification on Firefox 81 with COOP/COEP has an ideal bit rate 360 times higher than without COOP/COEP. Similarly, an attacker with COOP/COEP can build an eviction set in around a few seconds, where an attacker without COOP/COEP would need several minutes. The same goes with Chrome:
on version 71, with a resolution of 100 µs, we obtain, with amplification, an ideal bit rate of 800 bit/s, 30 times lower than with the new Chrome 84 timer values. An attacker using Chrome 84 can build an eviction set in a matter of seconds, as opposed to several hundred seconds for Chrome 71.

The efficiency of the jitter is also highlighted by these results: between Chrome 84, with jitter, and Firefox 81 with COOP/COEP, without jitter, the measurement overhead is similar, when Chrome offers a better base resolution.

These changes have a massive impact on a browser-based threat model, where a script running with high performance for several minutes is highly suspicious, and can be detected by browsers. In a first-party scenario, an attacker can easily setup COOP/COEP and use a powerful timer granted by this change of resolution and timer. For both browsers, the impact of this change in resolution is a massive increase in the threat of timing attacks, as it means that P1 is less mitigated than on older versions. Changing the timer resolution does not prevent attacks, but impacts massively the time needed to execute them, which is an important factor in web security, as the user has to stay on the malicious web page for the duration of the attack. Setting a lower resolution and lower jitter has a double impact on the measurement overhead: as each clock edge is shorter, each measurement is faster. The attacker therefore needs fewer repetitions to eliminate the jitter, furthermore accelerating attacks.

### 3.4.3. Longitudinal study of SharedArrayBuffer-based clocks

**Resolution** The resolution of SharedArrayBuffer only depends on the computation time of an increment of the shared value. The smaller the value, the higher the resolution. We used performance.rdtsc() before and after incrementing the array buffer and tested two different types of increments: a simple increment (value++) and the built-in method Atomics.add [ECMa]. The Atomics API offers methods to safely use shared memory and handle conflicts.

We observed that a simple increment takes in the order of 20 custom cycles on both Chrome 84 and Firefox 81 whereas using Atomics takes 100. Logically, handling concurrent accesses introduces an overhead. We also noted that the first increment is slower, by an order of magnitude, probably from a cache impact. As the sub-thread systematically increases the same value, we excluded it and focused on the following values. SharedArrayBuffer offers a resolution in the order of 20 CPU cycles, or 10 ns on our CPU.

**Measurement overhead** The measurement overhead for SharedArrayBuffer is roughly the time it takes to read a value in the shared array twice: before and after the event. We again used our custom performance.rdtsc() to measure this time, and we tested two methods: standard array access and Atomics.load. On Firefox 81, a standard access lasts in the order of 42 custom cycles, opposed to 160 with Atomics API. As the lowest measurement overhead is preferable, we used the standard access. The measurement overhead on Chrome 84 with the standard access is 40 performance.rdtsc() cycles, or 20 ns on a 1.60 GHz CPU. It is similar on Firefox 81.

**Conclusions** SharedArrayBuffer have been disabled by default in Chrome 60 and Firefox 57.0.4 to mitigate Spectre. With the introduction of mitigations to transient execution attacks, they have been reimplemented. They are available by default in Firefox 79 with COOP/COEP, and by default in Chrome 68.
SharedArrayBuffer based timers are, by far, the most powerful timer available in browsers. Table 3.2 illustrates the resolution and measurement time for SharedArrayBuffer-based clocks. They offer a resolution of 20 cycles and a measurement overhead of 40 cycles, equivalent to 10 ns and 20 ns respectively on a 1.60 GHz CPU. The offered resolution is sufficient to implement all known timing attacks. In addition, they have a very low measurement overhead and do not need amplification. An attacker using SharedArrayBuffer to build a covert channel can achieve an ideal bit rate of 50 Mbit/s on both browsers. This is 800 000 times higher than with performance.now() on Firefox 81 without COOP/COEP, and 2000 times higher than Chrome 84 and Firefox 81 with COOP/COEP.

An attacker could theoretically create an eviction set in less than a tenth of a millisecond by using this method. However, the algorithm required to create an eviction set has other sources of heavy computation, and still run within a few hundred milliseconds on our system.

Free access to such a powerful timer shows that P1 is not mitigated. Excluding Spectre-PHT, most of state-of-the-art attacks are theoretically possible under the current state of Chrome and Firefox, as P1, P2 and P3 are not mitigated, and P4 only partially mitigated. Other transient execution attacks, such as RIDL [vSMÖ+19] or ret2spec [MR18] are not prevented by COOP/COEP or site isolation, and are still implementable under certain conditions as the shared system resources are still accessible. In Firefox, where SharedArrayBuffer are restricted to sites with COOP/COEP, an attacker can still use them in a first-party scenario. Logically, countermeasures on performance.now() or other timers are secondary when SharedArrayBuffer are available, because they allow the creation of way more potent timers.

## 3.5. Discussion

In this section, we discuss the current state of timers in browsers and the challenges surrounding them.

**Usability vs security and the lack of proper mitigations**

In Section 3.2, we have seen that the behavior of API timers like `performance.now()` has varied over the years in response to newly discovered attacks. Timing-based countermeasures (C2) have been widely implemented, but to various degrees of strength. On one hand, browser vendors decreased timer's resolution and added jitter to provide a more secure environment for their users. But on the other hand, their decisions appear arbitrary in retrospect as changes to timers were made without any concrete evidence of their effectiveness. For example, despite the study of Oren et al. in 2015 [OKSK15], it was not until 2018 that we saw the first implementation of jitter in web browsers. In that time frame, the decrease in timer resolution could simply be bypassed through interpolation [SMGM17]. Moreover, since some genuine applications are directly impacted by the lack of real-time precision provided by the affected timers [Bug18c], each browser vendor has tried to balance security with usability: Chrome never went above 100 µs, Firefox hovered around the 1 ms mark and got down recently to 20 µs while the Tor Browser has kept a 100 ms resolution since April 2015. The same goes for SharedArrayBuffer: they are enabled by default on Chrome, Edge and Opera, enabled under COOP/COEP for Firefox, and disabled on Safari and Tor.

This lack of consensus between vendors highlights how uncertain the industry is with the provided fixes. The results provided in this chapter show that the current timer-based countermeasures (C2) are a good first step towards protecting users but they still fall short of
fully protecting them against a large range of timing attacks, as P1 is a shared prerequisite between most of the timing attacks, and allegedly future timing attacks.

An alternative that could be considered by vendors is to put access to a high-resolution timer, based on `performance.now()` or `SharedArrayBuffer`, behind a permission. This way, when a developer needs it for an application or a game, she would need to ask the user for an explicit permission. This would prevent stealthy usage of API timers for timing attacks and all vendors could adopt the exact same very low resolution by default as it would not break pages not needing it.

### The false sense of security created by resource isolation
Recent trends on the development of the web as a platform have focused a lot on controlling what is running on a web page. Isolation-based countermeasures (C1) are at the core of browser security. Mechanisms like SRI [Conh], CORP [Conc], COOP/COEP [AJ], site isolation [RMO19] or even a proposal for better cookies [Wes] are all pushing the web forward in strengthening security. Yet, when it comes to timing attacks, all these new barriers create a false sense of security even though some attacks are definitely now much harder to pull off than before. By design, these countermeasures are not meant to mitigate P2 nor P3, and only a subset of P4. They are a great step forward in terms of security, but are not sufficient alone to mitigate the vast majority of timing attacks. While they greatly limit the possibility of a third-party attack when everything is set up properly on a web page, an attacker can still host her own malicious domain and conduct the attack from there. Moreover, the recent increase of timer resolution coupled with the reactivation of `SharedArrayBuffer` represents a massive step back in security where some attacks can be run in similar conditions to the ones in 2015. Our study highlights the dangers of coming back to such a state, and we hope browser vendors will recognize their mistakes by considering stronger mitigations to P1.

### The need to mitigate timing attacks at the OS or hardware level
Since timers can represent such an important threat to the security in a web browser, one can wonder if it would be possible to have a browser without timers. One approach is to try and make the browser deterministic as prototyped by Cao et al. with DeterFox [CCLW17]. By transforming a physical clock into a logical one, they change the behavior of known timers so that they do not return the time a request takes but return the number of operations that are being executed. While promising, this approach presents several shortcomings. First, they have to patch each known clock individually to instill this new behavior. A deep re-engineering of the browser would have to be made to possibly cover all implicit clocks. The second problem is that a logical clock loses all its meaning in the context of a real-time application. Some programs need to access the actual physical clock of the system to function properly and having a deterministic clock would present a lot of hurdles for developers.

In the end, we believe that everything running in a web browser has the potential to be a timer. This means that fully mitigating P1 seems out of reach. While browsers in 1995 mainly rendered static pages, the web has kept growing since then and it is now this rich and dynamic platform that can not only render pages but it is also the home of real-time communications and virtual reality, to name but a few. While some alternatives like putting access to high-resolution timers behind a permission can improve security, we simply have to learn to live with timers as they are such an intricate but integral part of the web.

As a consequence, mitigating timing attacks at the browser level is not the only solution
as we can develop solutions at both the OS and hardware level to provide stronger security against such threats, particularly mitigating P2 and P3. Software mitigations to transient execution still have, at this point in time, a high cost in performance. Browser vendors claim that mitigation must come from a lower level than software [TS] as hardware and transient execution attacks originate from microarchitectural optimizations.

## 3.6. Conclusion

We have studied the evolution in the last years and the current state of JavaScript-based timers and timing attacks for Chrome and Firefox, evaluating the resolution and measurement overhead for the two most efficient timers: `performance.now()` and `SharedArrayBuffer`. Timer-based countermeasures like clamping the resolution and adding jitter do not prevent attacks, but increase the time needed to exploit these attacks. Unlike in native environments, exploitation time is an important factor in web-based attacks, where the victim may not stay on the same web page for more than a few seconds or minutes. Unfortunately, the current trend of browser vendors undermining previous timer-based countermeasures by re-enabling `SharedArrayBuffer` and increasing the resolution to improve usability re-opens the door to many practical timing attacks, that were thought to be mitigated years ago. For example, the reintroduction of `SharedArrayBuffer` on Chrome brought a 2000-fold increase in covert channel capacity, compared to `performance.now()` alone. This is even more dramatic on Firefox, where the increase is 800 000-fold. Powerful countermeasures such as site isolation and COOP/COEP only prevent a sub-class of transient execution attacks, thus browsers are currently vulnerable to other transient execution attacks, as well as a large range of timing attacks, with a large threat surface.

## 3.7. Evolution of Timer Security Since The Publication of the Results

The original work from this contribution dates from November 2020. Since its publication, the state of the art on timing attacks and their countermeasures has evolved. In particular, starting from Chrome 92 [Gooc], site isolation is no longer sufficient to retrieve `performance.now()`'s 5 µs and `SharedArrayBuffer`, but rather requires COOP/COEP to be enabled, using the same system as Firefox. When COOP/COEP is not enabled, `SharedArrayBuffer` are disabled and `performance.now()` has a resolution of 100 µs with jitter. This decision allows to reduce the threat models of timing attacks, as COOP/COEP introduces more security against, for instance, third-party attacks. However, the debate on security against usability is still present. In particular, the adoption of COOP/COEP is long and can be complicated to implement for websites with a large number of origins. To that extent, changes to the origin policy brought by COOP/COEP are currently being discussed [Vah], such as easing the policy regarding loaded resources, or allowing `SharedArrayBuffer` and a higher resolution on `performance.now()` without COOP/COEP when site isolation is deployed, i.e., in latest versions of Chrome and Firefox.
<figure><img src="image_31.png" /></figure>
Port Contention in the
Browser 4

In 2018, port contention attacks have been shown to be a potential attack vector in a technique introduced by Aldaya et al. [ABuH+19], named PortSmash. This attack on Intel CPUs is based on port contention, where CPU ports act as a bottleneck in the execution pipeline. By sharing ports with the victim, the attacker can exploit timing differences caused by the contention of different instructions. PortSmash has a high temporal resolution and can be used, like its counterparts on the cache, to perform side-channel attacks on cryptographic libraries. While port contention attacks restrict the attacker by requiring that it shares the core it executes on with its victim, they are inherently stealthier than attacks on the memory subsystem. They are also immune to most hardware and system countermeasures which, in their vast majority, target the cache [PGGV21, DFS20, LL14, KASZ09, ZR13, SQ21].

When compared to cache attacks such as Prime+Probe, native port contention attacks offer better speed and spatial accuracy, do not require a complex cache profiling step, are more resistant to noise, and, most significantly, can bypass cache-centric countermeasures. Mounting a port contention attack in a browser setting would therefore deliver a real advantage to attackers. Performing such an attack, however, is far from trivial. The basic step of a Prime+Probe cache attack is sequential access to user-controlled memory. It has been shown that even high-level primitives, such as substring searches, can provide this functionality [SAO+21]. Port contention, on the other hand, requires an attacker process that is co-located with the victim on the same processor core and executes assembly language instructions carefully chosen to conflict with the victim's instructions. This is highly challenging in a web browser environment:

**C1** In this setting, the attacker's code is written in a highly-abstracted language which is translated into machine code by a just-in-time compiler;

**C2** The attacker has no control over the physical core selected by the browser to execute the attack code;

**C3** Finally, web-based timers have a lower resolution than native hardware-based timers, increasing the attacker's measurement noise.

This chapter tackles these challenges, and asks the following questions: Can port contention attacks be mounted from within the browser? What are the implications of this new attack vector?

**Contributions** This chapter makes the following contributions:

<footnote n="1">¹This work was presented before heavy countermeasures against timing attacks. The covert channel is theoretically still implementable, but with a heavily degraded bandwidth.</footnote>
<table><caption>**Table 4.1.** – Comparison of covert channels in web browsers.</caption><thead><tr><th>Covert channel</th><th>Bandwidth</th><th>Runs with current mitigations</th><th>Setup</th></tr></thead><tbody><tr><td>CPU throttling [RRR16]</td><td>0.2 bit/s</td><td>●</td><td>-</td></tr><tr><td>Disk contention [vGJ17]</td><td>5 bit/s</td><td>●</td><td>-</td></tr><tr><td>RIDL (Evict+Reload) [vSMÖ+19]</td><td>8 bit/s</td><td>●</td><td>-</td></tr><tr><td>DRAM [SMGM17]</td><td>11 bit/s</td><td>●</td><td>-</td></tr><tr><td>Hardware interrupts [LGS+17]</td><td>25 bit/s</td><td>●</td><td>cross-browser</td></tr><tr><td>Event loop [VK17]</td><td>200 bit/s</td><td>○</td><td>cross-browser</td></tr><tr><td>Prime+Probe [OKSK15]</td><td>320 kbit/s<sup>1</sup></td><td>●</td><td>cross-browser</td></tr><tr><td>Prime+Probe [OKSK15]</td><td>8 kbit/s<sup>1</sup></td><td>●</td><td>cross-VM</td></tr><tr><td>Port contention [our work]</td><td>200 bit/s</td><td>●</td><td>cross-browser</td></tr><tr><td>Port contention [our work]</td><td>80 bit/s</td><td>●</td><td>cross-VM</td></tr></tbody></table>

* We show that port contention can be ported to web browsers via WebAssembly, despite the strong requirements of this attack and the abstraction of the WebAssembly language. This greatly increases the attack surface that is due to port contention (Section 4.1).

* We propose an automated framework to find which WebAssembly instructions can cause port contention on a given Intel processor (Section 4.2).

* We demonstrate a side-channel attack on a synthetic example, to evaluate the resolution of our port contention attack. We show that our attack has a spatial resolution of 1024 instructions with a single trace, of the same order of magnitude as the best microarchitectural attacks in the browser (Section 4.3).

* We build a covert channel using port contention. With a sender running unprivileged native code and a receiver inside the browser, we obtain a throughput of 200 bit/s, i.e., one order of magnitude higher than modern covert channels in the browser. Table 4.1 compares the results of our covert channel with the state of the art. In a virtualized setting where the sender is running inside a virtual machine, we reach a throughput of 80 bit/s. We also build a cross-browser covert channel with an estimated throughput of 200 bit/s. (Section 4.4).

## 4.1. Web-Assembly-Based Port Contention

We introduce, to the best of our knowledge, the first implementation of port contention inside a browser. We can create and measure port contention from the JavaScript sandbox, on both Mozilla Firefox and Google Chrome. We found instructions that create contention on both P1 and P5, allowing diverse potential victims.

**Experimental setup and threat model** Unless stated otherwise, we run all experiments on an Intel i5-8365U CPU with a maximal frequency of 1.60 GHz running Ubuntu 20.10, with
Mozilla Firefox 90 and Google Chrome 95 desktop version, both using WebAssembly 1.1². As Safari and Edge support WebAssembly, the attack can theoretically be carried on these browsers, but they remain outside of the scope of this chapter. The threat model is similar to a user visiting a malicious website with his browser. The browser scripts run in a cross-origin isolated browser [Conb, Cona], granting more context isolation and allowing access to Shared ArrayBuffer and higher resolution timers.

**Description** In principle, our web-based attack follows a similar attack flow than Aldaya et al.'s [ABuH⁺¹⁹] described in Section 2.4.1.4, but in the more restrictive JavaScript sandbox. The attacker is situated inside of the browser sandbox. During the attack, they repeat specific WebAssembly instructions that cause contention on a specific port. Section 4.2 explains how we find these instructions on different systems. For instance, on our processor, the WebAssembly `ctz` (Count Trailing Zeros) instruction creates contention on P1. Similarly, instructions that truncate floats to integers, e.g., `trunc_f32_u`, create contention on P5. The attacker then times the execution of these instructions. If no other processes use the same port at the same time, these instructions will all be executed in a row, resulting in a fast execution time. However, if another process emits µops on the same port, these µops will be queued with the attacker-generated µops, resulting in a slower execution time for the attacker. By measuring these differences in timings, the attacker process can monitor the port usage on a specific port, and thus monitor other processes.

**Challenges** We face three challenges when implementing port contention in the browser. First, as browser-based scripts run in a controlled sandbox, we have no access to native instructions, and must instead use higher-level language constructs (C1). Furthermore, as browser-based scripts are meant to be portable, the instructions are translated to different assembly language instructions by the browser's engine on different systems. This means that the same script generates different native instructions depending on the CPU architecture, each with a different port usage, varying from vendors and generations. The code is also highly optimized by the engines, and execution can vary even on the same system, based on the variables or structure of the code. To gain more control over the port usage of our attacks, we mounted our attack with WebAssembly. This grants us access to smaller, more atomic instructions. However, these instructions are still executed through the browser's JIT engine, and their translation to machine language can vary from one system to another. For instance, the WebAssembly instruction `ctz` is translated into the native Intel instruction `TZCNT` on our system, as we describe in more detail in Section 4.2. The `TZCNT` instruction, in turn, is implemented using a single µop which is executed on P1 [AR]. Thus, repeatedly executing the WebAssembly instruction `ctz` can cause contention on P1. The Intel instruction `TZCNT` is only available, however, on CPUs starting from the Broadwell generation. Thus, the WebAssembly `ctz` instruction may generate contention on another port in older CPU generations. Directly compiling native code using x86 assembly instructions to create contention is not possible. Since WebAssembly is designed as a portable language, the compilers cannot emit instructions that are directly architecture-dependent, as they could not run on non-Intel CPUs.

Secondly, the high level of abstraction provided by the browser means that an attacker can neither know nor control on which core the attack is executed (C2). Furthermore,

<footnote n="2">²We used the latest version available in November 2021. This version did not support vectorial types and SIMD instructions.</footnote>
<figure><img src="image_32.png" /><figcaption>**Figure 4.1.** – Port 1 contention experiment on i64.ctz for 1 000 000 instructions.</figcaption></figure>

the operating system's scheduler dynamically moves processes between cores to optimize computing and save energy. We address this challenge by performing our attack on multiple cores simultaneously by using Web Workers, JavaScript multi-threading implementation, which creates a sub-thread running in a different process. This lets the attacker create as many attacker processes as physical cores, and as they all have a high workload, they are spread on different physical cores. Then, one of the attacker processes runs on the same core as the victim process, able to monitor it.

Finally, our attack requires high-resolution timers to monitor processes at the μop level (C3). Native implementations of port contention attacks all use the cycle-accurate rdtsc instruction. As explained in Section 2.6.2 and Chapter 3, browser vendors have restricted access to such timers inside of the sandbox to prevent timing attacks, but auxiliary timers can still be built, letting attackers recover a high-resolution timer. In our attack, unless stated otherwise, we use SharedArrayBuffer-based timers, which offer a resolution and measurement time in the order of 20 ns [SMGM17, RML21].

**Proof-of-concept** Figure 4.1 shows a proof-of-concept illustrating the contention on P1 caused by the WebAssembly i64.ctz instruction.

In this experiment, we time the execution of 1 000 000 WebAssembly i64.ctz instructions using the low-resolution JavaScript function performance.now. We run the experiment on Firefox 90, where this timer offers a resolution of 20 µs without jitter. In parallel with the Firefox code, we also run a sender program written in native code and pinned to the same processor. In the P1 contention experiment, the native sender runs the Intel instruction crc32 in a loop. This assembly language instruction is known to cause contention on P1. In the control experiment, the native sender runs a simple loop designed not to cause port contention. We run this program, instead of simply not executing the sender at all, to ensure that the difference stems from port contention, and not from other sources. As the figure shows, the timings measured during the P1 contention experiment are on average 5% higher than the control experiment, allowing the browser to efficiently distinguish between the two distributions. We observe similar results on Chrome 95.

In the following sections, we describe how to convert this proof-of-concept into practical attacks. In particular we obtain a higher spatial resolution and evaluate 100 WebAssembly instructions (C1), we ensure the attacker does not have to pin processes (C2), and we use a higher resolution timer (C3).
## 4.2. PC-detector

The translation of WebAssembly instructions into µops is variable on different systems: it can depend on the microarchitecture, instruction extension sets or JavaScript engine. In this context, it can be hard to find WebAssembly instructions that reliably cause port contention. In this section, we propose PC-detector, a Selenium-based framework to dynamically detect and characterize the port usage of WebAssembly instructions. Using the methodology described in Section 4.1, PC-detector automatically tests multiple WebAssembly instructions and checks if they cause contention on P1 or P5.

### 4.2.1. Description

**Framework** Our framework is composed of two components. The first component is a native C script that either runs an empty loop, creates contention on P1, or creates contention on P5. The second component is a Selenium-controlled browser which runs automatically generated WebAssembly code. For each WebAssembly instruction *instr*, we create a binary file with 1 000 000 calls. This file is then executed in the browser, and its runtime is measured using `performance.now()`<fnref n="3" />. We run three experiments:

1. Repeatedly executing and timing the WebAssembly file, used as a control.

2. Creating contention on P1 with native code and timing the WebAssembly file.

3. Creating contention on P5 with native code and timing the WebAssembly file.

By evaluating the timing distributions of these three experiments, we can evaluate the port usage of *instr*. If the three distributions are mixed, *instr* is not affected by the port contention (thus it cannot cause it). If the P1 timings (respectively P5) are, on average, higher than both the control and P5 (respectively P1), this means *instr* can detect, and cause, contention on P1 (respectively P5).

We evaluate all standardized single and double operand operations [Gro], including arithmetic operations and memory operations. Due to the stack machine structure of WebAssembly, each experiment includes a load operation to add values to the stack between each operation. We discovered that due to JIT optimizations, it is not possible to load many values on the stack before running double operand operations in a row, as the compiler reorders the instructions to alternate between loads and the tested operation. Therefore, we could not run all double operand operations one after the other. We evaluate single instructions when instructions have an output of the same type as their input, and pairs of complementary instructions in the other case (e.g., convert a 32 bit integer into a 64 bit float). We do not evaluate control flow operations, e.g., loops or jumps.

**Metrics** We propose two main metrics to automatically evaluate if a WebAssembly instruction can create contention on P1 or P5. The first one is based on the error rate between timings from the P1 and P5 experiments. For this metric, we compare P1 to P5 instead of P1 to control, as the control experiment does not run calculations on the native side. This

<footnote n="3">³Here, we use `performance.now()` instead of a `SharedArrayBuffer`-based clock as we control the number of calls to *instr*. This allows us to artificially augment the duration of the timed event to be measurable with `performance.now()`. This ensures us that contention is caused by our experiment, and not by noise created by `SharedArrayBuffer`'s increments.</footnote>
means that the timing differences could originate from other sources than port contention, e.g., variation in frequency or contention on another shared hardware component. P1 and P5 have two timing distributions, and one distribution ($X_{low}$) has lower timings than the other distribution ($X_{high}$) when there is contention. Given a temporal threshold $\tau$, we define the error rate as the proportion of values of $X_{low} > \tau$ and values of $X_{high} < \tau$ over all experiments. We define the error rate for a given threshold as

$$er_{\tau} = \frac{|X_{low} > \tau| + |X_{high} < \tau|}{|X_{low}| + |X_{high}|}.$$

Then, by computing $er_{\tau}$ for $[min(X_{low}) < \tau < max(X_{high})]$, we can retrieve the lowest error rate possible, giving us the probability for a program to blindly distinguish between port contention and standard usage from experiment timings. By inverting $X_{low}$ and $X_{high}$ and computing the best error rate, we can see if an instruction creates contention on P1, P5 or none. In PC-detector, we infer that if $er_{\tau} < 5\%$, an instruction creates contention.

The error rate calculation lets us identify whether an instruction creates contention. It does not, however, illustrate the efficiency of this contention, i.e., how separated both distributions are or how spread they are. This parameter is important in our attacks, as the more distance between the distributions, the easier it is to distinguish between contention and standard usage. In order to measure the distance between P1 and P5, we compute the effect size, also known as Cohen's d. In our case, Cohen's d between P1 and P5 is defined as

$$d = \frac{|mean(P1) - mean(P5)|}{\sqrt{(stdev(P1) + stdev(P5))/2}},$$

with stdev() the standard deviation of the distribution. A high Cohen's d means that distributions are highly separated and concentrated, and that we can more easily distinguish contention from standard usage.

### 4.2.2. Results

We have tested 100 different instructions, including numerical, memory, bit-wise, and type conversion operations.

Table 4.2 lists which instructions cause contention on the i5-8365U. The results are identical between Chrome and Firefox, although the distance varies because of the different browser architectures. In total, we found 21 instructions causing contention. As most instructions have 32- and 64-bit variants, some instructions are doubled. Generally, we observe that 64-bit variants have a greater Cohen's d than their 32-bit counterparts. Similarly, the unsigned variants of integer operations often grant better results than the signed variants.

P1 contention seems to be caused by arithmetic instructions, whereas conversion/truncation operations create contention on P5. This result is coherent with the specialization of ports and execution units. i64.rem_u shows the highest effect size of all detected instructions.

To demonstrate the portability of port contention and PC-detector, we have run the same benchmark on different Intel CPUs. In total, we have tested 4 recent CPUs: i5-8365U, i7-8650, i7-10510 and i7-10610. The instructions creating contention remain constant, but Cohen's d can vary based on the CPU frequency. This is logical, as all tested cores have the same instruction set extensions, meaning that the WebAssembly instructions are translated to the same native instructions.
<table><caption>**Table 4.2.** – WebAssembly instructions causing port contention. For clarity, we group together the 32- and 64- bits versions of instructions under one line marked i32/i64.</caption><thead><tr><th>Instruction</th><th>P1 contention</th><th>P5 contention</th><th>Cohen's d</th></tr></thead><tbody><tr><td>i32/i64.ctz</td><td>●</td><td>○</td><td>1.2</td></tr><tr><td>i32/i64.clz</td><td>●</td><td>○</td><td>1</td></tr><tr><td>i32/i64.popcnt</td><td>●</td><td>○</td><td>1</td></tr><tr><td>i32/i64.div_s</td><td>●</td><td>○</td><td>10</td></tr><tr><td>i32/i64.div_u</td><td>●</td><td>○</td><td>10</td></tr><tr><td>i32/i64.rem_u</td><td>●</td><td>○</td><td>34</td></tr><tr><td>i32/i64.rem_s</td><td>●</td><td>○</td><td>5</td></tr><tr><td>f32.convert_i32_s and i32.trunc_f64_s</td><td>○</td><td>●</td><td>1</td></tr><tr><td>f32.convert_i32_s and i32.trunc_f32_s</td><td>○</td><td>●</td><td>2</td></tr><tr><td>f32.convert_i64_s and i64.trunc_f32_s</td><td>○</td><td>●</td><td>8</td></tr><tr><td>f32.convert_i32_u and i32.trunc_f32_u</td><td>○</td><td>●</td><td>2</td></tr><tr><td>f32.demote_f64 and f64.promote_f32</td><td>○</td><td>●</td><td>3</td></tr><tr><td>i32-wrap_i64 and i64.extend_i32_u</td><td>●</td><td>○</td><td>16</td></tr><tr><td>i32-wrap_i64 and i64.extend_i32_s</td><td>●</td><td>○</td><td>11</td></tr></tbody></table>

## 4.3. Side-channel Attack on Artificial Applications

In this section, we present an artificial gadget, illustrating the side-channel threat of web-based port contention. We built a synthetic and generic example showing how a program, which execution depends on secret information, is vulnerable to WebAssembly port contention. Indeed, if a program has branches depending on secret bits, an attacker can use a side-channel attack to infer the secret. The victim process is an unprivileged native process. The attacker is a JavaScript and WebAssembly script, running inside of the browser's sandbox. The attacker has no access to addresses, native instructions, and no control or knowledge of physical or logical cores.

In our implementation, an attacker, running code inside the browser's sandbox, monitors the victim's execution with a spatial resolution of 1024 native instructions, i.e., 3072 bytes. This spatial resolution is of the same order of magnitude as other microarchitectural attacks in the browser, e.g., Prime+Probe, which has a resolution of a cache set (typically 12 to 20 cache lines), i.e., 1280 bytes on our system.

### 4.3.1. Description

The victim is a native unprivileged program, running different code sections based on the bits of secret information. As port usage differs between branches, an attacker monitoring port contention could infer parts of the secret. Figure 4.2 illustrates our gadget, implemented in native assembly code. Depending on a secret bit, the code will execute either instruction creating contention on P1 or P5. To detect from within the browser which path is taken by the victim, we time the execution of *nb<sub>instr</sub>* WebAssembly *rem_u* instructions, which creates contention on P1 (Section 4.2). If the execution time is high, then we know that the native code also creates contention on P1, whereas if it is standard, we know that the native code
<figure><img src="image_33.png" /><figcaption>**Figure 4.2.** – Side channel artificial example. Depending on the key bit passed in parameter, the code will have different port usage.</figcaption></figure>

does not create contention. By repeating this process, we detect the branch that was executed by the native script, and hence the value of the secret bit.

After resolving **C1** with PC-detector and **C3** with `SharedArrayBuffer`, we still face the inability to pin the attack code to the same physical core as the victim (**C2**). Most schedulers try to balance the workload between physical cores. By creating a number of listening Web Workers equal to the number of physical cores, we maximize our chances that one of them listens on the victim's physical core, thus circumventing **C2**. Information about the system's core count is available through the `navigator.hardware_concurrency` JavaScript API [Cone], available by default on both Chrome and Firefox.

### 4.3.2. Results

An important metric for our evaluation is the spatial resolution, i.e., the smallest number of instructions we can detect in a branch. To detect contention, we measure the execution time of *nb<sub>instr</sub>* WebAssembly `rem_u` instructions. This parameter is important: a high number of instructions lowers our spatial resolution, but a lower number yields noisier time measurements. Furthermore, for values of *nb<sub>instr</sub>* ranging from 1 to 10, the execution time of the instruction is slower than the read access to the shared array and other overhead introduced by JavaScript. This means that contention is measured at only specific times in the measurement. To reduce the measurement time of `SharedArrayBuffer`, we access the array directly, without using concurrent access libraries. This grants a better resolution to the timer but creates more noise and outliers. On our system, we were able to create a web listener running in the same physical core as the victim in 95% of our experiments. We infer that the remaining errors stem from the scheduler moving our process to different cores because of other threads creating noise.

On our system, we found $nb_{instr} = 10$ to be the best compromise between noise and resolution. To reduce the noise, we process the data with a median sliding window with a width of 10 measurements. Figure 4.3 illustrates the resulting values when the victim runs the code with the secret 1101001, for a single trace of the victim. The high values represents
<figure><img src="image_34.png" /><figcaption>**Figure 4.3.** – Single-trace execution with secret information 1101001, on Chrome 95.</figcaption></figure>

the execution of the victim branch creating contention on P1 i.e., a bit set to 1. The width of a peak or a pit is proportional to the number of bits inside the sequence.

Our implementation is able to detect the executed branch with a resolution of 1024 native instructions on both Google Chrome and Mozilla Firefox. To obtain this result, we first implement Figure 4.2 with a very high number of POPCNT and VPBROADCASTD instructions, that we progressively lower. The resolution is the lowest number of instructions where we can clearly retrieve the secret bits without error on a single victim trace.

This experimental limit of 1024 instructions is mainly due to the lack of access to high-resolution timers. Note that we observe two peaks per secret bit with a single trace. We have found that a higher resolution of 512 instructions could introduce errors with a single-trace attack. One solution to increase the resolution would be to revert to multiple-trace attacks. Moreover, by using a custom browser implementing rdtsc, based on the native cycle accurate timer, we observed that our implementation has a resolution of 256 instructions, i.e., a better spatial resolution than Prime+Probe. This means that our experimental limit could be lowered with better auxiliary timers or noise filters, which could offer a more fine-grained attack vector than existing microarchitectural side channels in the browser.

## 4.4. Covert Channel

In this section, we present a port contention-based covert channel with a throughput of 200 bit/s for a 1% error rate. This covert channel is composed of a sender running unprivileged native code, and a receiver running completely inside the browser (similarly as Schwarz et al. [SMGM17]). We also show that our covert channel runs with a sender located inside a VM, and can even be used in a cross-browser fashion (similarly as Lipp et al. [LGS$^+$17]).

The sender runs unprivileged C code on the victim's hardware. The sender can therefore freely use most native instructions, and has access to cycle-accurate timers. It can also pin itself to a certain physical or logical core. The receiver, on the other hand, runs fully inside a cross-origin isolated web page. As it runs inside the browser's sandbox, the receiver has no access to native instructions. Port contention must be created and measured by using WebAssembly (C1). Moreover, the web script must share a physical core with the sender, but cannot control or know on which physical core it is running (C2). Finally, the receiver does not have access to high-resolution timers (C3). Instead, we use SharedArray Buffers to get the best resolution available.
### 4.4.1. Description

We implemented a half-duplex asynchronous channel based on port contention, between a native sender and a web-based receiver. In addition to data, the sender and receiver exchange control messages to handle acknowledgments and synchronization. Both parties must therefore be able to send and receive bits. Our side channel can be decomposed into two layers. The lower layer, sending and receiving bits, is equivalent to the physical layer of the TCP/IP model. This layer uses CPU ports as its transmitting channel, and must be able to distinguish between 0 and 1 bits. The upper layer is equivalent to the data-link layer. This layer handles the synchronization between the parties, as well as error management.

**Physical layer** The two parties send 1-bits by creating contention on P1 for a fixed duration ($t_{bit}$), and send 0-bits by idling for $t_{bit}$. $t_{bit}$ is an important factor, as a high duration lowers the channel's bandwidth but allows the receiver to tolerate more noise when attempting to distinguish bits. In our covert channel implementation, we have fixed $t_{bit}$ = 1 ms. To create contention, the sender and receiver repeatedly call an instruction, respectively the native Intel instruction `crc32` and the WebAssembly instruction `rem_u`. To receive a bit, the sender or receiver repeatedly calls these instructions while timing them. A high execution time means the emitting party is sending a 1, while a standard time means a 0. As both instructions are handled by the CPU port P1, both the sender and receiver cannot emit at the same time, making our channel a half-duplex channel. Besides their high resolution, another advantage of a `SharedArrayBuffer`-based timer is that it is based on a Web Worker, and therefore runs on a different core. This lowers potential noise on the covert channel.

We also need to ensure both the sender and receiver are running on the same core (C2). As the browser cannot control which core it is running on, the sender creates as many sub-senders as physical cores. The sender runs unprivileged native code, so it knows the number of physical and logical cores, and can pin each of its sub-threads to a specific core. This ensures that at least one sender thread is running on the same physical core as the receiver.

Although `SharedArrayBuffer`s offer a high resolution, they can introduce errors at the physical layer level. In particular, concurrent accesses between the thread incrementing a value and the main thread reading the timestamp can cause insertion or deletion errors. We have determined two error-prone scenarios at the physical level. In the first scenario, the main thread reads the shared value too frequently. This prevents the clock thread from incrementing the value, and as a result the measured time is much lower than the real-time value. The other scenario stems from particularly high measurement outliers when contention is created. We assume it also comes from concurrent accesses. As this access is longer than usual, it means that we can get less measurements during $t_{bit}$, thus creating bit deletion errors on higher layers.

**Protocol and frame format** To ensure synchronization and correct potential errors, we implemented a simple protocol above our physical layer, similarly as Maurice et al. [MWS+17]. Figure 4.4 illustrates a typical exchange, as well as packet loss management. It is based on a simple request-to-send scheme: the receiver sends a request frame (described in Figure 4.5a), containing a 4-bit sequence number. Upon reception, the sender sends a data frame (described in Figure 4.5b), containing the sequence number as well as the associated data (1 byte). If the data frame is received correctly, the receiver requests the next sequence number. Both
<figure><img src="image_35.png" /><figcaption>**Figure 4.4.** – Illustration of the protocol’s synchronization in case of lost or incorrect packet.</figcaption></figure>

frames start with a 4-bit preamble consisting of an initial sequence which is always set to 1010. This initial sequence serves as calibration for the receiver.

To handle possible insertion or deletion errors, we added an error detection code. More specifically, the sequence number is encoded with (8,4) Hamming code [Ham50] in request frames, and the last 4 bits of the data frame contain a Berger code [Ber61], counting the number of zeros in the data and sequence number fields. As the type of errors we face are mainly bit insertion or deletion, we do not use the error correcting properties of Hamming code, and instead use it as an error-detection code.

Our protocol encodes 8 bits of payload into a 31-bit message, including the preamble, sequence numbers and error detecting code. This means that, with $t_{bit}=1$ ms, we can reach a maximal raw throughput of 1 kbit/s, i.e., a theoretical maximum of data bit rate of 260 bit/s.

Our protocol also manages packet loss and desynchronization. This is handled by the sequence number and the request-to-send scheme. As illustrated in Figure 4.4, after sending a request, the receiver waits for a fixed timeout value. If it has not received an answer at the end of this time period, it simply re-sends the request. This lets the covert channel recover from packet loss from the sender to the receiver, and from the receiver to the sender.

**Receiving frames** The sender and receiver do not share a common clock. Hence, the party receiving bits does not know in advance the demarcations between successive bits, nor when the frame starts. It is processing execution time of instructions as a real-time stream of information, not in post-processing. In order to automatically detect the start of the frame, as well as the actual bits, both sender and receiver run DenStream [CEQZ06], a density-based data-stream clustering algorithm. It dynamically creates clusters of data, based on the execution time and their time of arrival. The listening party then detects the start of the frame when it detects 4 consequent small clusters with variation in execution time, corresponding to the initial sequence of 1010. The initial sequence is used to calibrate two
<table><caption>(a) Request frame.</caption><thead><tr><th>0</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th></tr></thead><tbody><tr><td>Init sequence</td><td colspan="7">-encoded -</td></tr><tr><td>-Sequence number</td><td colspan="7"></td></tr></tbody></table>

<table><caption>(b) Data frame.</caption><thead><tr><th>0</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th></tr></thead><tbody><tr><td>Init sequence</td><td colspan="7">Sequence Number</td></tr><tr><td colspan="8">Data</td></tr><tr><td>Berger code</td><td colspan="7"></td></tr></tbody></table>

**Figure 4.5.** – Format of the request and data frames.

major values: the temporal threshold between 0-bits and 1-bits, as well as the average number of instructions in a single bit. The average number of points lets the algorithm detect the number of bits in a sequence. As DenStream computation can be slow when we reach a high bit rate, we only use it to detect the preamble. For the rest of the frame, we use a simple stream-based threshold detection: timings above the calibration threshold are identified as 1-bits, and others as 0-bits.

To infer the actual number of bits in such a sequence, we use the average number of instructions calibrated from the initialization sequence. Then, by dividing the number of instructions in our same bit sequence, we can infer how many bits it contains. This step is prone to insertion or deletion errors.

When the stream algorithm has detected a number of bits corresponding to the frame size, it stops listening. If the frame is invalid because of insertion and deletion errors, we try to reinterpret it with slightly modified calibration values. Indeed, variation in frequency can cause slight changes on the number of measurements in a bit, e.g., a frequency raise means we measure more instructions in a bit, thus potential insertion errors.

### 4.4.2. Evaluation

We evaluated our covert channel in two different scenarios. The first scenario is the baseline implementation, where both the native sender and web-based receiver run in a standard OS. In the second scenario, the native sender now runs in a virtual machine running on the victim's physical hardware, while the browser runs in the standard OS. This scenario is common, as malware analysis is often conducted in sandboxed environments such as VMs. We also evaluate the impact of noise on our covert channel.

**Native sender** This threat model represents the most common scenario, where both the browser and the native sender run as unprivileged processes in the OS. We evaluated our covert channel by transmitting 10 kB of data from the native sender to the web-based receiver. To compute the error rate, we compare the original and received bit sequences bit-by-bit.

Table 4.3 illustrates the bit rate and error rate of our channel in different noise conditions. The transmission takes, on average, slightly less than 7 min. During the transmission, on
<figure><img src="image_36.png" /><figcaption>(a) Standard native-to-web scenario</figcaption></figure>

<figure><img src="image_37.png" /><figcaption>(b) VM-to-Host scenario</figcaption></figure>

<figure><img src="image_38.png" /><figcaption>(c) Cross-Browser scenario</figcaption></figure>

average 600 frames arrive incorrectly or are lost from the sender to the receiver, over a total of 10 600 frames. This represents a total frame loss rate of 5.5%. Most of the incorrect frames were the result of insertion or deletion errors. The lost frame rate from the receiver to the sender is negligible. We achieve a bit rate of 200 bit/s. This is 80% of the maximal bandwidth possible when using $t_{bit}$ =1 ms. The difference between the bit rate upper bound and our implementation stems from the loss of frames, which requires the sender to wait for some time before requesting the data again, as well as from the short computation time required to handle the protocol.

In this setup, our covert channel presents a better bit rate than previous web-based covert channels [SMGM17, LGS$^{+}$17, RRR16, VK17, vGJ17]. The only covert channel with a better resolution is Prime+Probe by Oren et al. [OKSK15]. However, recent countermeasures had a substantial negative impact on the bit rate. To the best of our knowledge, no other Prime+Probe covert channel has been implemented since that allows us to compare between the two approaches. The closest cache covert channel is the one presented by van Schaik et al. in RIDL [vSMÖ$^{+}$19], with a bit rate of 8 bit/s.

We now evaluate our covert channel in the presence of noise. Noise can impact both the bit transmission through port contention, and the SharedArrayBuffer clock. Indeed, we observe that when stressing the physical core used by the SharedArrayBuffer clock, the number of ticks we measure in each time period decreases, in turn decreasing our resolution. However, our covert channel shows strong resilience to sources of noise with a low thread count. That is
<table><caption>**Table 4.3.** – Evaluation of the port-contention covert channel in different conditions.</caption><thead><tr><th>Experimental setup</th><th>Bit rate</th><th>Packet Loss rate</th><th>Error rate</th></tr></thead><tbody><tr><td>Noiseless</td><td>200 bit/s</td><td>5.5%</td><td>1%</td></tr><tr><td>stress -c 2</td><td>170 bit/s</td><td>8%</td><td>3%</td></tr><tr><td>stress -m 2</td><td>120 bit/s</td><td>15%</td><td>3%</td></tr><tr><td>stress -c/-m 3</td><td>25 bit/s</td><td>80%</td><td>5%</td></tr><tr><td>stress -c/-m 8</td><td>&lt;1 bit/s</td><td>99%</td><td>5%</td></tr></tbody></table>

because port contention depends on the physical core. As our sender and receiver already use a major part of the core computing capacities, the OS scheduler tends to move other noisy processes to different physical cores, thus lowering their impact on our covert channel. For instance, when running stress with square root (-s) or malloc (-m) on two threads, the bit rate remains on the same order of magnitude. The loss of performance stems from a higher rate of lost frames due to clock outliers. Our channel also shows better resilience to sources of noise with a low thread count than cache covert channels, as the LLC is shared between cores [MWS$^{+17}$]. However, if a noisy thread runs on a physical core shared either by the clock or the receiver, the performance significantly drops, as illustrated in the stress -c 3 case. In that case, the lost frame rate increases drastically because of lower resolution from our timer. Introducing specific error-correcting codes to correct insertion or deletion errors could greatly improve the performance of the channel in noisy conditions.

**Virtualized sender** We also evaluate our channel in a virtualized setup. In this scenario, the native sender runs inside of a virtual machine running Ubuntu. The browser runs in the standard OS. The main change in the threat model is that the native sender has no control or knowledge of cores, physical or logical. However, by creating multiple sender threads and not pinning them, we managed to force at least one sender thread to run on a physical core shared with a receiver. In this setup, our covert channel has a bit rate of 80 bit/s. This bit rate is still higher than that of many browser covert channels [VK17, SMGM17, LGS$^{+17}$, vGJ17, RRR16], and even equivalent to some native covert channels in the same setup [SMAK20].

### 4.4.3. Cross-Browser Covert Channel Bandwidth Estimation

Our covert channel can be extended to a cross-browser setup. As we can create and detect contention on the browser, we can replace the native sender with a JavaScript sender. This has two major impacts on the effectiveness of the attack. First off, the web-based sender loses access to powerful native timers, potentially creating new errors on the request frames. Most importantly, the browser has no knowledge of physical or logical cores. It cannot know nor control on which core it is running. To circumvent this difficulty, the web-based sender creates a number of Web Workers equal to the number of physical cores of the machine. By doing so, the scheduler will spread these senders on different physical cores. When launching the receiver, however, the senders are not the only processes using a high workload, and we have noticed that launching the receiver and the SharedArrayBuffer clock after the sender results in a physical core running both the clock and the receiver, and the senders sharing the remaining core. We overcome this limitation by initializing the clock and receiver before the
<figure><img src="image_39.png" /><figcaption>**Figure 4.7.** – Transmitted square signal from Firefox 90 to Chrome 94 with $t_{bit}$ =1 ms</figcaption></figure>

sender. As a result, the scheduler assigns a physical core shared by a receiver and a sender, effectively allowing the implementation of our covert channel.

Using this technique, we were able to transmit bits of information across browsers through port contention with $t_{bit}$ = 1 ms. i.e., conditions equivalent to the native-to-web covert channel. We were able to demonstrate data transfer at the physical layer from Chrome to Firefox, from Firefox to Chrome, and between two instances of the same browser. Figure 4.7 shows the transmitted square signal from Firefox to Chrome. We did not re-implement the data-link layer to this threat model, as it represents significant engineering work, and leave it to future work. However, this proof of concept solves all scientific and technical challenges, including the most difficult, i.e., core management (C2), by its ability to transmit bits. As the physical layer offers similar bit and error rates to the native sender, even for a long duration of transmission, it is safe to estimate that this cross-browser covert channel can reach a final bandwidth on-par with the native-to-web covert channel, i.e., in the order of 200 bit/s.

## 4.5. Discussion

In this section, we discuss the limitations of our approach, potential countermeasures, as well as future work.

### 4.5.1. Limitations

The WebAssembly implementation of port contention offers a lower spatial resolution than the native PortSmash attack proposed by Aldaya et al. [ABuH$^+$19]. Most of this performance loss originates from the challenges introduced by the JavaScript sandbox. In particular, **C3** is the most challenging aspect. Although auxiliary timers offer a very high resolution, they are still inaccurate compared to native cycle-accurate timers. This difference particularly impacts the attack's spatial resolution, as timer imprecision prevents us from measuring small time differences.

Another limitation, inherent to port contention and SMT attacks, is that this attack cannot run in a cross-core setting. We can effectively circumvent **C2** by creating more threads to share a core with the victim, but the attack still depends on the OS scheduler. If the attacker cannot run code on the victim's physical core, the attack does not succeed.
### 4.5.2. Countermeasures

Many countermeasures have been proposed to mitigate microarchitectural attacks based on SMT. In particular, countermeasures to port contention can effectively apply to web-based port contention. These countermeasures, described more thoroughly in Section 2.6, can stem from several different levels. On the hardware level, SMT could be disabled or propose a more secure way of partitioning resources [TP19, TRVT22]. On the system level, standard approaches, such as port-independent code or static analysis, have been proposed [ABuH$^{+}$19]. More original approaches, such as an SMT-attacks-aware scheduler, could prevent this side channel. Web-based port contention could also be prevented at the browser level. However, except for timing-based countermeasures (see Chapter 3), browser countermeasures focus on cache side channels or Spectre-like attacks, and have no effect on web port contention.

## 4.6. Conclusion

We presented the first implementation of port contention in the browser (Q2). We showed that port contention side channels have a performance on par or better than previous microarchitectural side channels in the browser, and a more generic threat model. We demonstrated the genericity of this attack by building several types of exploits, including a 200 bit/s covert channel, as well as a concrete example illustrating a side-channel attack with a spatial resolution of 1024 instructions (Q3). We further demonstrated the portability of web-based port contention by testing instructions on different Intel CPUs, and we showed that our attack also works in cross-browser and Host-to-VM settings, while being more resilient to noise than cache attacks. We consider port contention side channels, and hardware contention side channels in general, to be a generic class of attacks that can be used as a building block for future microarchitectural attacks in the browser. This work illustrates the difficulty of isolating the JavaScript sandbox from microarchitectural attacks, as currently deployed countermeasures fail to mitigate contention-based side channels.
Port Contention Without
SMT and its Privacy
Implications 5

Port contention, as described by Aldaya et al. [ABuH+19] and in Chapter 4, requires SMT. Both the attacker and the victim need to run on the same physical core for the attack to work, as CPU ports are on-core resources. If the attacker cannot fill the victim's CPU ports, it cannot detect timing differences caused by the victim's actions, thus cannot mount attacks. This is also valid for the covert channel presented in Section 4.4: if both the sender and receiver cannot use the CPU ports at the same time, they cannot use port contention as the physical layer of the covert channel.

This prerequisite represents a challenge in some settings, as some systems do not have SMT or disable it [Hat], and it may become increasingly hard to fulfill as countermeasures to SMT attacks are being explored [TP19, TRVT22]. It also has severe implications in a web setting, where the attacker script, situated inside the JavaScript sandbox, cannot know nor control which core it is running on. Although we introduced core-control heuristics in Chapter 4, they may not function with a different scheduler, or an SMT-attack aware scheduler.

**Contributions** This chapter makes the following contributions:

* We present sequential port contention, a novel form of contention on the CPU execution ports. It relies on instruction-level parallelism instead of thread-level parallelism, hence does not rely on SMT. We show that such sequences work in native code but also work reliably in WebAssembly. Our side channel works in unmodified off-the-shelf browsers, including the privacy-focused browsers Tor and Brave (Section 5.2).

* We build a framework to automatically find WebAssembly instructions creating sequential port contention. We use differences in port contention behavior to fingerprint the CPU generations in WebAssembly in web browsers without any browser API. We evaluate our new fingerprinting method on 50 CPUs from 12 generations with an accuracy of 95% with a runtime of only 12s. We show that our fingerprint is highly stable over major releases of browsers and is robust against system noise (Section 5.3).

* We discuss the security and privacy implications of our new side channel. In particular, we discuss the advantages and limitations of our side channel for fingerprinting applications. We show that sequential port contention is also possible in a virtualized environment but stops working in emulated environments. These results also indicate that the side channel is valuable for malware as an anti-emulation measure (Section 5.4).
<figure><img src="image_40.png" /><figcaption>**Figure 5.1.** – Illustration of the differences in execution time based on the order of instructions, with a look-ahead window of size 1.</figcaption></figure>

## 5.1. Threat Model

Sequential port contention, as most microarchitectural attacks, requires code execution on the victim machine. We assume that the attacker either has native unprivileged code execution (native side channel) or can run WebAssembly in the victim's browser (browser-based side channel). The attacker does not rely on software vulnerabilities, does not require any permissions that have to be granted by the victim, or any particular setup such as SMT or a specific core assignment. We assume that the victim spends at least 15 s on the attacker's website, based on the average time of 20 s users spend on an unknown website [LWD10].

## 5.2. Port Contention Without SMT

In this section, we show port contention without requiring SMT, both in a native setting and in a browser sandbox.

### 5.2.1. Main Idea

The main idea of sequential port contention is to exploit the limited look-ahead window of the µop scheduler, leading to contention for well-chosen instruction pairs (*instr1*, *instr2*). Both instructions use different execution ports on the CPU. If the instructions are grouped, i.e., if the instruction stream consists of *n* instructions *instr1*, followed by *n* instructions *instr2*, with *n* larger than the look-ahead window of the scheduler, parallelization is not possible (cf. Figure 5.1a). The scheduler cannot detect that some instructions later in the instruction stream could already be executed in parallel. However, if interleaved in an instruction stream of 2*n* instructions, they can be executed in parallel (cf. Figure 5.1b). As a result, the overall execution time of an instruction stream of the same length depends on the order of the two repeated instructions *instr1* and *instr2* if these instructions do not use the same ports.

Similar to port contention with SMT [ABuH$^{+}$19], the contending instructions *instr1* and *instr2* depend on the underlying microarchitecture. However, as this information is publicly available [AR19], sequential port contention is applicable to a wide range of microarchitectures. We show sequential port contention in native environments (Section 5.2.2) and demonstrate that it is also exploitable from off-the-shelf unmodified browsers (Section 5.2.3).
**Listing 5.1** – *Grouped*. Always creates contention.

```
1 grouped:
2     lfence
3     rdtsc # Timestamp
4     lfence
5     .rept $n # First loop
6         instr1 %reg, %reg
7     .endr
8     .rept $n # Second loop
9         instr2 %reg, %reg
10    .endr
11     lfence # Timestamp
12     rdtsc
```

**Listing 5.2** – *Interleaved*. Creates contention if the two instructions share a CPU port.

```
13 interleaved:
14     lfence
15     rdtsc # Timestamp
16     lfence
17
18     .rept $n # Single loop
19         instr1 %reg, %reg
20         instr2 %reg, %reg
21     .endr
22
23     lfence # Timestamp
24     rdtsc
```

### 5.2.2. Native Environment

#### 5.2.2.1. Proof of Concept

Our proof of concept of sequential port contention is based on two experiments, illustrated in Listings 5.1 and 5.2. In these experiments, we evaluate two native x86 instructions, `instr1` and `instr2`.

The first experiment is a control experiment, *grouped*, which is composed of two loops, each calling an instruction *n* times. As the decomposition of instructions in µops is deterministic, the various calls to the same instructions have the same port usage. This means that during loop 1 (respectively loop 2), `instr1` (respectively `instr2`) always creates contention on its ports. The second experiment, *interleaved* is composed of a single loop with the same number of iterations. Instead of calling the same instructions in a row, it alternatively calls `instr1` and `instr2`. If `instr1` and `instr2` emit µops to the same port, it creates contention, resulting in a slower overall execution time. However, if they do not emit µops on the same port, the execution is parallelized due to instruction-level parallelization, resulting in a faster execution time.

By computing $\rho = \frac{\text{time(grouped)}}{\text{time(interleaved)}}$, we know if *interleaved* creates contention. If $\rho \approx 1$, both experiments have a similar execution time, i.e., the instructions share at least one port. If $\rho > 1$, *interleaved* has a shorter execution time than *grouped*, i.e., the instructions do not share a common port.

#### 5.2.2.2. Experiments

We ran this experiment on an Intel i5-8365U (Whiskey Lake), with TurboBoost enabled and without fixing the CPU frequency. First, we run it with `instr1 = crc32`, which emits a single µop on execution port 1 (P1), and `instr2 = aesdec`, which emits a single µop on execution port 0 (P0). Both instructions have the same throughput and latency.

Figure 5.2 illustrates the results of this experiment when we vary the number of loop iterations *n*. Figure 5.2a shows how the *grouped* execution time is systematically higher than the *interleaved* one. The gap between the two curves increases with the number of loops. Figure 5.2b shows that $\rho$ quickly converges to 1.8 at *n* = 1000. It then remains constant when increasing the number of loop iterations. The inflection point situated around *n* = 64 is caused by the size of the look-ahead window of the scheduler. When instructions from
<figure><img src="image_41.png" /><figcaption>**Figure 5.2.** – Sequential port contention experiments for instructions (crc32, aesdec).</figcaption></figure>

<figure><img src="image_42.png" /><figcaption>**Figure 5.3.** – Ratio $\rho$ for (crc32, popcnt) depending on the loop iterations $n$.</figcaption></figure>

both loops fit inside this window, the scheduler can rearrange instructions to execute them in the most optimized order, prioritizing parallelism and thus reducing port contention. When an `mfence` is added between the two loops (Lines 7-8 of Listing 5.1), this inflection point disappears, and the curve rises smoothly to 1.8.

We run the same experiment with `instr1 = crc32` and `instr2 = popcnt`. Both instructions emit a single P1 $\mu$op, and have the same throughput and latency. Figure 5.3 shows that $\rho$ stays constant around 1. That is expected, as the contention is always the same on P1, independently of instruction order.

### 5.2.3. Web Browsers

#### 5.2.3.1. Challenges

Porting these experiments to a browser sandbox introduces challenges similar to those met in Chapter 4 First, neither JavaScript nor WebAssembly provides high-resolution timers. In this chapter, we use a `SharedArrayBuffer`-based clock. Second, both JavaScript and WebAssembly are high-level languages running inside a sandbox. Moreover, WebAssembly instructions are
<caption>**Listing 5.3** – *Grouped* in WebAssembly. Always creates contention.</caption>

```python
25 (module
26 (func $grouped
27 (param $p type)(result type)
28 (local.get $p)
29 (type.instr_1)
30 ... # Repeat $n
31 (type.instr_1)
32 (type.instr_2)
33 ... # Repeat $n
34 (type.instr_2)
35 )
36 (export "grouped" (func $grouped))
37 )
```

<caption>**Listing 5.4** – *Interleaved* in Web-Assembly. Creates contention if the two instructions share a CPU port.</caption>

```python
38 (module
39 (func $interleaved
40 (param $p type)(result type)
41 (local.get $p)
42 (type.instr_1)
43 ... # Repeat $n
44 (type.instr_1)
45 (type.instr_2)
46 ... # Repeat $n
47 (type.instr_2)
48 )
49 (export "interleaved" (func $interleaved))
50 )
```

<figure><img src="image_43.png" /><figcaption>**Figure 5.4.** – Ratio $\rho$ for the WebAssembly instructions (`i64.popcnt`, `i64.or`) depending on the number of loop iterations $n$.</figcaption></figure>

an abstraction of native instructions and thus do not directly map to execution ports. As WebAssembly is aimed at being portable, the translation of WebAssembly to native code depends on the browser's WebAssembly compiler and the targeted CPU. We can, however, empirically determine the port usage of these instructions for a system with PC-detector presented in Section 4.2.

### 5.2.3.2. Proof of Concept

Similar to native experiments, the sequential port contention in WebAssembly is composed of two different functions. Listing 5.3 shows the code for the *grouped* experiment, which results in a slow execution time as instructions are delayed by contention. Listing 5.4 shows the *interleaved* experiment. A low execution time indicates that the experiments were not slowed down by contention, whereas a high execution time means both instructions share at least one port.

### 5.2.3.3. Experiments

We run this experiment on the same Intel i5-8365U CPU, with `instr1 = i64.popcnt` and `instr2 = i64.or`. Figure 5.4 illustrates how $\rho$ also increases with the number of loops. On both Chrome 101 and Firefox 99, $\rho$ stabilizes around 1.1 starting from $n = 100\,000$ loop
iterations. This ratio is significantly lower than the native one. This stems from lower precision timers, as well as the stack structure of WebAssembly, where we need to add a value to the stack between instructions. Running the same experiment with `instr1 = i64.popcnt` and `instr2 = i64.ctz`, $\rho$ remains constant around 1 when varying the number of loops. We devise a framework to isolate pairs of instructions that exhibit sequential contention in Section 5.3.2.

Privacy-oriented browsers are also vulnerable to sequential port contention. With 100 000 loop iterations in Brave 1.38, we obtain $\rho = 1.1$. In Tor Browser 11.0.11, `SharedArrayBuffer` is disabled by default to prevent timing attacks. However, we can still reproduce sequential port contention with the lower-resolution timer `performance.now()` by increasing the number of loop iterations $n$ to 100 000 000. In that case, we obtain $\rho = 1.2$, but each experiment takes up to 1 s, i.e., 1000 times more than for other browsers.

## 5.3. Fingerprinting CPU Generations

In this section, we show how sequential port contention can be used to determine the CPU generation of the victim, even from inside the JavaScript sandbox.

### 5.3.1. Core Idea

The port usage of native instructions varies across generations of microarchitecture. As the number of execution units and CPU ports vary, the same instruction can emit P1 $\mu$ops on a given generation and P0 on another generation. For instance, `VPBROADCAST` emits one $\mu$op on P5 on both Haswell and Whiskey Lake microarchitectures, and `AESDEC` emits one $\mu$op on P1 on Haswell and one $\mu$op on P5 on Whiskey Lake. We computed $\rho$ on an Intel i5-8365U (Whiskey Lake) and an Intel i3-4160T (Haswell). The frequency of these CPUs can vary. However, the base frequency does not impact our experiment as we compute a ratio. We found $\rho_{WhiskeyLake} = 1$ and $\rho_{Haswell} = 1.8$. This correlates with the documented port usage. Indeed, on Whiskey Lake, both instructions emit a $\mu$op on P5. Thus, both experiments are slowed down by contention. On Haswell, the two instructions do not share a common port. Thus, the *interleaved* experiment is not slowed down by port contention, resulting in a faster execution time and a ratio $\rho > 1$.

In summary, by finding pairs of instructions that create contention for some generations but not others, we can detect on which CPU generation the code is executed. As sequential contention is visible from a browser (cf. Section 5.2.3), we also aim to discover pairs of WebAssembly instructions that exhibit sequential port contention to fingerprint the CPU generation from a web page.

### 5.3.2. Framework

The port usage of the CPU-independent WebAssembly instructions cannot be determined from the WebAssembly source code. Thus, we build a framework based on PC-detector (see Section 4.2) to automatically evaluate 458 pairs of WebAssembly instructions for contention on a specific CPU generation. Due to the nature of WebAssembly, it is highly portable and can be executed on any microarchitecture. This framework aims at isolating instruction pairs that can act as distinguishers. Such distinguishers have two major properties: 1) they exhibit different contention for different generations, and 2) they always exhibit the same contention for different CPUs of the same generation. The second property is essential, as other sources
of contention that do not depend on the generation could yield false results. Changes in the microarchitecture, e.g., floating-point units, inside a CPU generation can cause changes in behaviors, thus preventing stable fingerprinting.

Using this framework, we collect the best distinguishers to create traces for each generation. To fingerprint generations, we create a *k*-NN-based classifier and train it with results from the framework. It represents traces as points in an *l*-dimensional space, where *l* is the length of the trace, i.e., the number of distinguishers. Given a distance for each unknown execution trace, the classifier computes the *k*-nearest traces from our training dataset. A trace is classified in the most frequent class, i.e., CPU generation, in the *k*-nearest-neighbors.

To collect evaluation traces for the two sequential port contention experiments, we use a simple web page (https://fp-cpu-gen.github.io/fp-cpu-gen). It works on the latest versions of Firefox and Chrome, on Linux, macOS and Windows.

### 5.3.3. Evaluation

This section presents the results of our classifier and the different parameters used. Our classifier presents a 95% accuracy in a real-world threat model (cf. Section 5.1): a user visits a malicious website for a few seconds.

The *training set* is composed of 26 different CPUs spanning 13 different generations. It is composed of both AMD and Intel CPUs, including server and standard desktop CPUs. Table A.1 in Appendix A.3 presents the training set. The *test set* is composed of a subset of traces from the training set. It contains 13 different CPUs. The *evaluation set* is composed of traces from our website. These traces come from an uncontrolled environment since the web script cannot control or quantify the system noise. It contains 50 CPUs from 12 different generations.

#### 5.3.3.1. Training and Testing

We train our model using data from our training set. The CPUs used in our training set are not balanced in terms of CPU generations, some being more represented than others. We therefore include the same number of traces for each generation to compensate for this. Our framework finds 36 pairs of instructions acting as distinguishers between the CPU generations. We use the traces from these distinguishers to train our *k*-NN classifier. Our model shows a 96% accuracy on the test set, using *k* = 5 neighbors and majority voting.

#### 5.3.3.2. Accuracy

Figure 5.5 illustrates the results of our classifier on the evaluation set. It has a balanced accuracy of 95%. We use *k* = 5 as the number of neighbors. We gathered 10 traces and classified each one independently. The class for the experiment is determined using majority voting on the 10 classified traces. Due to the lack of microarchitectural changes between closely-related generations, some generations have the same assignment of execution ports for all instructions. As a consequence, some generations are indistinguishable using sequential port contention. We grouped such generations in the classes of our classifier. This includes the Bridge (Ivy Bridge, Sandy Bridge), Well (Haswell, Broadwell), Skylake (Skylake, Cascade Lake), and Coffee-Lake group (Coffee Lake, Whiskey Lake, Comet Lake). AMD CPUs are distinguishable from Intel ones, but the generations are grouped in the Zen group (Zen 1, Zen 2, and Zen 3).
<figure><img src="image_44.png" /><figcaption>**Figure 5.5.** – Confusion matrix for the evaluation of the *k*-NN classifier with grouped generations, *k* = 5 and majority voting on 10 traces.</figcaption></figure>

### 5.3.3.3. Execution Time

The total execution time is composed of the offline and the online execution time. The *one-time offline execution time* is composed of the framework execution time and *k*-NN training time. On average, testing all pairs of instructions in the framework takes 4 h, with a standard deviation of 1 hour and 7 minutes. Training the *k*-NN model takes 5 s on an i5-8365U. The *online execution time* is composed of the data collection time, i.e., the time taken on the website to gather the 10 traces, plus the prediction time, i.e., the execution time of predicting the class of the trace. The data collection time is the most critical factor, as it represents the duration the victim has to remain on the web page. The client sends the traces to the server that then computes the prediction, so the victim can then close the web page. Data collection takes 12 s on average, with a standard deviation of 6 s. The data collection time is faster on average on Google Chrome (10 s) compared to Firefox (13 s). On both browsers, the data collection time is in the range of the average visit time on a website. The prediction time is on average of 40 ms for 10 traces on an i5-8365U, which is negligible compared to the data collection time.

### 5.3.3.4. Impact of Majority Voting

System noise can decrease the accuracy of a single trace. In particular, the first traces gathered when launching the script are the most prone to these misclassifications. On our evaluation set, the first trace for each experiment has a 30% chance of being mispredicted, the second 12%, and then the misclassification rate goes down with repetitions to 6%. There
are multiple reasons, including the power saving policy of the system, where by default, the CPU does not use its maximum frequency to save energy, and cold caches. The first traces act as a “warm-up” of the CPU, before reaching maximum frequency. To compensate for this phenomenon, we implement majority voting. With majority voting, we gather data on *v* traces and classify the experiment based on the most common classification of these traces. This improves accuracy at the cost of a higher execution time. Without majority voting, our evaluation set shows an accuracy of 70% with a data collection time of 5 s. With *v* = 5, the accuracy increases to 86% and a data collection time of 9 s on average. Starting from *v* = 10, the accuracy peaks at 95% with a data collection time of 12 s.

5.3.3.5. Impact of the Number of Neighbors

The number of neighbors *k* is a significant factor in the classifier’s efficiency. A small number renders the classification vulnerable to noise, as a single noisy trace in the training set can lead to mispredicting many evaluation traces. A higher number tends to increase the impact of densely grouped traces, as well as increase the computation costs.

For instance, when using $k = 1$ on the evaluation dataset, the classifier accuracy is reduced to 85%. We found that $k = 5$ grants a higher accuracy for our testing and evaluation sets. Higher values of $k$ tend to yield a lower accuracy. This comes from the similarity of traces between closely-related generation groups, e.g., Skylake and Coffee-Lake groups.

5.3.3.6. Time Stability

Time stability is an essential feature, as hardware is seldomly changed by users, compared to software that has regular updates. We evaluate the stability of the classifier on an Intel i5-8365U on each major version of Firefox and Chrome, covering about a year. The generation is correctly classified from Chrome 91 (released in May 2021) to 101 and Firefox 89 (released in June 2021) to 100. Prior versions did not support WebAssembly SIMD instructions, which are part of the distinguishers in our traces. Our CPU-generation fingerprints have been stable for a year. This represents a high time stability for a browser fingerprint compared to ever-changing browser APIs and other hardware-based approaches, such as DrawnApart [LMD$^+$22], where the fingerprint may change with browsers’ major releases, resulting in a median tracking time of 28 days.

5.3.3.7. Impact of Noise on Classification

As the attacker resides inside a sandbox, they cannot know nor control noise created by other
processes or tabs. Such noise could deteriorate the performance of our classifier by creating
wrong results in the data collection process. We run the data collection process in the website
on Firefox 100 and Chrome 101 on a quadcore i5-8365U, while artificially creating noise with
the stress command. The stress threads create noise, disturbing either the sequential port
contention or the clock thread. Fewer noise sources, i.e., stress -c {1..4}, result in 93%
accuracy. That is because the OS's scheduler balances the workload, and the attack physical
core is not affected by the noise. A higher count of stress threads, i.e., 5 to 8, still yields an
accuracy of 75%.
## 5.4. Discussion

In this section, we discuss the practical use of CPU generation fingerprinting (Section 5.4.1), its limitations (Section 5.4.2), the effects of virtualization and emulation (Section 5.4.3) as well as possible mitigations (Section 5.4.4).

### 5.4.1. Practical Use of CPU-Generation Fingerprinting

The CPU-generation attribute does not have a high uniqueness, as even with a bigger training set, there are a limited number of CPU generations. The relevant feature here is its *stability*. We envision using this new fingerprinting attribute in combination with existing attributes. Its stability can be used as a linking factor to better link fingerprints to enhance tracking time [VLRR18] or use fingerprinting as a second authentication factor [LABN19]. Hardware-based fingerprinting attributes are ideal candidates, as hardware is updated less often than software, and software updates usually lead to changes in fingerprints. However, even robust hardware-based methods can break with browser internal changes [LMD$^{+22}$. We have shown that our method is robust to major version changes of browsers over a year.

### 5.4.2. Limitations

For CPU generations with major changes, sequential port contention is a highly reliable method to fingerprint the CPU generation. Such changes are found on Intel CPUs between the Bridge (e.g., Sandy Bridge, Ivy Bridge), the Well (e.g., Haswell, Broadwell), and the Lake (e.g., Skylake, Coffee Lake, Whiskey Lake, Comet Lake) microarchitectures. However, starting with the Lake microarchitecture, changes between new versions are smaller, making it harder to detect the specific microarchitecture. For example, Coffee Lake, Whiskey Lake, and Comet Lake are based on the nearly identical designs of the execution units. Only Ice Lake introduced changes again, specifically with an additional store unit [Wikc] which subsequently led to changes in the port assignment for several instructions. Hence, the detection of the CPU generation cannot differentiate names for essentially the same generation.

Due to lack of access, some generations are not included in the training set, e.g., Nehalem or Ice Lake. Thus, they cannot be correctly predicted by our proof-of-concept model and are not included in the evaluation set. This could be easily corrected by extending our study and running the framework on a larger range of CPUs. CPUs with significant microarchitectural changes are potentially highly identifiable, e.g., Ice Lake with its addition of new store units.

### 5.4.3. Virtualization and Emulation

Sequential port contention is not limited to bare-metal code execution but also works from inside virtual machines if the guest is virtualized and not emulated.

#### 5.4.3.1. Virtualization

As all involved instructions are unprivileged and not emulated by the hypervisor, there is no difference in the execution stream to a bare-metal execution. Hence, the measured effects are also the same. Moreover, as only a single CPU core is required, the scheduler of the hypervisor does not affect the contention. We verify on Ubuntu 20.04 (kernel 5.13) with QEMU KVM
4.2.1 that we measure the same effect of sequential port contention within a virtual machine (Ubuntu 20.04, kernel 5.4).

### 5.4.3.2. Emulation

Sequential port contention requires that the specifically-crafted instruction stream is executed without modifications on the CPU. For emulation, this is not the case if instructions are interpreted or translated just in time with potential additional instructions in the instruction stream. For example, when running the guest operating system (Ubuntu 20.04, kernel 5.4) in QEMU 4.2.1 with full system emulation (TCG), we are unable to measure the effect of sequential port contention. In this setup, the instruction stream with and without contention have the same execution time.

Based on this observation, sequential port contention can detect emulation, e.g., if the code is analyzed via a malware-analysis emulator [Kru14, BBR16]. Hence, sequential port contention provides malware with another trick to detect such environments. As discussed in Section 5.4.4, mitigating sequential port contention is difficult. Likewise, sequential port contention is likely infeasible to emulate, making it difficult to prevent malware from detecting the presence of an emulator.

## 5.4.4. Mitigation

Sequential port contention does not require any operating-system interface or particular setup, such as SMT (cf. Section 5.1). Hence, this side channel cannot be prevented on the operating-system level but potentially on the browser level. Similar to previous work on microarchitectural attack detection [GMWM16, Pay16b, IES18, SBK$^{+21}$], we show that this side channel can also be detected using hardware performance counters.

### 5.4.4.1. Browser Mitigation

Existing browser mitigations against side-channel attacks are only effective against sequential port contention if they block access to timing sources [KS16, MCS$^{+16}$, SLG18a] or entirely prevent the execution of active content [Gio17, Ray17]. However, while effective, these methods also impact the usability of all websites.

The browser can interleave the generated instruction stream with memory fences, effectively preventing out-of-order execution. Theoretically, to fully mitigate the side channel, a browser has to emit a memory fence after every assembly instruction. However, this leads to unacceptable performance penalties, as it effectively prevents out-of-order execution while additionally adding the overhead of the fence (multiple cycles) after every instruction. A trade-off between the number of inserted fences and signal strength might be feasible, though. We leave an evaluation to future work.

Alternatively, the browser can reorder the instruction stream while keeping its functionality. Such reordering can be part of existing compiler optimizations, such as loop optimizations. Software-diversification approaches have also been shown as mitigation against side-channel attacks [CHB$^{+15}$, RLT15]. As the code required for sequential port contention requires precise control over the instruction sequence, any diversification likely breaks the side channel. We leave the evaluation of software-diversification methods applied by the browser to future work.
<figure><img src="image_45.png" /><figcaption>**Figure 5.6.** – Ratio of backend-bound to misprediction-bound execution when running the JetStream JavaScript and WebAssembly benchmark (left), nothing (middle), and our website for generating the browser fingerprint (right) in Firefox 100.0.2.</figcaption></figure>

### 5.4.4.2. Detection via Performance Counters

To detect sequential port contention, we propose a metric based on the topdown bottleneck decomposition [Yas14]. Previous work focused mostly on cache-based performance counters for detecting microarchitectural attacks [GMWM16, Pay16b, IES18, SBK$^{+}$21]. However, for sequential port contention, the cache activity is indistinguishable from typical workloads. The bottleneck exploited in sequential port contention is the execution unit in the backend. As the instruction stream is entirely linear, we use the ratio of backend-bound execution divided by misprediction-bound execution. Hence, the more often the bottleneck is in the backend, combined with next to no mispredictions, the higher the likelihood that the monitored snippet uses sequential port contention.

Figure 5.6 shows the evaluation of this metric in Firefox while running the JetStream JavaScript and WebAssembly benchmark (left), nothing (middle), and our website for generating the browser fingerprint (right). Our tests do not show any workload where this metric is as high as for sequential port contention, allowing detection of this side channel using a simple threshold (dashed line).

## 5.5. Conclusion

We introduced sequential port contention, a new side channel based on port contention that does not require SMT. This extends the threat surface of this side channel to new systems, and circumvents popular countermeasures. We proposed a WebAssembly framework to automatically determine instruction sequences creating sequential port contention on different systems and CPU vendors. We demonstrated that an attacker can exploit sequential port contention to determine the CPU generation of a victim from the browser within 12s. This information is highly stable, and the attack works correctly even under heavy system noise. This new side-channel is privacy-threatening, as it is hard to mitigate and can be used for improving the stability of fingerprints. This fingerprint shows how web-based microarchitectural side channels can have an impact on the privacy of the users by reducing the anonymity of the web (Q3).
Conclusion and Perspectives 6

This thesis aimed to explore in more depth the threat surface of web-based microarchitectural side channels. To this end, we proposed three major contributions:

1. A systematic study of JavaScript timers and timing attacks (Chapter 3).

2. The implementation of port contention in the browser (Chapter 4).

3. A new evolution of this side channel, and the study of its impact on privacy (Chapter 5).

With these contributions, we aimed to explore the research questions Q1, Q2, and Q3.

**Q1: What is the current landscape of browser-based attacks and countermeasures?** Browsers are constantly evolving pieces of software, and the security countermeasures change with every release. This makes it particularly hard to evaluate the state of browsers' security to microarchitectural side channels. Chapter 3 was primarily focused on this question, as it proposes a classification of timing attacks, countermeasures, as well as tools to evaluate timers in JavaScript automatically.

Furthermore, we also believe that a single, fixed-in-time study is insufficient to make durable contributions to browser security, as attacker code can be executed on different browsers of different versions, on different OSs sitting on different hardware. To that extent, we provided automated evaluation frameworks for our proofs-of-concepts, in order to make them as portable and durable as possible. PC-detector (Chapter 4) allows detecting the contention caused by WebAssembly instructions regardless of the browser versions (as long as WebAssembly is supported). Our sequential port contention framework (Chapter 5) can evaluate instructions even on non-x86 processors, and use it to automatically detect the generation of the processor.

**Q2: Are other components vulnerable to side channels from the JavaScript sandbox?** Cache attacks have probably been the literature's most explored microarchitectural side channels. However, new components are exploited from the JavaScript sandbox to widen the threat surface of web-based side channels. Generally, these side channels are first implemented in native code, as it offers a more fine-grained control over the microarchitecture.

This is the case with web-based port contention. Aldaya et al. [ABuH$^+19$] theorized native CPU port contention, and in Chapter 4 we extended it to the JavaScript sandbox. This contribution shows that there are still threatening side channels that could be implemented in JavaScript. In particular, JavaScript port contention shows that SMT side channels can be implemented in JavaScript as an attacker can achieve core co-residency with a victim, even without core control.
Sequential port contention, defined in Chapter 5, was directly designed to run in the JavaScript sandbox. It allows to extend port contention to new systems, where SMT attacks are unavailable. With it, we show how a change in the paradigm of a side channel, here from thread-level parallelism to instruction-level parallelism, can offer a new threat surface to already discovered side channels.

**Q3: What can an attacker extract from these side channels?** This is probably the most pragmatic of this manuscript's research questions, as it aims to quantify the impact of microarchitectural side channels in browsers. With this thesis, we tried to exemplify how flexible these attacks are, and that they can apply to many different security fields.

Microarchitectural side channels have often been applied to attacks against cryptographic algorithms, even in the JavaScript sandbox [GPTY18]. We developed the threat of web port contention on this type of attack in our artificial example in Section 4.3.

However, we believe that side channels, and in particular port contention, can also have heavy implications on web users' privacy. This is first the case with the port-contention covert channel explored in Section 4.4. This channel completely breaks the isolation barriers brought by the sandbox and site isolation, as it allows an attacker in the sandbox to communicate with the outside. It could be used to extract native information to the sandbox, to leak Tor Browser users' IP addresses, or to exchange authentication cookies between two different tabs. We also explored port contention's impact on another privacy aspect: browser fingerprinting. In Chapter 5, we showed how an attacker could leverage sequential port contention to identify the CPU generation of the victim, allowing to complement software-based fingerprints and grant more extended time stability.

## Perspectives and Future Work

This manuscript has provided partial answers to the research questions introduced in the introduction. However, if these contributions have not provided definitive answers to the open questions, they have brought even more perspectives for future work.

**Of new side channels and new threats** The first lead for future work would be to explore the implementation of new side channels to web browsers. This research is critical as each microarchitectural component can be exploited differently, bringing different threats and ways to circumvent already existing mitigations. Efficient countermeasures cannot be implemented without a clear view of the attack surface.

With the resolution of JavaScript-specific challenges, e.g., lack of high-resolution timers or core-control, the exploitation of new microarchitectural components is more accessible. In particular, on-core resources already exploited natively, e.g., the TLB or μop cache, could be exploited from the browser to widen the attack surface.

**Hardware fingerprinting** We briefly explored how microarchitectural side channels could be used for fingerprinting. This direction is highly interesting as fingerprinting can be seen as a specific type of side channel, where the attacker collects hardware information instead of secrets.

Hardware fingerprints are currently starting to be explored [LMD+22] as it offers different properties than software attributes. In particular, hardware attributes are more stable, as
users do not change their CPU monthly. This stability permits to link less stable software fingerprints in time. Hardware attributes are also less spoofable because they depend on active fingerprinting: instead of reading an attribute that the user can modify, the information results from actual computations in the browser. Although a user can still modify these values to prevent fingerprinting, it is harder to set the specific fingerprint of another system, thus preventing spoofing.

Hardware fingerprints can be decomposed in two different directions based on the type of attributes. The first direction would be to use precise information about the hardware to complement software fingerprinting. This is the same direction we explored with sequential port contention by finding the generation of the processor. Using microarchitectural side channels, an attacker could detect the CPU or GPU model, vendor, or attributes about microarchitectural properties, e.g., cache size or associativity, or the number of CPU cores. All this information does not create a unique fingerprint as many users have the same processors, but is stable information about a set of discrete attributes. The second direction would be to create more unique fingerprints based on hardware imperfections. This is already the direction explored by Sánchez-Rola et al. [SSB18] and Laor et al. [LMD+22]. By leveraging minor differences in execution time or results of non-deterministic computations, a tracker could gather unique information about a user. This type of fingerprint is often less stable than discrete attributes, as other phenomena, such as software or system noise, can impact the fingerprint.

This new paradigm in fingerprinting broadens the scope of applications for fingerprinting. In particular, its stability and relative resistance to spoofing could help develop fingerprint as a multi-factor authentication token. However, its implications on tracking applications are also heavy, as it eases long-lasting fingerprints, allowing a third party to track anonymous users over the web.

**Browser-based countermeasures: a deadend?** Web-based microarchitectural attacks stand at a paradoxical crossroads: they are low-level attacks exploited from a very high-level sandbox. Logically, they can be mitigated at several levels. Whereas microarchitectural countermeasures are currently the most studied as they also apply to native attacks, they are hard to implement as it is not possible to patch hardware.

Browser-based countermeasures can be deployed rapidly after the discovery of attacks. However, the current state of browser-based countermeasures is unclear. Timing-based countermeasures were a popular paradigm after the discovery of the first microarchitectural side channels in the browser, but are now abandoned as they are often too penalizing for web developers. The current paradigm for browser-based countermeasures is based on isolation, specifically targetting same address-space attacks, such as Spectre-PHT. As presented in Chapter 3, this new direction is insufficient, as it does not prevent most timing attacks. However, browser vendors seem to consider microarchitectural countermeasures as a dead-end, as implementing hardware-level countermeasures at an application level is often too costly.

A new approach we would like to explore in future work is based on detecting attacks instead of preventing them. In particular, approaches similar to performance-counters-based approaches [CSY16, AYQ+16, PIO19, LG18, For18, WSS+20] could be efficient to protect the web. In a third-party attack, the browser could detect untrusted processes and monitor their behavior to detect suspicious patterns before the attack is over. This approach could be based on reading performance counters in the browser process, or implementing new
policies on suspicious array accesses. Although this type of detection is based on heuristics, machine-learning approaches could provide the genericity needed to detect the wide variety of web-based microarchitectural side channels, and could be trained and deployed rapidly.

**Automation and systematization** Security research resembles a cat-and-mouse game: new attacks motivate new countermeasures, which in turn force the creation of newer attacks. The field of web-based microarchitectural channels is not an exception and is rapidly evolving.

In particular, each new side channel requires reverse-engineering the behavior of a microarchitectural component, finding a vulnerability, exploiting it natively then modifying it so it can be exploited from the JavaScript sandbox. This workflow requires extensive engineering work, often highly repetitive from one attack to another. We believe that at least some side channels could be detected automatically by an automated framework, comparable to the native ABSynthe [GGK+20] or Osiris [WIN+21]. These frameworks rely on a theoretical systematization of side channels to evaluate random pairs of instructions for data leakage. The same idea could be done on JavaScript and WebAssembly instructions. PC-detector is a preliminary implementation of this idea, but is limited to detecting on-core contention between pairs of instructions. A more complex implementation of a black-box side-channel detector could provide the literature with a more complete picture of sources of leakages in the sandbox. Another future work on automated discovery of side channels would be implementing the detector at the application level. Instead of evaluating WebAssembly or JavaScript instructions, evaluating the output bytecode produced by JavaScript engines could bring a more deterministic understanding of how the sandbox interacts with the microarchitecture.

We believe this systematic approach is necessary to produce effective and generic countermeasures instead of specific patches for a particular type of attack.
Appendices A

A.1. Custom RDTSC implementation

We modified the following files in order to implement rdtsc:

A.1.1. Firefox 81

moshellcentral / dom / performance / Performance.cpp

std::uint64_t Performance::Rdtsc() { unsigned int lo,hi; __asm__ __volatile__ ("mfence"); __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); __asm__ __volatile__ ("mfence"); return ((std::uint64_t)hi << 32) | lo; }

mosaiccentral / dom / performance / Performance.h

std::uint64_t Rdtsc();

mosaiccentral / dom / webidl / Performance.webidl

typedef double uint64_t;

A.1.2. Chromium 84

chromium / src / third party / blink / renderer / core / timing / performance.cc

std::uint64_t Performance::rdtsc() { unsigned int lo,hi; __asm__ __volatile__ ("mfence"); __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); __asm__ __volatile__ ("mfence"); return ((std::uint64_t)hi << 32) | lo; }

chromium / src / third party / blink / renderer / core / timing / performance.h

std::uint64_t rdtsc();
chromium/src/third party/blink/renderer/core/timing/dom_high_res_time _ stamp.idl

typedef double uint64_t;

chromium/src/third party/blink/renderer/core/timing/performance.idl

uint64_t rdtsc();
## A.2. Port Contention on Other WebAssembly Instructions

Figures A.1a to A.1c show port contention on the following WebAssembly instructions: `f64.floor`, the pair `f32.convert_i32_u` and `i32.trunc_f32_u`, and `i64.rem_u`. We can clearly distinguish the three outcomes of a PC-detector usage:

* Figure A.1a illustrates an instruction that do not cause contention. The P1 and P5 distributions have a similar mean and standard deviation, making them difficult to distinguish. However, they are still distinguishable from the control experiment.

* Figure A.1c illustrates a pair of instructions causing contention on P5. The distribution P5 has a higher mean than P1 and the control experiment.

* Figure A.1b illustrates an instruction causing contention on P1. The distribution P1 has a higher mean than P5 and the control experiment.

<figure><img src="image_46.png" /><figcaption>(a) P1 contention experiment on `f64.floor` for (b) P1 contention experiment on `i64.rem_u` for 1000000 instructions.</figcaption></figure>

<figure><img src="image_47.png" /><figcaption>(c) P5 contention experiment on paired `f32.convert_i32_u` and `i32.trunc_f32_u` for 1000000 instructions.</figcaption></figure>
## A.3. Training set

Table A.1 presents the different processors used to train the model presented in Section 5.3.2.

<table><caption>Table A.1. – CPUs used in our training set</caption><thead><tr><td>CPU</td><td>Vendor</td><td>Generation</td></tr></thead><tbody><tr><td>Xeon X5670</td><td>Intel</td><td>Westmere</td></tr><tr><td>Xeon E5-2620</td><td>Intel</td><td>Sandy Bridge</td></tr><tr><td>Xeon E5-2630</td><td>Intel</td><td>Sandy Bridge</td></tr><tr><td>Xeon E5-2630L</td><td>Intel</td><td>Sandy Bridge</td></tr><tr><td>Xeon E5-2650 0</td><td>Intel</td><td>Sandy Bridge</td></tr><tr><td>Xeon E5-2660 0</td><td>Intel</td><td>Sandy Bridge</td></tr><tr><td>Core i5-2520M</td><td>Intel</td><td>Sandy Bridge</td></tr><tr><td>Xeon E5-2660 v2</td><td>Intel</td><td>Ivy Bridge</td></tr><tr><td>Xeon E5-2630 v3</td><td>Intel</td><td>Haswell</td></tr><tr><td>Core i3-4160T</td><td>Intel</td><td>Haswell</td></tr><tr><td>Xeon E5-2620 v4</td><td>Intel</td><td>Broadwell</td></tr><tr><td>Xeon E5-2630 v4</td><td>Intel</td><td>Broadwell</td></tr><tr><td>Xeon E5-2680 v4</td><td>Intel</td><td>Broadwell</td></tr><tr><td>Core i3-5010U</td><td>Intel</td><td>Broadwell</td></tr><tr><td>Xeon Gold 6126</td><td>Intel</td><td>Skylake</td></tr><tr><td>Xeon Gold 6130</td><td>Intel</td><td>Skylake</td></tr><tr><td>Core i9-9980HK</td><td>Intel</td><td>Coffee Lake</td></tr><tr><td>Core i5-8365U</td><td>Intel</td><td>Whiskey Lake</td></tr><tr><td>Xeon Gold 5218</td><td>Intel</td><td>Cascade Lake SP</td></tr><tr><td>Xeon Gold 5220</td><td>Intel</td><td>Cascade Lake SP</td></tr><tr><td>Core i7-10510U</td><td>Intel</td><td>Comet Lake</td></tr><tr><td>Core i7-10710U</td><td>Intel</td><td>Comet Lake</td></tr><tr><td>Core i5-1135G7</td><td>Intel</td><td>Tiger Lake</td></tr><tr><td>EPYC 7301</td><td>AMD</td><td>Zen</td></tr><tr><td>Ryzen 5 2500U</td><td>AMD</td><td>Zen</td></tr><tr><td>Ryzen 9 5900HX</td><td>AMD</td><td>Zen 3</td></tr></tbody></table>
Bibliography A

[AAG17] Zirak Allaf, Mo Adda, and Alexander Gegov. A comparison study on flush+ reload and prime+ probe attacks on aes using machine learning approaches. In *UK Workshop on Computational Intelligence*, pages 203–213. Springer, 2017.

[ABG10] Onur Aciiçmez, Billy Bob Brumley, and Philipp Grabher. New results on instruction cache attacks. In *CHES*, volume 6225 of *Lecture Notes in Computer Science*, pages 110–124. Springer, 2010.

[ABuH<sup>+</sup>19] Alejandro Cabrera Aldaya, Billy Bob Brumley, Sohaib ul Hassan, Cesar Pereida García, and Nicola Tuveri. Port contention for fun and profit. In *S&P*, 2019.

[AEE<sup>+</sup>14] Gunes Acar, Christian Eubank, Steven Englehardt, Marc Juárez, Arvind Narayanan, and Claudia Díaz. The web never forgets: Persistent tracking mechanisms in the wild. In *CCS*, 2014.

[AES15] Gorka Irazoqui Apecechea, Thomas Eisenbarth, and Berk Sunar. S$\$a: A shared cache attack that works across cores and defies VM sandboxing - and its application to AES. In *IEEE Symposium on Security and Privacy*, pages 591–604. IEEE Computer Society, 2015.

[AIES15] Gorka Irazoqui Apecechea, Mehmet Sinan Inci, Thomas Eisenbarth, and Berk Sunar. Lucky 13 strikes back. In *AsiaCCS*, pages 85–96. ACM, 2015.

[AJ] Anne van Kesteren Artur Janc, Charlie Reis. Coop and coep explained. https://docs.google.com/document/d/1zDlfvfTJ_9e8Jdc8ehuV4zMEu9ySMCiTGMS9y0GU92k/edit.
Accessed: 2022-10-05.

[AKM<sup>+</sup>15] Marc Andrysco, David Kohlbrenner, Keaton Mowery, Ranjit Jhala, Sorin Lerner, and Hovav Shacham. On subnormal floating point and abnormal timing. In *S&P*, 2015.

[AKS07] Onur Aciiçmez, Çetin Kaya Koç, and Jean-Pierre Seifert. Predicting secret keys via branch prediction. In *CT-RSA*, volume 4377 of *Lecture Notes in Computer Science*, pages 225–242. Springer, 2007.

[ANT<sup>+</sup>20] Diego F. Aranha, Felipe Rodrigues Novaes, Akira Takahashi, Mehdi Tibouchi, and Yuval Yarom. Ladderleak: Breaking ECDSA with less than one bit of nonce leakage. In *CCS*, pages 225–242. ACM, 2020.

[AR] Andreas Abel and Jan Reineke. Tzcnt uops.info page. https://uops.info/html-instr/TZCNT_R16_R16.html. Accessed: 2021-11-11.
[AR19] Andreas Abel and Jan Reineke. uops.info: Characterizing latency, throughput, and port usage of instructions on intel microarchitectures. In *ASPLOS*, pages 673–686. ACM, 2019.

[AYQ$^{+}$16] Zelalem Birhanu Aweke, Salessawi Ferede Yitbarek, Rui Qiao, Reetuparna Das, Matthew Hicks, Yossi Oren, and Todd M. Austin. ANVIL: software-based protection against next-generation rowhammer attacks. In *ASPLOS*, pages 743–755. ACM, 2016.

[BB05] David Brumley and Dan Boneh. Remote timing attacks are practical. *Computer Networks*, 2005.

[BBR16] Michael Brengel, Michael Backes, and Christian Rossow. Detecting hardware-assisted virtualization. In *DIMVA*, volume 9721 of *Lecture Notes in Computer Science*, pages 207–227. Springer, 2016.

[BEPW10] Andrey Bogdanov, Thomas Eisenbarth, Christof Paar, and Malte Wienecke. Differential cache-collision timing attacks on AES with applications to embedded cpus. In *CT-RSA*, volume 5985 of *Lecture Notes in Computer Science*, pages 235–251. Springer, 2010.

[Ber61] Jay M. Berger. A note on error detection codes for asymmetric channels. *Inf. Control.*, 4(1):68–73, 1961.

[Ber05] Daniel Bernstein. Cache-timing attacks on aes. 2005.

[BFS20] Daniel De Almeida Braga, Pierre-Alain Fouque, and Mohamed Sabt. Drag-onblood is still leaking: Practical cache-based side-channel in the wild. In *ACSAC*, pages 291–303. ACM, 2020.

[BFS21] Daniel De Almeida Braga, Pierre-Alain Fouque, and Mohamed Sabt. PARASITE: password recovery attack against srp implementations in the wild. In *CCS*, pages 2497–2512. ACM, 2021.

[BH09] Billy Bob Brumley and Risto M. Hakala. Cache-timing template attacks. In *ASIACRYPT*, volume 5912 of *Lecture Notes in Computer Science*, pages 667–684. Springer, 2009.

[BM18] Sarani Bhattacharya and Debdeep Mukhopadhyay. *Advanced Fault Attacks in Software: Exploiting the Rowhammer Bug*, pages 111–135. 2018.

[BMD$^{+}$17] Ferdinand Brasser, Urs Müller, Alexandra Dmitrienko, Kari Kostiainen, Srdjan Capkun, and Ahmad-Reza Sadeghi. Software grand exposure: SGX cache attacks are practical. *CoRR*, abs/1702.07521, 2017.

[BMW$^{+}$18] Jo Van Bulck, Marina Minkin, Ofir Weisse, Daniel Genkin, Baris Kasikci, Frank Piessens, Mark Silberstein, Thomas F. Wenisch, Yuval Yarom, and Raoul Strackx. Foreshadow: Extracting the keys to the intel SGX kingdom with transient out-of-order execution. In *USENIX Security Symposium*, pages 991–1008. USENIX Association, 2018.
[BRBG16] Erik Bosman, Kaveh Razavi, Herbert Bos, and Cristiano Giuffrida. Dedup est machina: Memory deduplication as an advanced exploitation vector. In *IEEE Symposium on Security and Privacy*, pages 987–1004. IEEE Computer Society, 2016.

[BRPG15] Antonio Barresi, Kaveh Razavi, Mathias Payer, and Thomas R. Gross. CAIN: silently breaking ASLR in the cloud. In *WOOT*. USENIX Association, 2015.

[BSN$^{+}$19] Atri Bhattacharyya, Alexandra Sandulescu, Matthias Neugschwandtner, Alessandro Sorniotti, Babak Falsafi, Mathias Payer, and Anil Kurmus. Smotherspectre: Exploiting speculative execution through port contention. In *CCS*, 2019.

[Bug18a] Bugzilla. Reduce timer resolution to 2ms. https://bugzilla.mozilla.org/show_bug.cgi?id=1435296, feb 2018.

[Bug18b] Bugzilla. Set timer resolution to 1ms with jitter. https://bugzilla.mozilla.org/show_bug.cgi?id=1451790, apr 2018.

[Bug18c] Bugzilla. Unanticipated security/usability degradation from precision-lowering of performance.now() to 2ms. https://bugzilla.mozilla.org/show_bug.cgi?id=1440863, feb 2018.

[Bug20] Bugzilla. Check crossoriginisolated for all nsrfpservice::reducetimeprecision* callers. https://bugzilla.mozilla.org/show_bug.cgi?id=1586761, 02 2020.

[BvdPSY14] Naomi Benger, Joop van de Pol, Nigel P. Smart, and Yuval Yarom. "ooh aah... just a little bit": A small amount of side channel can go a long way. In *CHES*, volume 8731 of *Lecture Notes in Computer Science*, pages 75–92. Springer, 2014.

[CBS$^{+}$19] Claudio Canella, Jo Van Bulck, Michael Schwarz, Moritz Lipp, Benjamin von Berg, Philipp Ortner, Frank Piessens, Dmitry Evtyushkin, and Daniel Gruss. A systematic evaluation of transient execution attacks and defenses. In *USENIX Security Symposium*, pages 249–266. USENIX Association, 2019.

[CCLW17] Yinzhi Cao, Zhanhao Chen, Song Li, and Shujiang Wu. Deterministic browser. In *CCS*, pages 163–178. ACM, 2017.

[CEQZ06] Feng Cao, Martin Ester, Weining Qian, and Aoying Zhou. Density-based clustering over an evolving data stream with noise. In *SDM*, pages 328–339. SIAM, 2006.

[CGG$^{+}$19] Claudio Canella, Daniel Genkin, Lukas Giner, Daniel Gruss, Moritz Lipp, Marina Minkin, Daniel Moghimi, Frank Piessens, Michael Schwarz, Berk Sunar, Jo Van Bulck, and Yuval Yarom. Fallout: Leaking Data on Meltdown-resistant CPUs. In *CCS*, 2019.

[CHB$^{+}$15] Stephen Crane, Andrei Homescu, Stefan Brunthaler, Per Larsen, and Michael Franz. Thwarting cache side-channel attacks through dynamic software diversity. In *NDSS*, 2015.
[Chr17a] Chromium. Issue 611420: WebAccessibleResources take too long to make a decision about loading if the extension is installed. https://bugs.chromium.org/p/chromium/issues/detail?id=611420, 2017.

[Chr17b] Chromium. Issue 709464: Detecting the presence of extensions through timing attacks (including Incognito) - Chromium bug tracker. https://bugs.chromium.org/p/chromium/issues/detail?id=709464, 2017.

[Cona] MDN Contributors. Cross-origin-embedder-policy. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy. Accessed: 2021-19-11.

[Conb] MDN Contributors. Cross-origin-opener-policy. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Domain-Opener-Policy. Accessed: 2021-19-11.

[Conc] MDN Contributors. Cross-origin resource policy. https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Domain-Resource-Policy_(CORP).

[Cond] MDN Contributors. Date.now() api. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now. Accessed: 2022-06-30.

[Cone] MDN Contributors. Navigator.hardwareconcurrency. https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardware Concurrency. Accessed: 2021-19-11.

[Conf] MDN Contributors. Planned changes to shared memory. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer/Planned changes. Accessed: 2022-07-26.

[Cong] MDN Contributors. Same-origin-policy. https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy. Accessed: 2020-10-06.

[Conh] MDN Contributors. Subresource integrity. https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity.

[Coni] MDN Contributors. Window.requestanimationframe() api. https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame. Accessed: 2022-06-30.

[Conj] MDN Contributors. Window.settimeout() api. https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout. Accessed: 2022-06-30.

[Con20a] MDN Contributors. Performance api. https://developer.mozilla.org/en-US/docs/Web/API/Performance_API, October 2020.

[Con20b] MDN Contributors. Performance.now() api. https://developer.mozilla.org/fr/docs/Web/API/Performance/now, Sept 2020.

[CSH+20] Claudio Canella, Michael Schwarz, Martin Haubenwallner, Martin Schwarzl, and Daniel Gruss. KASLR: break it, fix it, repeat. In AsiaCCS, pages 481–493. ACM, 2020.
[CSY16] Marco Chiappetta, Erkay Savas, and Cemal Yilmaz. Real time detection of cache-based side-channel attacks using hardware performance counters. *Appl. Soft Comput.*, 2016.

[Dam06] Peter Damaschke. Threshold group testing. In *GTIT-C*, volume 4123 of *Lecture Notes in Computer Science*, pages 707–718. Springer, 2006.

[DFS20] Ghada Dessouky, Tommaso Frassetto, and Ahmad-Reza Sadeghi. Hybcache: Hybrid side-channel-resilient caches for trusted execution environments. In *USENIX Security Symposium*, 2020.

[DJL$^{+12}$] Leonid Domnitser, Aamer Jaleel, Jason Loew, Nael B. Abu-Ghazaleh, and Dmitry Ponomarev. Non-monopolizable caches: Low-complexity mitigation of cache side channel attacks. *ACM Trans. Archit. Code Optim.*, 8(4):35:1–35:21, 2012.

[DKPT17] Craig Disselkoen, David Kohlbrenner, Leo Porter, and Dean M. Tullsen. Prime+abort: A timer-free high-precision L3 cache attack using intel TSX. In *USENIX Security Symposium*, pages 51–67. USENIX Association, 2017.

[Eck10] Peter Eckersley. How unique is your web browser? In *Privacy Enhancing Technologies*, 2010.

[ECMa] ECMA. Atomics.add - standard. https://www.ecma-international.org/ecma-262/#sec-atomics.add. Accessed: 2020-09-30.

[ECMb] ECMA. Sharedarraybuffer objects. https://tc39.es/ecma262/#sec-sharedarraybuffer-objects. Accessed: 2022-06-30.

[ECMc] ECMA. Standard ecma-262. https://tc39.es/ecma262/. Accessed: 2022-07-21.

[ECMd] ECMA. Standard ecma-262. https://tc39.es/ecma402/. Accessed: 2022-07-21.

[EP16] Dmitry Evtyushkin and Dmitry V. Ponomarev. Covert channels through random number generator: Mechanisms, capacity estimation and mitigations. In *CCS*, pages 843–857. ACM, 2016.

[EPA16] Dmitry Evtyushkin, Dmitry V. Ponomarev, and Nael B. Abu-Ghazaleh. Jump over ASLR: attacking branch predictors to bypass ASLR. In *MICRO*, pages 40:1–40:13. IEEE Computer Society, 2016.

[ERAP18] Dmitry Evtyushkin, Ryan Riley, Nael B. Abu-Ghazaleh, and Dmitry Ponomarev. Branchscope: A new side-channel attack on directional branch predictor. In *ASPLOS*, pages 693–707. ACM, 2018.

[F$^{+11}$] Agner Fog et al. Instruction tables: Lists of instruction latencies, throughputs and micro-operation breakdowns for intel, amd and via cpus. *Copenhagen University College of Engineering*, 93:110, 2011.

[FE15] David Fifield and Serge Egelman. Fingerprinting web users through font metrics. In *Financial Cryptography*, volume 8975 of *Lecture Notes in Computer Science*, pages 107–124. Springer, 2015.
[Fog] Andreas Fogh. Covert shotgun. https://cyber.wtf/2016/09/27/covert-shotgun/. Accessed: 2022-07-04.

[For18] James Christopher Foreman. A survey of cyber security countermeasures using hardware performance counters. CoRR, abs/1807.10868, 2018.

[GBK11] David Gullasch, Endre Bangerter, and Stephan Krenn. Cache games-bringing access-based cache attacks on aes to practice. In 2011 IEEE Symposium on Security and Privacy, pages 490-505. IEEE, 2011.

[GBM15] Daniel Gruss, David Bidner, and Stefan Mangard. Practical memory deduplication attacks in sandboxed javascript. In ESORICS (1), volume 9326 of Lecture Notes in Computer Science, pages 108-122. Springer, 2015.

[GGK+20] Ben Gras, Cristiano Giuffrida, Michael Kurth, Herbert Bos, and Kaveh Razavi. Absynthe: Automatic blackbox side-channel synthesis on commodity microarchitectures. In NDSS, 2020.

[GIA+15] Berk Gülmezoglu, Mehmet Sinan Inci, Gorka Irazoqui Apecechea, Thomas Eisenbarth, and Berk Sunar. A faster and more realistic flush+reload attack on AES. In COSADE, volume 9064 of Lecture Notes in Computer Science, pages 111-126. Springer, 2015.

[Gio17] Giorgio Maone. NoScript - JavaScript/Java/Flash blocker for a safer Firefox experience!, July 2017.

[GMM16] Daniel Gruss, Clémentine Maurice, and Stefan Mangard. Rowhammer.js: A remote software-induced fault attack in javascript. In DIMVA, volume 9721 of Lecture Notes in Computer Science, pages 300-321. Springer, 2016.

[GMWM16] Daniel Gruss, Clémentine Maurice, Klaus Wagner, and Stefan Mangard. Flush+flush: A fast and stealthy cache attack. In DIMVA, volume 9721 of Lecture Notes in Computer Science, pages 279-299. Springer, 2016.

[Gooa] Google. Google end to end library. https://github.com/google/end-to-end/. Accessed: 2022-07-26.

[Goob] Google. Product status: Microarchitectural data sampling (mds). https://support.google.com/faqs/answer/9330250?hl=en. Accessed: 2021-19-11.

[Gooc] Google. Sharedarraybuffer updates in android chrome 88 and desktop chrome 92 - chrome developers. https://developer.chrome.com/blog/enabling-shared-array-buffer/. Accessed: 2022-07-26.

[Good] Google. time_clamper.cpp. https://source.chromium.org/chromium/chromium/src/+/master:third Crushtimerake sure that the time clamped. Accessed: 2020-10-12.

[Gooe] Google. V8 javascript engine. https://v8.dev/. Accessed: 2022-07-21.

[Goof] Google. v8/bytecodes.h. https://github.com/v8/v8/blob/master/src/interpreter/bytecodes.h. Accessed: 2022-07-26.
[GPTY18] Daniel Genkin, Lev Pachmanov, Eran Tromer, and Yuval Yarom. Drive-by key-extraction cache attacks from portable code. In *ACNS*, 2018.

[GRB$^{+}$17] Ben Gras, Kaveh Razavi, Erik Bosman, Herbert Bos, and Cristiano Giuffrida. ASLR on the line: Practical cache attacks on the MMU. In *NDSS*. The Internet Society, 2017.

[GRBG18] Ben Gras, Kaveh Razavi, Herbert Bos, and Cristiano Giuffrida. Translation leak-aside buffer: Defeating cache side-channel protections with TLB attacks. In *USENIX*, 2018.

[Gri] Ilya Grigorik. High resolution time level 2. https://www.w3.org/TR/hr-time-2/. Accessed: 2022-06-30.

[Gro] W3C Community Group. Index of instructions webassembly 2.0. https://webassembly.github.io/spec/core/appendix/index-instructions.html. Accessed: 2022-05-20.

[GSM15] Daniel Gruss, Raphael Spreitzer, and Stefan Mangard. Cache template attacks: Automating attacks on inclusive last-level caches. In *USENIX Security Symposium*, pages 897–912. USENIX Association, 2015.

[GST14] Daniel Genkin, Adi Shamir, and Eran Tromer. RSA key extraction via low-bandwidth acoustic cryptanalysis. In *CRYPTO (1)*, volume 8616 of *Lecture Notes in Computer Science*, pages 444–461. Springer, 2014.

[GZ13] Michael Misiu Godfrey and Mohammad Zulkernine. A server-side solution to cache-based side-channel attacks in the cloud. In *IEEE CLOUD*, pages 163–170. IEEE Computer Society, 2013.

[Ham50] Richard W Hamming. Error detecting and error correcting codes. *The Bell system technical journal*, 29(2):147–160, 1950.

[Hat] Red Hat. Disabling smt to prevent cpu security issues using the web console. https://access.redhat.com/documentation/en-us/red-hat-enterprise-linux/8/topic/f1d65124-781b-4543-a51a-d2bf9fa794ac. Accessed: 2022-05-10.

[Hor] Jan Horn. Project zero: Reading privileged memory with a side channel. https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.html. Accessed: 2022-07-04.

[Hor18] Jann Horn. speculative execution, variant 4: speculative store bypass, 2018.

[HS13] Michael Hutter and Jörn-Marc Schmidt. The temperature side channel and heating fault attacks. In *CARDIS*, volume 8419 of *Lecture Notes in Computer Science*, pages 219–235. Springer, 2013.

[Hu92] Wei-Ming Hu. Lattice scheduling and covert channels. In *IEEE Symposium on Security and Privacy*, pages 52–61. IEEE Computer Society, 1992.

[HWH13] Ralf Hund, Carsten Willems, and Thorsten Holz. Practical timing side channel attacks against kernel space ASLR. In *IEEE Symposium on Security and Privacy*, pages 191–205. IEEE Computer Society, 2013.
[IES16] Gorka Irazoqui, Thomas Eisenbarth, and Berk Sunar. Cross processor cache attacks. In *AsiaCCS*, pages 353–364. ACM, 2016.

[IES18] Gorka Irazoqui, Thomas Eisenbarth, and Berk Sunar. MASCAT: preventing microarchitectural attacks before distribution. In *CODASPY*, pages 377–388. ACM, 2018.

[IIES14] Gorka Irazoqui, Mehmet Sinan Inci, Thomas Eisenbarth, and Berk Sunar. Wait a minute! a fast, cross-vm attack on aes. In *International Workshop on Recent Advances in Intrusion Detection*, pages 299–319. Springer, 2014.

[Inta] Intel. Affected processors: Transient execution attacks & related security. https://www.intel.com/content/www/us/en/developer/topic-technology/software-security-guidance/processors-affected-consolidated-product-cpu-model.html. Accessed: 2022-07-26.

[Intb] Intel. How to benchmark code execution times on intel ia-32 and ia-64 instruction set architectures white paper - ia-32-ia-64-benchmark-code-execution-paper.pdf. https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/ia-32-ia-64-benchmark-code-execution-paper.pdf. Accessed: 2022-07-26.

[Intc] Intel. Intel® 64 and ia-32 architectures optimization reference manual. https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html. Accessed: 2022-06-30.

[Intd] Intel. Intel® 64 and ia-32 architectures software developer's manual. https://www.intel.com/content/dam/doc/manual/64-ia-32-architectures-optimization-manual.pdf. Accessed: 2022-07-20.

[Inte] Intel. Introduction to cache allocation technology. https://www.intel.com/content/www/us/en/developer/articles/technical/introduction-to-cache-allocation-technology.html. Accessed: 2022-07-26.

[JS12] Suman Jana and Vitaly Shmatikov. Memento: Learning secrets from process footprints. In *IEEE Symposium on Security and Privacy*, pages 143–157. IEEE Computer Society, 2012.

[K15] Sakamoto K. Reduce resolution of performance.now to prevent timing attacks. https://bugs.chromium.org/p/chromium/issues/detail?id=506723, Jul 2015.

[KASZ09] Jingfei Kong, Onur Aciiçmez, Jean-Pierre Seifert, and Huiyang Zhou. Hardware-software integrated approaches to defend against software cache-based side channel attacks. In *HPCA*, 2009.

[KDK+14] Yoongu Kim, Ross Daly, Jeremie S. Kim, Chris Fallin, Ji-Hye Lee, Donghyuk Lee, Chris Wilkerson, Konrad Lai, and Onur Mutlu. Flipping bits in memory without accessing them: An experimental study of DRAM disturbance errors. In *ISCA*, pages 361–372. IEEE Computer Society, 2014.
[KGA$^{+20}$] Michael Kurth, Ben Gras, Dennis Andriesse, Cristiano Giuffrida, Herbert Bos, and Kaveh Razavi. Netcat: Practical cache attacks from the network. In *2020 IEEE Symposium on Security and Privacy (SP)*, pages 20–38. IEEE, 2020.

[KHF$^{+19}$] Paul Kocher, Jann Horn, Anders Fogh, Daniel Genkin, Daniel Gruss, Werner Haas, Mike Hamburg, Moritz Lipp, Stefan Mangard, Thomas Prescher, Michael Schwarz, and Yuval Yarom. Spectre attacks: Exploiting speculative execution. In *IEEE Symposium on Security and Privacy*, pages 1–19. IEEE, 2019.

[KJJ99] Paul Kocher, Joshua Jaffe, and Benjamin Jun. Differential power analysis. In *CRYPTO*, volume 1666 of *Lecture Notes in Computer Science*, pages 388–397. Springer, 1999.

[KKSA18] Esmaeil Mohammadian Koruyeh, Khaled N. Khasawneh, Chengyu Song, and Nael B. Abu-Ghazaleh. Spectre returns! speculation attacks using the return stack buffer. In *WOOT @ USENIX Security Symposium*. USENIX Association, 2018.

[Koc96] Paul Kocher. Timing attacks on implementations of diffie-hellman, rsa, dss, and other systems. In *CRYPTO*, volume 1109 of *Lecture Notes in Computer Science*, pages 104–113. Springer, 1996.

[KPM12] Taesoo Kim, Marcus Peinado, and Gloria Mainar-Ruiz. STEALTHMEM: system-level protection against cache-based side channel attacks in the cloud. In *USENIX Security Symposium*, pages 189–204. USENIX Association, 2012.

[Kru14] Christopher Kruegel. Full system emulation: Achieving successful automated dynamic analysis of evasive malware. In *BlackHat USA*, 2014.

[KS16] David Kohlbrenner and Hovav Shacham. Trusted browsers for uncertain times. In *USENIX Security Symposium*, pages 463–480. USENIX Association, 2016.

[KSWH00] John Kelsey, Bruce Schneier, David A. Wagner, and Chris Hall. Side channel cryptanalysis of product ciphers. *J. Comput. Secur.*, 8(2/3):141–158, 2000.

[KW18] Vladimir Kiriansky and Carl A. Waldspurger. Speculative buffer overflows: Attacks and defenses. *CoRR*, abs/1807.03757, 2018.

[Kyö18] Sami Kyöstilä. Clamp performance.now() to 100us. https://chromium-review.googlesource.com/c/chromium/src+/849993, Jan 2018.

[LABN19] Pierre Laperdrix, Gildas Avoine, Benoit Baudry, and Nick Nikiforakis. Morellian analysis for browsers: Making web authentication stronger with canvas fingerprinting. In *DIMVA*, 2019.

[Lar] Michael Larabel. Openbsd disabling smt / hyper threading due to security concerns. https://www.phoronix.com/scan.php?page=news_item&px=OpenBSD-Disabling-SMT. Accessed: 2021-19-11.

[LAS$^{+18}$] Moritz Lipp, Misiker Tadesse Aga, Michael Schwarz, Daniel Gruss, Clémentine Maurice, Lukas Raab, and Lukas Lamster. Nethammer: Inducing rowhammer faults through network requests. *CoRR*, abs/1805.04956, 2018.
[LG18] Congmiao Li and Jean-Luc Gaudiot. Online detection of spectre attacks using microarchitectural traces from performance counters. In *SBAC-PAD*, pages 25–28. IEEE, 2018.

[LGR14] Peng Li, Debin Gao, and Michael K. Reiter. Stopwatch: A cloud architecture for timing channel mitigation. *ACM Trans. Inf. Syst. Secur.*, 17(2):8:1–8:28, 2014.

[LGS$^{+16}$] Moritz Lipp, Daniel Gruss, Raphael Spreitzer, Clémentine Maurice, and Stefan Mangard. Armageddon: Cache attacks on mobile devices. In *USENIX Security Symposium*, pages 549–564. USENIX Association, 2016.

[LGS$^{+17}$] Moritz Lipp, Daniel Gruss, Michael Schwarz, David Bidner, Clémentine Maurice, and Stefan Mangard. Practical keystroke timing attacks in sandboxed javascript. In *ESORICS (2)*, volume 10493 of *Lecture Notes in Computer Science*, pages 191–209. Springer, 2017.

[LHS$^{+20}$] Moritz Lipp, Vedad Hadzic, Michael Schwarz, Arthur Perais, Clémentine Maurice, and Daniel Gruss. Take A way: Exploring the security implications of amd's cache way predictors. In *AsiaCCS*, pages 813–825. ACM, 2020.

[LKO$^{+21}$] Moritz Lipp, Andreas Kogler, David F. Oswald, Michael Schwarz, Catherine Easdon, Claudio Canella, and Daniel Gruss. PLATYPUS: software-based power side-channel attacks on x86. In *IEEE Symposium on Security and Privacy*, pages 355–371. IEEE, 2021.

[LL14] Fangfei Liu and Ruby B. Lee. Random fill cache architecture. In *MICRO*, 2014.

[LMD$^{+22}$] Tomer Laor, Naif Mehanna, Antonin Durey, Vitaly Dyadyuk, Pierre Laperdrix, Clémentine Maurice, Yossi Oren, Romain Rouvoy, Walter Rudametkin, and Yuval Yarom. *DRAWNAPART: A device identification technique based on remote GPU fingerprinting*. In *NDSS*, 2022.

[LSG$^{+20}$] Moritz Lipp, Michael Schwarz, Daniel Gruss, Thomas Prescher, Werner Haas, Jann Horn, Stefan Mangard, Paul Kocher, Daniel Genkin, Yuval Yarom, Mike Hamburg, and Raoul Strackx. Meltdown: reading kernel memory from user space. *Commun. ACM*, 63(6):46–56, 2020.

[LWD10] Chao Liu, Ryen W. White, and Susan T. Dumais. Understanding web browsing behaviors through weibull analysis of dwell time. In *SIGIR*, 2010.

[LYG$^{+15}$] Fangfei Liu, Yuval Yarom, Qian Ge, Gernot Heiser, and Ruby B. Lee. Last-level cache side-channel attacks are practical. In *IEEE Symposium on Security and Privacy*, pages 605–622. IEEE Computer Society, 2015.

[May09] Jonathan R Mayer. Any person... a pamphleteer": Internet anonymity in the age of web 2.0. *Undergraduate Senior Thesis*, Princeton University, 85, 2009.

[MBYS11] Keaton Mowery, Dillon Bogenreif, Scott Yilek, and Hovav Shacham. Fingerprinting information in JavaScript implementations. In Helen Wang, editor, *Proceedings of W2SP 2011. IEEE Computer Society*, May 2011.
[MCS<sup>+</sup>16] Jian Mao, Yue Chen, Futian Shi, Yaoqi Jia, and Zhenkai Liang. Toward exposing timing-based probing attacks in web applications. In *WASA*, volume 9798 of *Lecture Notes in Computer Science*, pages 499–510. Springer, 2016.

[MOG<sup>+</sup>20] Kit Murdock, David F. Oswald, Flavio D. Garcia, Jo Van Bulck, Daniel Gruss, and Frank Piessens. Plundervolt: Software-based fault injection attacks against intel SGX. In *IEEE Symposium on Security and Privacy*, pages 1466–1482. IEEE, 2020.

[Moza] Mozilla. Rabaldrmonkey baseline compile. https://hg.mozilla.org/mozilla-central/file/tip/js/src/wasm/WasmBaselineCompile.cpp. Accessed: 2022-07-26.

[Mozb] Mozilla. Spidermonkey javascript engine. https://spidermofnkey.dev/. Accessed: 2022-07-21.

[Mozc] Mozilla. v8/bytecodes.h. https://searchfox.org/mozilla-central/source/js/src/vm/Opcodes.h. Accessed: 2022-07-26.

[Moz19] Mozilla. Always restyle / repaint when a visited query finishes - Mozilla Central. https://hg.mozilla.org/mozilla-central/rev/89fad029456188f03a670ef5f08a5d0856a728b1, 2019.

[Moz20a] Mozilla. Bug 884270: Link Visitedness can be detected by redraw timing – Bugzilla. https://bugzilla.mozilla.org/show_bug.cgi?id=884270, 2020.

[Moz20b] Mozilla. nsrfpservice.cpp, firefox sourcecode. https://hg.mozilla.org/mozilla-central/file/tip/toolkit/components/resistfingerprinting/nsRFPService.cpp, October 2020.

[MR18] Giorgi Maisuradze and Christian Rossow. ret2spec: Speculative execution using return stack buffers. In *CCS*, pages 2109–2122. ACM, 2018.

[MWS<sup>+</sup>17] Clémentine Maurice, Manuel Weber, Michael Schwarz, Lukas Giner, Daniel Gruss, Carlo Alberto Boano, Stefan Mangard, and Kay Römer. Hello from the other side: SSH over robust cache covert channels in the cloud. In *NDSS*, 2017.

[NS06] Michael Neve and Jean-Pierre Seifert. Advances on access-driven cache attacks on AES. In *Selected Areas in Cryptography*, volume 4356 of *Lecture Notes in Computer Science*, pages 147–162. Springer, 2006.

[NSY15] Gabi Nakibly, Gilad Shelef, and Shiran Yudilevich. Hardware fingerprinting using HTML5. *CoRR*, abs/1503.01408, 2015.

[OACD15] Lukasz Olejnik, Gunes Acar, Claude Castelluccia, and Claudia Díaz. The leaking battery - A privacy analysis of the HTML5 battery status API. In *DPM/QASA@ESORICS*, volume 9481 of *Lecture Notes in Computer Science*, pages 254–263. Springer, 2015.

[OKSK15] Yossef Oren, Vasileios P. Kemerlis, Simha Sethumadhavan, and Angelos D. Keromytis. The spy in the sandbox: Practical cache attacks in javascript and their implications. In *CCS*, pages 1406–1418. ACM, 2015.
[Ope] OpenPGP.js. Openpgp.js | openpgp javascript implementation. https://openpgpjs.org/. Accessed: 2022-07-26.

[Ore15] Yossi Oren. "spy in the sandbox" - security issue related to high resolution time api. https://bugzilla.mozilla.org/show_bug.cgi?id=1167489, may 2015.

[OST06] Dag Arne Osvik, Adi Shamir, and Eran Tromer. Cache attacks and countermeasures: the case of aes. In *CT-RSA*, pages 1–20. Springer, 2006.

[OW11] Rodney Owens and Weichao Wang. Non-interactive OS fingerprinting through memory de-duplication technique in virtual machines. In *IPCCC*, pages 1–8. IEEE Computer Society, 2011.

[Pag05] Dan Page. Partitioned cache architecture as a side-channel defence mechanism. *IACR Cryptol. ePrint Arch.*, page 280, 2005.

[Pay16a] Mathias Payer. Hexpads: A platform to detect "stealth" attacks. In *ESSoS*, volume 9639 of *Lecture Notes in Computer Science*, pages 138–154. Springer, 2016.

[Pay16b] Mathias Payer. Hexpads: A platform to detect "stealth" attacks. In *ESSoS*, volume 9639 of *Lecture Notes in Computer Science*, pages 138–154. Springer, 2016.

[Per05] Colin Percival. Cache missing for fun and profit. In *In Proc. of BSDCan 2005*, 2005.

[PGGV21] Antoon Purnal, Lukas Giner, Daniel Gruss, and Ingrid Verbauwhede. Systematic analysis of randomization-based protected cache architectures. In *S&P*, 2021.

[PGM+16] Peter Pessl, Daniel Gruss, Clémentine Maurice, Michael Schwarz, and Stefan Mangard. DRAMA: exploiting DRAM addressing for cross-cpu attacks. In *USENIX Security Symposium*, pages 565–581. USENIX Association, 2016.

[PIO19] Iván Prada, Francisco D Igual, and Katzalin Olcoz. Detecting time-fragmented cache attacks against aes using performance monitoring counters. In *Conference on Cloud Computing and Big Data*, pages 3–15. Springer, 2019.

[PLF21] Riccardo Paccagnella, Licheng Luo, and Christopher W. Fletcher. Lord of the ring(s): Side channel attacks on the CPU on-chip ring interconnect are practical. In *USENIX Security Symposium*, pages 645–662. USENIX Association, 2021.

[PSS+18] Damian Poddebniak, Juraj Somorovsky, Sebastian Schinzel, Manfred Lochter, and Paul Rösler. Attacking deterministic signature schemes using fault attacks. In *EuroS&P*, pages 338–352. IEEE, 2018.

[PTV21] Antoon Purnal, Furkan Turan, and Ingrid Verbauwhede. Prime+scope: Overcoming the observer effect for high-precision cache contention attacks. In *CCS*, pages 2906–2920. ACM, 2021.

[Qur18] Moinuddin K. Qureshi. CEASER: mitigating conflict-based cache attacks via encrypted-address and remapping. In *MICRO*, pages 775–787. IEEE Computer Society, 2018.
[Ray17] Raymond Hill. uBlock Origin - An efficient blocker for Chromium and Firefox. Fast and lean., July 2017.

[RGB+16] Kaveh Razavi, Ben Gras, Erik Bosman, Bart Preneel, Cristiano Giuffrida, and Herbert Bos. Flip feng shui: Hammering a needle in the software stack. In *USENIX Security Symposium*, pages 1–18. USENIX Association, 2016.

[RLT15] Ashay Rane, Calvin Lin, and Mohit Tiwari. Raccoon: Closing digital {Side-Channels} through obfuscated execution. In *USENIX Security Symposium*, 2015.

[RMBO22] Thomas Rokicki, Clémentine Maurice, Marina Botvinnik, and Yossi Oren. Port contention goes portable: Port contention side channels in web browsers. In *AsiaCS*, pages 1182–1194. ACM, 2022.

[RML21] Thomas Rokicki, Clémentine Maurice, and Pierre Laperdrix. Sok: In search of lost time: A review of javascript timers in browsers. In *EuroS&P*, pages 472–486. IEEE, 2021.

[RMO19] Charles Reis, Alexander Moshchuk, and Nasko Oskov. Site isolation: Process separation for web sites within the browser. In *USENIX Security Symposium*, 2019.

[RMS22] Thomas Rokicki, Clémentine Maurice, and Michael Schwarz. Cpu port contention without SMT. In *ESORICS*, 2022.

[RMT+21] Xida Ren, Logan Moody, Mohammadkazem Taram, Matthew Jordan, Dean M. Tullsen, and Ashish Venkat. I see dead µops: Leaking secrets via intel/amd micro-op caches. In *ISCA*, 2021.

[RR01] Josyula R. Rao and Pankaj Rohatgi. Empowering side-channel attacks. *IACR Cryptol. ePrint Arch.*, page 37, 2001.

[RRR16] Michael Rushanan, David Russell, and Aviel D. Rubin. Malloryworker: Stealthy computation and covert channels using web workers. In *STM*, volume 9871 of *Lecture Notes in Computer Science*, pages 196–211. Springer, 2016.

[SAO+21] Anatoly Shusterman, Ayush Agarwal, Sioli O'Connell, Daniel Genkin, Yossi Oren, and Yuval Yarom. Prime+probe 1, javascript 0: Overcoming browser-based side-channel defenses. In *USENIX Security Symposium*, 2021.

[SBK+21] Martin Schwarzl, Pietro Borrello, Andreas Kogler, Kenton Varda, Thomas Schuster, Daniel Gruss, and Michael Schwarz. Dynamic process isolation. *CoRR*, abs/2110.04751, 2021.

[SD15] Mark Seaborn and Thomas Dullien. Exploiting the dram rowhammer bug to gain kernel privileges. *Black Hat*, 15:71, 2015.

[Sea] M. Seaborn. How physical addresses map to rows and banks in dram. http://lackingroticity.blogspot.com/2015/05/how-physical-addresses-map-to-rows-and-banks.html. Accessed: 2022-07-04.
<table>
  <tr>
    <td>[sel20]</td>
    <td>SeleniumHQ browser automation. https://www.selenium.dev/, oct 2020.</td>
  </tr>
  <tr>
    <td>[SIYA11]</td>
    <td>Kuniyasu Suzaki, Kengo Iijima, Toshiki Yagi, and Cyrille Artho. Memory deduplication as a threat to the guest OS. In EUROSEC, page 1. ACM, 2011.</td>
  </tr>
  <tr>
    <td>[SKH<sup>+</sup>19]</td>
    <td>Anatoly Shusterman, Lachlan Kang, Yarden Haskal, Yosef Meltser, Prateek Mittal, Yossi Oren, and Yuval Yarom. Robust website fingerprinting through the cache occupancy channel. In USENIX Security Symposium, 2019.</td>
  </tr>
  <tr>
    <td>[SKLG21]</td>
    <td>Martin Schwarzl, Erik Kraft, Moritz Lipp, and Daniel Gruss. Remote memory-deduplication attacks. NDSS, 2021.</td>
  </tr>
  <tr>
    <td>[SLCO18]</td>
    <td>Bin Shi, Bo Li, Lei Cui, and Liu Ouyang. Vanguard: A cache-level sensitive file integrity monitoring system in virtual machine environment. IEEE Access, 6:38567-38577, 2018.</td>
  </tr>
  <tr>
    <td>[SLG18a]</td>
    <td>Michael Schwarz, Moritz Lipp, and Daniel Gruss. Javascript zero: Real javascript and zero side-channel attacks. In NDSS. The Internet Society, 2018.</td>
  </tr>
  <tr>
    <td>[SLG<sup>+</sup>18b]</td>
    <td>Michael Schwarz, Moritz Lipp, Daniel Gruss, Samuel Weiser, Clémentine Maurice, Raphael Spreitzer, and Stefan Mangard. Keydrown: Eliminating software-based keystroke timing side-channel attacks. In NDSS. The Internet Society, 2018.</td>
  </tr>
  <tr>
    <td>[SLG19]</td>
    <td>Michael Schwarz, Florian Lackner, and Daniel Gruss. Javascript template attacks: Automatically inferring host information for targeted exploits. In NDSS, 2019.</td>
  </tr>
  <tr>
    <td>[SLKN19]</td>
    <td>Oleksii Starov, Pierre Laperdrix, Alexandros Kapravelos, and Nick Nikiforakis. Unnecessarily identifiable: Quantifying the fingerprintability of browser extensions due to bloat. In WWW, 2019.</td>
  </tr>
  <tr>
    <td>[SLM<sup>+</sup>19]</td>
    <td>Michael Schwarz, Moritz Lipp, Daniel Moghimi, Jo Van Bulck, Julian Stecklina, Thomas Prescher, and Daniel Gruss. Zombieload: Cross-privilege-boundary data sampling. In CCS, pages 753-768. ACM, 2019.</td>
  </tr>
  <tr>
    <td>[SMAK20]</td>
    <td>Benjamin Semal, Konstantinos Markantonakis, Raja Naeem Akram, and Jan Kalbantner. Leaky controller: Cross-vm memory controller covert channel on multi-core systems. In SEC, volume 580 of IFIP Advances in Information and Communication Technology, pages 3-16. Springer, 2020.</td>
  </tr>
  <tr>
    <td>[SMGM17]</td>
    <td>Michael Schwarz, Clémentine Maurice, Daniel Gruss, and Stefan Mangard. Fantastic timers and where to find them: High-resolution microarchitectural attacks in javascript. In Financial Cryptography, volume 10322 of Lecture Notes in Computer Science, pages 247-267. Springer, 2017.</td>
  </tr>
  <tr>
    <td>[SNK<sup>+</sup>12]</td>
    <td>Alexander Schlösser, Dmitry Nedospasov, Juliane Krämer, Susanna Orlic, and Jean-Pierre Seifert. Simple photonic emission analysis of AES - photonic side channel analysis for the rest of us. In CHES, volume 7428 of Lecture Notes in Computer Science, pages 41-57. Springer, 2012.</td>
  </tr>
</table>
[SP13] Raphael Spreitzer and Thomas Plos. Cache-access pattern attack on disaligned AES t-tables. In COSADE, volume 7864 of Lecture Notes in Computer Science, pages 200–214. Springer, 2013.

[SP18] Julian Stecklina and Thomas Prescher. Lazyfp: Leaking FPU register state using microarchitectural side-channels. CoRR, abs/1806.07480, 2018.

[SQ21] Gururaj Saileshwar and Moinuddin K. Qureshi. MIRAGE: mitigating conflict-based cache attacks with a practical fully-associative design. In USENIX Security Symposium, 2021.

[SS20] Milad Seddigh and Hadi Soleimany. Enhanced flush+reload attack on AES. ISC Int. J. Inf. Secur., 12(2):81–89, 2020.

[SSB17a] Iskander Sánchez-Rola, Igor Santos, and Davide Balzarotti. Extension breakdown: Security analysis of browsers extension resources control policies. In USENIX Security Symposium, pages 679–694. USENIX Association, 2017.

[SSB17b] Iskander Sánchez-Rola, Igor Santos, and Davide Balzarotti. Extension breakdown: Security analysis of browsers extension resources control policies. In USENIX Security Symposium, pages 679–694. USENIX Association, 2017.

[SSB17c] Iskander Sánchez-Rola, Igor Santos, and Davide Balzarotti. Extension breakdown: Security analysis of browsers extension resources control policies. In USENIX Security Symposium, 2017.

[SSB18] Iskander Sánchez-Rola, Igor Santos, and Davide Balzarotti. Clock around the clock: Time-based device fingerprinting. In CCS, 2018.

[SSL+19] Michael Schwarz, Martin Schwarzl, Moritz Lipp, Jon Masters, and Daniel Gruss. Netspectre: Read arbitrary memory over network. In European Symposium on Research in Computer Security, pages 279–299. Springer, 2019.

[ST04] Adi Shamir and Eran Tromer. Acoustic cryptanalysis, 2004.

[Sta] Chrome Platform Status. Align performance api timer resolution to cross-origin isolated capability. https://chromestatus.com/feature/6497206758539264.

[Sto13] Paul Stone. Pixel perfect timing attacks with HTML5, 2013.

[SVS17] Alexander Sjösten, Steven Van Acker, and Andrei Sabelfeld. Discovering browser extensions via web accessible resources. In CODASPY, pages 329–336. ACM, 2017.

[SWG+17] Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice, and Stefan Mangard. Malware guard extension: Using SGX to conceal cache attacks. CoRR, abs/1702.08719, 2017.

[SWT01] Dawn Xiaodong Song, David A. Wagner, and Xuqing Tian. Timing analysis of keystrokes and timing attacks on SSH. In USENIX Security Symposium. USENIX, 2001.
[Teaa] ARM Security Team. Speculative processor vulnerability. https://developer.arm.com/Arm%20Security%20Center/Speculative%20Processor%20Vulnerability. Accessed: 2022-07-04.

[Teab] Google Security Team. Leaky page. https://security.googleblog.com/2021/03/a-spectre-proof-of-concept-for-spectre.html. Accessed: 2022-07-04.

[THAC18] David Trilla, Carles Hernández, Jaume Abella, and Francisco J. Cazorla. Cache side-channel attacks and time-predictability in high-performance critical real-time systems. In *DAC*, pages 98:1–98:6. ACM, 2018.

[TKA+18] Andrei Tatar, Radhesh Krishnan Konoth, Elias Athanasopoulos, Cristiano Giuffrida, Herbert Bos, and Kaveh Razavi. Throwhammer: Rowhammer attacks over the network and defenses. In *USENIX Annual Technical Conference*, pages 213–226. USENIX Association, 2018.

[TP19] Daniel Townley and Dmitry Ponomarev. SMT-COP: defeating side-channel attacks on execution units in SMT processors. In *PACT*, 2019.

[TRVT22] Mohammadkazem Taram, Xida Ren, Ashish Venkat, and Dean Tullsen. Secsmt: Securing SMT processors against contention-based covert channels. In *USENIX Security Symposium*, 2022.

[TS] Ben L. Titzer and Jaroslav Sevcik. A year with spectre: a v8 perspective. https://v8.dev/blog/spectre. Accessed: 2021-02-12.

[TSS17] Adrian Tang, Simha Sethumadhavan, and Salvatore J. Stolfo. CLKSCREW: exposing the perils of security-oblivious energy management. In *USENIX Security Symposium*, pages 1057–1074. USENIX Association, 2017.

[Tur18] Paul Turner. Retpoline: a software construct for preventing branch-target-injection. URL https://support.google.com/faqs/answer/7625886, 2018.

[Vah] Lutz Vahl. Intent to extend origin trial: Trial for sharedarray-buffers in non-isolated pages on desktop platforms. https://mikewest.github.io/cookie-incrementalism/draft-west cookie-incrementalism.htmlhttps://groups.google.com/a/chromium.org/g/blink-dev/c/OLbI-axDyHo/m/qYYz7LvEAgAJ. Accessed: 2022-08-05.

[vba] v8 blog. Ignition - v8. https://v8.dev/docs/ignition. Accessed: 2022-07-26.

[vbb] v8 blog. Liftoff - v8. https://v8.dev/blog/liftoff. Accessed: 2022-07-26.

[vbc] v8 blog. Turbofan - v8. https://v8.dev/docs/turbofan. Accessed: 2022-07-26.

[vdPSY15] Joop van de Pol, Nigel P. Smart, and Yuval Yarom. Just a little bit more. In *CT-RSA*, volume 9048 of *Lecture Notes in Computer Science*, pages 3–21. Springer, 2015.

[VDS11] Bhanu Chandra Vattikonda, Sambit Das, and Hovav Shacham. Eliminating fine grained timers in xen. In *CCSW*, pages 41–46. ACM, 2011.
[vGJ17] Tom van Goethem and Wouter Joosen. One side-channel to bring them all and in the darkness bind them: Associating isolated browsing sessions. In *WOOT USENIX Association*, 2017.

[vGJN15] Tom van Goethem, Wouter Joosen, and Nick Nikiforakis. The clock is still ticking: Timing attacks in the modern web. In *CCS*, pages 1382–1393. ACM, 2015.

[VK17] Pepe Vila and Boris Köpf. Loophole: Timing attacks on shared event loops in chrome. In *USENIX Security Symposium*, 2017.

[VKM19] Pepe Vila, Boris Köpf, and José F. Morales. Theory and practice of finding eviction sets. In *IEEE Symposium on Security and Privacy*, pages 39–54. IEEE, 2019.

[VLRR18] Antoine Vastel, Pierre Laperdrix, Walter Rudametkin, and Romain Rouvoy. FP-STALKER: tracking browser fingerprint evolutions. In *S&P*, 2018.

[VRS14] Venkatanathan Varadarajan, Thomas Ristenpart, and Michael M. Swift. Scheduler-based defenses against cross-vm side-channels. In *USENIX Security Symposium*, 2014.

[vSMÖ⁺¹⁹] Stephan van Schaik, Alyssa Milburn, Sebastian Österlund, Pietro Frigo, Giorgi Maisuradze, Kaveh Razavi, Herbert Bos, and Cristiano Giuffrida. RIDL: rogue in-flight data load. In *S&P*, 2019.

[W3C] W3C. Webassembly core specification. https://webassembly.github.io/spec/core/bikeshed/. Accessed: 2022-07-26.

[w3t] w3techs. Usage statistics of javascript as client-side programming language on websites. https://w3techs.com/technologies/details/cp-javascript/. Accessed: 2022-07-26.

[Wag18] Luke Wagner. Mitigations landing for new class of timing attack. https://blog.mozilla.org/security/2018/01/03/mitigations-landing-new-class-timing-attack/, jan 2018.

[WC14] Ruisheng Wang and Lizhong Chen. Futility scaling: High-associativity cache partitioning. In *MICRO*, pages 356–367. IEEE Computer Society, 2014.

[Wes] Mike West. Incrementally better cookies. https://mikewest.github.io/cookie-incrementalism/draft-west cookie-incrementalism.html. Accessed: 2020-11-05.

[WFZ⁺¹⁶] Yao Wang, Andrew Ferraiuolo, Danfeng Zhang, Andrew C. Myers, and G. Edward Suh. Secdcp: secure dynamic cache partitioning for efficient timing channel protection. In *DAC*, pages 74:1–74:6. ACM, 2016.

[Wika] Mozilla Wiki. https://www.mozilla.org/en-US/firefox/95.0/releasenotes/.

[Wikb] Perf Wiki. Perf. https://perf.wiki.kernel.org/index.php/Main_Page. Accessed: 2022-07-26.
[Wikc] WikiChip. Sunny cove - microarchitectures - intel - wikichip. https://en.wikichip.org/wiki/intel/microarchitectures/sunny_cove. Accessed: 2022-05-20.

[WIN+21] Daniel Weber, Ahmad Ibrahim, Hamed Nemati, Michael Schwarz, and Christian Rossow. Osiris: Automated discovery of microarchitectural side channels. In USENIX Security Symposium, pages 1415-1432. USENIX Association, 2021.

[WL07] Zhenghong Wang and Ruby B. Lee. New cache designs for thwarting software cache-based side channel attacks. In ISCA, pages 494-505. ACM, 2007.

[WSS+20] Han Wang, Hossein Sayadi, Avesta Sasan, Setareh Rafatirad, Tinoosh Mohsenenin, and Houman Homayoun. Comprehensive evaluation of machine learning countermeasures for detecting microarchitectural side-channel attacks. In ACM Great Lakes Symposium on VLSI, pages 181-186. ACM, 2020.

[WZCN20] Minghua Wang, Zhi Zhang, Yueqiang Cheng, and Surya Nepal. Dramdig: A knowledge-assisted tool to uncover DRAM address mapping. In DAC, pages 1-6. IEEE, 2020.

[XXHW13] Jidong Xiao, Zhang Xu, Hai Huang, and Haining Wang. Security implications of memory deduplication in a virtualized environment. In DSN, pages 1-12. IEEE Computer Society, 2013.

[XZZT16] Yuan Xiao, Xiaokuan Zhang, Yinqian Zhang, and Radu Teodorescu. One bit flips, one cloud flops: Cross-vm row hammer attacks and privilege escalation. In USENIX Security Symposium, pages 19-35. USENIX Association, 2016.

[Yas14] Ahmad Yasin. A top-down method for performance analysis and counters architecture. In ISPASS, pages 35-44. IEEE Computer Society, 2014.

[YB14] Yuval Yarom and Naomi Benger. Recovering openssl ECDSA nonces using the FLUSH+RELOAD cache side-channel attack. IACR Cryptol. ePrint Arch., page 140, 2014.

[YF14] Yuval Yarom and Katrina Falkner. FLUSH+RELOAD: A high resolution, low noise, L3 cache side-channel attack. In USENIX Security Symposium, 2014.

[ZJOR11] Yinqian Zhang, Ari Juels, Alina Oprea, and Michael K. Reiter. Homealone: Co-residency detection in the cloud via side-channel analysis. In IEEE Symposium on Security and Privacy, pages 313-328. IEEE Computer Society, 2011.

[ZR13] Yinqian Zhang and Michael K. Reiter. Düppel: retrofitting commodity operating systems to mitigate cache side channels in the cloud. In CCS, 2013.

[ZW09] Kehuan Zhang and XiaoFeng Wang. Peeping tom in the neighborhood: Keystroke eavesdropping on multi-user systems. In USENIX Security Symposium, pages 17-32. USENIX Association, 2009.
<figure><img src="image_48.png" /></figure>
**Titre :** Canaux Auxiliaires dans les Navigateurs : Applications à la Sécurité et la Vie Privée

**Mot clés :** Canaux auxiliaires, Microarchitecture, Sécurité du Web, Contention de port, Attaques par minutage

**Résumé :**

Les attaques par canal auxiliaire exploitent les effets secondaires d'un calcul sensible pour divulguer des secrets. Leur implémentation dans les navigateurs web représente une augmentation considérable de la surface d'attaque, mais s'accompagne de défis dus à l'environnement restrictif et aux mises à jour constantes des navigateurs. Cette thèse évale la menace que représentent les canaux auxiliaires microarchitecturaux dans les navigateurs.

Nous fournissons une systématisation des attaques par minutage et des contre-mesures dans les navigateurs. En particulier, nous montrons que l'évolution de la sécurité basée

sur le timing rend les navigateurs plus vulnérables aux attaques par minutage.

Nous présentons également la contention de port du processeur dans l'environnement restreint de JavaScript. Notre canal auxiliaire a une résolution spatiale comparable à celle des meilleurs canaux auxiliaires dans les navigateurs et permet la création d'un canal caché à large bande passante. En outre, nous montrons que la contention de port peut également être exploitée sans SMT. Les implications de ce nouveau canal auxiliaire sur la vie privée sont inquiétantes, car un attaquant peut l'utiliser pour récupérer les générations de processeurs.

**Title:** Side Channels in Web Browsers: Applications to Security and Privacy

**Keywords:** Side channels; Microarchitecture, Web Security, Port Contention, Timing attacks

**Abstract:** Side channel attacks exploit the side effects of sensitive computation to leak secrets. Their implementation in web browsers represents a considerable increase in threat surface, but comes with challenges due to the restrictive environment and the constant browser updates. This thesis evaluates the threat posed by microarchitectural side channels in browsers.

We provide a systematization of timing attacks and countermeasures in browsers. With automatic frameworks, we show that the

shift in timing-based security makes browsers more vulnerable to timing attacks.

We also introduce CPU port contention to the JavaScript Sandbox. Our side channel has a spatial resolution on par with the best side channels in the browsers and allows the creation of a high-bandwidth covert channel. Furthermore, we show that port contention can also be leveraged without SMT. The implications of this new side channel on privacy are worrying, as an attacker can leverage it to retrieve CPU generations.