Opened 3 years ago

Closed 12 months ago

#21011 closed enhancement (wontfix)

Disable JavaScript JIT

Reported by: cypherpunks Owned by: yawning
Priority: Medium Milestone:
Component: Archived/Tor Browser Sandbox Version:
Severity: Normal Keywords: sandbox-security
Cc: Yawning, brade, mcs, gk, arthuredelstein Actual Points:
Parent ID: Points:
Reviewer: Sponsor:

Description

JIT (Just-In-Time compilation) is an optimization applied to some interpreted languages which allows them to be compiled into bytecode just before being run. JavaScript is one of those languages. The sandbox should disable JIT to improve security. I've attached a solution (just appending the config changes to the autoconfig file).

Problems caused by JIT:

  • Increased susceptibility to ROP
  • A type of heap spraying called JIT-spraying (used for bypassing ASLR and NX)
  • High speed loops leading to efficient rowhammer.js implementations
  • Side-channel attacks against other tabs and other processes
  • Improved accuracy for keystroke dynamics (biometric fingerprinting)
  • Mandatory RWX mappings (Firefox 46 may fix this, making W^X and maybe PAX_MPROTECT finally work)
  • Increased attack surface by passing code through a compiler

Problems solved by JIT:

  • Improved performance on extremely JavaScript-heavy pages

Given that the priority is assumed to be security rather than performance, I hope the negligible trade-off is acceptable.

Child Tickets

Attachments (1)

disable_javascript_jit.patch (673 bytes) - added by cypherpunks 3 years ago.

Download all attachments as: .zip

Change History (18)

comment:1 Changed 3 years ago by yawning

FF46 does fix the issue with MPROTECT, but we won't get the benefit of that till ESR52.

In principle I don't mind this, but it feels somewhat redundant to me since Tor Browser already will set javascript.options.baselinejit.content and javascript.options.ion.content to false, as long as you don't have the security slider set to "YOLO".

IMO, if you think that more options should be set to *really* kill the JIT, then the patches should go into torbutton. If the JIT is just always evil, then the Tor Browser code should never JIT JS regardless of what the slider says.

