Blink-dev – Intent to Ship: SharedArrayBuffer
groups.google.com
groups.google.com
With SharedArrayBuffer you can easily implement extremely high resolution sub-nanosecond timers and open the door to new timing attacks. For example, here is a high resolution SharedArrayBuffer timer: https://codepen.io/yossioren/pen/LVBNMR
For more discussion regarding the security implications of this change, see https://github.com/tc39/ecmascript_sharedmem/issues/1 . Some of the security problems may be mitigable with Intel CAT, although I am not aware of Chrome making use of that yet.
There have even been timing attacks that let you recover AES keys from analyzing a device's power usage.
In layman's terms: computers are extremely complicated beasts of coordinated timing of software and hardware, and timing data leaks many things about what a piece of software is doing. This is the reason that many modern encryption libraries pad operations as a defense against timing attacks.
So, how does this work? I set a timer, and then read the time a bit later, and somehow I recovered an AES key from a different process? I'm still missing a piece :-)
Notably, how can timing data leak things?
I mean, I can see how I can do
1. Start hi-res timer
2. Kick off something that involves out-of-sandbox data
3. Stop hi-res timer
and do this often enough and with well-tuned input to read useful data out. Is that how it works?But how can I use this to read stuff in entirely different processes? Moreover, how can I do that in a targeted manner? Eg I suspect my target is using internet banking but I don't know which other programs are running, how many cores the machine has, etc etc etc.
Where they are different is that timing attacks usually serve as information extraction tools, which attackers can choose to further leverage by basing subsequent attacks on the information they obtained, where as buffer overflow attacks can do pretty much anything up to and including rooting a box or breaking out of a hypervisor.
That part's simple. Naive crypto code will often vary in speed based on the data. A 0 bit in the key causes some behavior, a 1 bit causes some slightly different behavior, and suddenly if you can measure the length of each step you can recover the secrets.
Getting the timing data is a little bit trickier from javascript, but it's also simple in concept. As sensitive code runs, it affects the CPU cache. Javascript can use memory locations that go in the same cache slots as sensitive code. This goes a few nanoseconds faster or slower based on what parts of the sensitive code have finished. Now you have timing data.
If you don't know what else is running or if you're on the same core, you just have to try repeatedly.
A lot of crypto code, especially implementations of asymmetric crypto, is not constant time, meaning that by timing it's execution you can extract key or plaintext fragments. Of course, authors try to make them as constant time as possible, but it's very, very hard to mask a non-constant time operation (required by some algorithms). So a higher resolution timer for the attacker means that it's easier and faster to attack these applications.
(This was a major design motivation for Curve25519. Previous ECC algorithms all had special cases, which mean non-constant-time, even with masking. Curve25519 was specifically designed to avoid that. -- That doesn't mean you can't implement it badly, though ;)
Due to the memory hierarchy (i.e. the fact that a CPU has caches) key or plaintext-dependent memory accesses lead to time variations as well. There are attacks that can be used to amplify these, by poisoning or preparing the caches in a way that forces main-memory or L3 reads for certain addresses.
(Some badly written libraries also use completely naive implementations, e.g. BouncyCastle used a not-at-all constant time implementation of AES, which was trivial to attack.)
For example measuring the time of a=b with constant b tells you roughly how large a[:n] such that a[:n] = b[:n].
Does the recent Chrome change to limit processor usage of a background tab also neuter this attack vector?
Edit: just check this tutorial. I'd venture to guess to 99% of JS developers it sounds totally bizarre: https://github.com/tc39/ecmascript_sharedmem/blob/master/TUT...
import ctypes
from multiprocessing import Array
mysharedarray = Array(ctypes.<type>, 100)
That's essentially the same as this proposal.Think of C++ for example. It's used to implement frameworks like JUCE, used for high-level application logic and UIs, but underneath that there are a lot of optimised abstractions. Some of these abstractions can only be so good or so deep until the language they are implemented in can get closer to the "metal" (or in this instance, VM).
I for one welcome these new additions to the ECMAscript spec.
- Introduce real native types, not complex-named functions that are way more bothersome to work with than types.
- Use WASM or something similar to provide for a low level variant.
One of those is not like the others.
Clearly the Java language -> Java bytecode -> Java Hardware chain is inherently more native and consistent than C language -> C Virtual Machine -> x64 -> Intel Core 2, where each step in the C language chain looses access to features of the underlying layer.
Plus, web assembly is here.
> Provide low-level buildings blocks for pthreads-style shared memory: shared memory between threads, atomics and futexes (or synchronic).
New atomic memory operators, including loads/stores annotated with their atomic ordering property, will follow the C++11 memory model, similarly to the PNaCl atomic support and the SharedArrayBuffer proposal. Regular loads and stores will be bound by a happens-before relationship to atomic operators in the same thread of execution, which themselves synchronize-with atomics in other threads. Following these rules, regular load/store operators can still be elided, duplicated, and split up. This guarantees that data-race free code executes as if it were sequentially consistent. Even when there are data races, WebAssembly will ensure that the nondeterminism remains limited and local.
Now if only Node.JS could support worker threads at all.
I guess it may come in handy for Electron apps.
Using Web Workers instead of Shared Workers just means that any actual communication beyond the shared memory must be posted via the instantiator of the worker.
I think a polyfill would be pretty difficult. First you have to make sure only one tab starts a Web Worker. Maybe that's not impossible, but it's tricky. And then the real difficulty... when the tab that spawned the Web Worker closes while another tab is open, you'd need to spawn another Web Worker in that tab and copy the state of the first Web Worker to the second Web Worker before the first one is destroyed by the browser. Not sure if that's possible.
Other examples would be MD5 removed from subtlecrypto, killing any way to speak with services that use it for non-cryptographic operations, or the missing functions to encode/decode hex strings, which maybe are not everyday use cases but are provided by most languages and would need an afternoon to write with tests.
I want a better standard library. Just my discouraged 5 cents.
> The "Unicode Problem"
> Since DOMStrings are 16-bit-encoded strings, in most browsers calling window.btoa on a Unicode string will cause a Character Out Of Range exception if a character exceeds the range of a 8-bit ASCII-encoded character. There are two possible methods to solve this problem:
https://developer.mozilla.org/en/docs/Web/API/WindowBase64/B...
Holy fuck, this is going to be bad, introducing a whole continent of new bugs into JavaScript land. And also giving JS even more and even better options to spy and attack other applications on the same computer.
However I think threading issues won't be as common as in C++/Java/C# land, since the only thing that will be shared between threads/workers is byte arrays -> There's no shared access to other Javascript objects. As most normal JS developers won't be dealing with plain byte arrays the potential for misuse is not too high.