Web Challenge
In this challenge, the defender has a secret Macguffin, in this case a random code which the attacker (below) is trying to guess. Everything is running inside a single, locked-down Hardened JavaScript realm. The attacker’s code (pasted into the text box) is evaluated by the defender in a separate Compartment when the Execute button is pressed.
The secret consists of a ten-character alphanumeric code (about 52 bits of entropy). The attacker’s program gets a “check my guess” function, which returns a Promise that fires with true for a correct guess and false for a wrong one. If the program guesses correctly, red lights flash and the attacker wins.
To make things easier for our attacker, we’ve added a classic timing side-channel. Our check function tests one character at a time, and takes 10 milliseconds for each comparison. An attacker with full access to a clock would try all possible values for the first character and see which one takes the least time, concluding that the full password must start with that character. Then they iterate on the second character, and so on until they’ve worked out the full password, roughly 18 seconds later.
However, Hardened JavaScript is deterministic and has no timers by default.
Shared intrinsics like new Date()
, Date.now()
, and Math.random()
are
disabled for programs confined to a Compartment
after lockdown()
in
Hardened JavaScript.
So this attacker doesn’t get a clock, and cannot read from the covert channel.
We provide an option to leak the real Date.now()
to demonstrate that the
attack works if attackers receive a clock.
Meanwhile, the defender running in the start Compartment gets access to
powerful JS globals.
This includes sources of non-determinism like window.setTimeout
and
window.crypto.getRandomValues
as well as the DOM.
Secret
Guess
Sample Attacks
Try a sample attack! Each of these will configure and execute a sample attack.
View Source
Find this demo on Github.