(Also you're patching the wrong file, you want mozilla.cfg.)

Last edited 3 years ago by yawning (previous) (diff)

comment:2 Changed 3 years ago by yawning

Something like this perhaps:
https://git.schwanenlied.me/yawning/sandboxed-tor-browser/commit/a2b6668045f1947a94edde8b52766e10f43cf76e

Tor Browser will modify the unlocked prefs, but I'm not sure if that will actually do anything. I still think this is something that should just be done in Tor Browser (both in the "that's the correct place to fix this, if we aren't killing the JIT correctly" and "we should kill the JIT by default, possibly always" senses).

comment:3 in reply to:  1 ; Changed 3 years ago by cypherpunks

Replying to yawning:

IMO, if you think that more options should be set to *really* kill the JIT, then the patches should go into torbutton. If the JIT is just always evil, then the Tor Browser code should never JIT JS regardless of what the slider says.

Then for now, set the default slider higher?

(Also you're patching the wrong file, you want mozilla.cfg.)

Fixed.

Changed 3 years ago by cypherpunks

comment:4 in reply to:  3 Changed 3 years ago by yawning

Replying to cypherpunks:

Then for now, set the default slider higher?

Yeah, that will definitely happen before I tag the next release. I think "High" is the sensible default anyway, and people that want their random web-5.0 or whatever crap to work, should explicitly and consciously reduce their security, rather than the other way around...

I want to make it so that the mozilla.cfg gets force-updated based on versioning information (the git tag probably), so I'll do it after I fix that.

comment:5 Changed 3 years ago by yawning

Ok, the security slider on a fresh install will default to High (d8c9273d27489353a6250a106c34951fc2aa4322). As far as making more changes to the JIT settings, I'd want the other browser people to weigh in here.

comment:6 Changed 3 years ago by mcs

Cc: brade mcs added

comment:7 Changed 3 years ago by yawning

Keywords: sandbox-security added

comment:8 in reply to:  5 ; Changed 3 years ago by gk

Replying to yawning:

Ok, the security slider on a fresh install will default to High (d8c9273d27489353a6250a106c34951fc2aa4322). As far as making more changes to the JIT settings, I'd want the other browser people to weigh in here.

As a general matter I think we should try to avoid dealing with browser related settings outside of the browser itself. For one it makes things harder to debug if there different pieces of our products are taking care of the same settings and we open up the whole system to subtle bugs that might lie in Mozilla's code (they might never have tested whether the parts we use play together nicely). Plus this mixing of responsibilities has the tendency to make the whole system harder to analyze.

For now, having the slider set to "High" in the alpha Tor Browser sandbox is okay with me but we should think harder about that if we envision a future (as I do) where we only ship Tor Browser in the sandbox to our users. Maybe that's some kind of crazy Utopia but I want to see all users benefiting from the security guarantees the sandbox provides. And currently it seems to me we would drive quite a chunk of them away with that move. A lot of the web is broken in that mode (alas) and users will not blame Facebook or whomever for that but Tor Browser and choose a different (albeit less secure by default) product.

Regarding messing with the JIT preferences: what I said above in the first paragraph applies here as well + I feel we need to be careful to not introduce ways to fingerprint users of the Tor Browser sandbox that way. I am not sure whether flipping those prefs would already be bad. But I could imagine that some timing measurements might be able to reveal them, in combination with all the other prefs set on your particular slider mode. (Sure, if you have set your slider level to "High" this would be moot but then flipping those prefs in then first place would be superfluous as well)

comment:9 in reply to:  8 Changed 3 years ago by cypherpunks

Replying to gk:

As a general matter I think we should try to avoid dealing with browser related settings outside of the browser itself. For one it makes things harder to debug if there different pieces of our products are taking care of the same settings and we open up the whole system to subtle bugs that might lie in Mozilla's code (they might never have tested whether the parts we use play together nicely). Plus this mixing of responsibilities has the tendency to make the whole system harder to analyze.

I don't see how it would do that. The interpreter is likely still used in many parts of the browser, and the same code is shared with the JIT compiler. I don't see how the interpreter could break without simultaneously breaking the JIT compiler and JITed code. Empirically, JIT causes far more bugs. The fact that they are often security related is why it's so problematic. I think the best thing to do would be to disable JIT on all security levels, for all version of Tor Browser, sandboxed or not.

For now, having the slider set to "High" in the alpha Tor Browser sandbox is okay with me but we should think harder about that if we envision a future (as I do) where we only ship Tor Browser in the sandbox to our users. Maybe that's some kind of crazy Utopia but I want to see all users benefiting from the security guarantees the sandbox provides. And currently it seems to me we would drive quite a chunk of them away with that move. A lot of the web is broken in that mode (alas) and users will not blame Facebook or whomever for that but Tor Browser and choose a different (albeit less secure by default) product.

Disabling JIT would provide security benefits to JavaScript users without breaking Facebook and other sites. It's just a performance optimization which doesn't provide new functionality, after all. As for having the default set to high, to me at least that seems more like a feature which will not be present if the sandbox is added to the default browser. Or at least, not used at the default security setting. But considering the sandbox is, at the moment, only used by people who manually install it because they specifically want high security, setting the default to high seems reasonable.

Regarding messing with the JIT preferences: what I said above in the first paragraph applies here as well + I feel we need to be careful to not introduce ways to fingerprint users of the Tor Browser sandbox that way. I am not sure whether flipping those prefs would already be bad. But I could imagine that some timing measurements might be able to reveal them, in combination with all the other prefs set on your particular slider mode. (Sure, if you have set your slider level to "High" this would be moot but then flipping those prefs in then first place would be superfluous as well)

The sandbox is already trivial to fingerprint. I didn't think that was even a question. I can think of a few possibilities:

  • It blocks notoriously insecure libraries like gstreamer which default installs already have for instance, in order to reduce attack surface area. I wouldn't be surprised if more libraries are blocked. This completely disables support for certain media codecs, which an attacker can tell if you use media (though it does mean that it'll no longer be a piece of cake to exploit you through said media, even if ffmpeg is still around).
  • The proc filesystem (and sys?) is not mounted so system information is not accessible. I wouldn't be surprised if there is a way to trigger behavior in Firefox that only occurs when it cannot access the directory.
  • You could likely trigger a sandbox violation if you tried hard enough, leading to a crash from a fatal signal or an internal error. Good luck writing a good seccomp sandbox for a huge program with two dozen libraries if your threat model includes "don't let anyone who wants to know if the sandbox is in use trigger a syscall violation".
  • Having hardware acceleration disabled by blocking access to the control/render nodes is also fingerprintable (not that DRI nodes themselves don't also provide a powerful fingerprinting vector).
  • Reduced performance, through disabled JIT as you mentioned, or through replacing high-performance vDSO calls with regular syscalls (necessary to disable CR4.TSD to mitigate timing attacks, as planned in another ticket).
  • There might also be a way to trigger an intentional priority inversion in pulseaudio through Firefox so the priority-inheritance futex-disabling patches cause the browser to lock up (not that I can think of a way to do this, but I can't say it's impossible either).

Of course, simply having JavaScript enabled would cause far worse fingerprinting (audio context fingerprinting, math library fingerprinting, performance fingerprinting, clock skew fingerprinting, all the forms of GPU fingerprinting, battery API fingerprinting, security slider fingerprinting, HID fingerprinting, the list goes on). So I think the general idea should be that a user of the sandbox should not use JavaScript unless they want sandbox fingerprinting to be added to that list.

Personally, I think the highest security level for the sandbox should even disable JavaScript in the config entirely, since we know that NoScript bypasses exist, and I've heard of the existence of extant ones from several different places (not to mention @movrcx, if that counts), whereas bypassing a disabled config entry would seem to be next to impossible. But that's for another ticket and more thought, considering it would disable pdf.js (whether or not that'd necessarily be a bad thing for a sandbox on its maximum setting, I don't know...).

Last edited 2 years ago by cypherpunks (previous) (diff)

comment:10 in reply to:  1 ; Changed 3 years ago by cypherpunks

Replying to yawning:

FF46 does fix the issue with MPROTECT, but we won't get the benefit of that till ESR52.

Are you sure it does? From what I read, the old behavior was creating an RWX mapping, filling it with JITed byecode, then executing it. FF46 allows this to work with W^X by creating an RW mapping, filling it, then making it RX and executing it with the AutoWritableJitCode RAII class, according to https://jandemooij.nl/blog/2015/12/29/wx-jit-code-enabled-in-firefox/. But PAX_MPROTECT is much more aggressive than OpenBSD's implementation (which merely prevents RWX mappings from being created). PAX_MPROTECT additionally prevents a process from making an RW mapping executable again:

$ cat | gcc -x c -
#include <sys/mman.h>
#include <stdlib.h>
#include <stdio.h>

void main(void)
{
    char *m;
    int r;

    m = mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    perror("mmap");
    if (m == MAP_FAILED)
        exit(1);

    r = mprotect(m, 4096, PROT_READ|PROT_EXEC);
    perror("mprotect");
    if (r == -1)
        exit(1);
}

$ ./a.out
mmap: Success
mprotect: Permission denied

$ setfattr -n user.pax.flags -v m ./a.out

$ ./a.out
mmap: Success
mprotect: Success

Unless my understanding of how Firefox deals with OpenBSD's W^X protections are totally off, then it seems to me like it would not play nicely with PAX_MPROTECT.

comment:11 Changed 3 years ago by gk

Cc: gk added

comment:12 in reply to:  10 ; Changed 3 years ago by yawning

Replying to cypherpunks:

Unless my understanding of how Firefox deals with OpenBSD's W^X protections are totally off, then it seems to me like it would not play nicely with PAX_MPROTECT.

Yeah I was wrong sorry. The stupid package for my distribution sets a bunch of flags.

comment:13 Changed 3 years ago by yawning

Disabling JIT would provide security benefits to JavaScript users without breaking Facebook and other sites. It's just a performance optimization which doesn't provide new functionality, after all.

On a side note, I brought this up, and argued the case for this (in general, beyond the sandbox) at the browser meeting today and was informed that some sites have performance degradation that render them unusable without the JIT (ISTR mega.co.nz being mentioned).

Edit: #13069

Last edited 3 years ago by yawning (previous) (diff)

comment:14 in reply to:  13 Changed 3 years ago by gk

Replying to yawning:

Disabling JIT would provide security benefits to JavaScript users without breaking Facebook and other sites. It's just a performance optimization which doesn't provide new functionality, after all.

On a side note, I brought this up, and argued the case for this (in general, beyond the sandbox) at the browser meeting today and was informed that some sites have performance degradation that render them unusable without the JIT (ISTR mega.nz being mentioned).

See: #13069. And #9387 has some useful information about this as well as there have been performance measurements done and we got user feedback (see comment:38:ticket:9387 ff. for some discussion around that, and comment:32:ticket:9387) while have it disabled in the alpha series.

comment:15 in reply to:  12 Changed 3 years ago by cypherpunks

Replying to yawning:

Replying to cypherpunks:

Unless my understanding of how Firefox deals with OpenBSD's W^X protections are totally off, then it seems to me like it would not play nicely with PAX_MPROTECT.

Yeah I was wrong sorry. The stupid package for my distribution sets a bunch of flags.

Well shit... But isn't there some patch which OpenBSD (and iOS) uses which disables RWX pages entirely? I bet that could be implemented via an LD_PRELOAD hook so this can work on grsec, unless that patch was the one for FF46.

comment:16 Changed 2 years ago by arthuredelstein

Cc: arthuredelstein added

comment:17 Changed 12 months ago by yawning

Resolution: wontfix
Status: newclosed

This project is deprecated, and none of these will ever be fixed.

Note: See TracTickets for help on using tickets.