The browser is the worst sandbox ever designed
bentrask.com
bentrask.com
I am sorry, security guys, but unless it's military-grade software, security is just another feature. And it is not a highest priority one. Of course, security would be easier if there were no new features or spec changes. And software development in general would be much easier if there weren't any of those pesky end users.
Which is a good thing, probably. Otherwise, you'd be mostly out of your jobs. Security is always changing, chaotic battlefront.
Having said that, sandboxing is a good idea. Theoretically. But it is really hard to implement right — attack surface on the edges of the boxes is quite large. Remember those Java applets? They were sandboxed neck-deep, with excellent security model. Did it help?
I completely disagree: security is the foundation of any software system. Without security, the system simply cannot be trusted to do anything correctly, not even add 1 and 1 together. For far too long we've relied on our systems being accidentally correct rather than deliberately secure; we need to fix that.
If something's mathematically possible, then it will happen. We need to build systems where security flaws are impossible, because then … they won't happen.
> So I personally consider security bugs to be just "normal bugs". I don't cover them up, but I also don't have any reason what-so-ever to think it's a good idea to track them and announce them as something special.
Linus Torvalds - http://yarchive.net/comp/linux/security_bugs.html
Here's a lengthier article about it - http://www.washingtonpost.com/sf/business/2015/11/05/net-of-...
Not really. For a simple example, imagine a calculator software which has been mathematically proven to work correctly for any number with 30 or less digits, but which overflows a fixed-size buffer if the user inputs a number with more than 30 digits. That software could absolutely be trusted to add 1 and 1 together, while still having a security issue.
Java applets are another example of security competing with features. Any part of the runtime could cause an exploit. If the sandbox had been separate it would've been safer.
For Counter Strike, sure. But for things like spreadsheets or web browsers, hundreds of thousands or millions of people working in arms manufacture or intelligence are going to be using your software and it needs to not leak designs to foreign intelligence agencies or competitors.
I started off talking about the browser, not the F-35, but by the end the line blurred. :-)
Then use Qubes OS:
You can set up a separate VM in Qubes OS purely for browsing. That way, even if your browser was compromised, it would be isolated from your other applications.
developers do...
... and they (might) use something like Rust... they could also (believe it or not) use C.
It is also the long set of compiler specific behaviors, sometimes version specific even, and UB. All of each very hard for a human to keep all the time on its head.
Hence why we have things like static analyzers, MISRA and Frama-C and still falls through the cracks.
Even unsafe Rust offers more guarantees than C. But is a spot where you can remove the guard rails.
C was/is an amazingly performant language, but you're kidding yourself if you believe that most developers can write software as securely in it as they could in Rust.
Every sandboxed app ever has needed native access of some sort to do something useful.
The best example of this difficulty is probably graphics (WebGL). To provide a compelling user experience, the API must allow apps to upload almost arbitrary code (shaders).
http://www.kitguru.net/gaming/security-software/carl/webgl-e...
http://www.contextis.com/resources/blog/webgl-more-webgl-sec...
http://www.pcworld.com/article/227438/dangerous_webgl_flaw_p...
There haven't been any real WebGL exploits I know of. No you can't upload arbitrary shaders either. They're validated and then re-written by the browsers.
My feeling having written a few GLSL shaders is that the language is already sandboxed by design, making it a safer environment to execute 'arbitrary code' than just about any other viable option. In a shader, I get access only to the input I'm given, and can only affect the color of a pixel, and nothing more.
The 'graphics memory theft' exploit (your 2nd link) cannot have been a primary result of a GLSL exploit, as I understand it. That would have required use of an improperly authorized API call like glGetPixels(), and so arbitrary code execution is not the issue there. WebGL's API design and the browser's sandboxing are accountable -- and anyway, it sounds like that got fixed a long time ago?
The first link says the main risk is crashing, so some sort of DOS attack I suppose. That is true of all computing systems, and also isn't exclusive to arbitrary code execution. I'd speculate it's probably easier to get WebGL to crash using the API than shaders. Either way yes, this is a risk, but not particularly specific to WebGL and not the worst kind of security risk in most environments unless combined with something else. (I grant that crashes in hospital equipment, for example, is a high security risk. Then again, most hospitals don't actually let their sensitive equipment browse the web for a reason.)
What other real risks are there, to the average person surfing the web?
If we can't do that, how much will sandboxing help? Sure, we can make a much smaller surface that we expose - let's say 1% of the size of what the browser currently exposes. Will that be good enough though? Xen's surface is about as small as you can get for a reasonable general-purpose sandbox, and, per the article, Xen has a lot of vulnerabilities too.
I think the only option is to push the defect rate down to zero. (This may be impossible; if so, we're all going to die. Computing power will inevitably advance to the point where any vulnerable system can be cracked by a lone terrorist, and economics and our inability to coordinate ensure that power plants, water treatment facilities, automated bioengineering facilities etc. are going to be computerized.)
Rust is, I think, worthwhile as a step on the road towards provably correct programs - memory management isn't everything, but it's something. Sandboxing OTOH feels like a dead end, because it's inherently ad-hoc and unprincipled.
I don't think the math is on your side. As the defect rate approaches zero, there are diminishing returns to pushing it lower. On the other hand, the attack surface effect becomes overwhelming. Addressing both at once will be far more effective than concentrating on one or the other.
You might be right that in the long run, the defect rate needs to be 0.0. But that is a long ways away. Once we've picked the low-hanging fruit (including perhaps a provably correct sandbox), then we can start thinking about how to prove the correctness of random applications.
Huh? That's not how it works, is it? If we want to minimize X * Y and we currently have X = 50 and Y = 5, it's much more efficient to focus on bringing Y down.
> Once we've picked the low-hanging fruit (including perhaps a provably correct sandbox), then we can start thinking about how to prove the correctness of random applications.
"low-hanging fruit" tends to mean doing unprincipled things that can't be generalized / don't contribute anything in the long term, right? My view is that there's limited value in lowering the rate of security flaws in ways that aren't on the path to bringing it to zero. Getting it to zero will be valuable; halving it isn't really (there's some economic value in reducing the frequency of breaches, but not enough). So I don't think ad-hoc countermeasures are worthwhile.
To the extent to which a sandbox can be written in a principled/provable way it will be valuable. I'm not at all convinced that a general-purpose sandbox is possible, but that's a different question. (The techniques of factoring a program into pieces with the minimal capabilities that they need are valuable, but I think this needs to be done far more holistically than is possible with a sandbox; the security design needs to reflect the program design, because whether particular operations are safe or not is a function of the application-specific context. But this is very much speculation on my part)
I guess I see 0 as the asymptote. Like if you're already at 99.99% reliability, adding another 9 is quite hard. On the other hand, if you're at 10%, then there are big gains to be had.
> "low-hanging fruit" tends to mean doing unprincipled things that can't be generalized / don't contribute anything in the long term, right?
I think sandboxes generalize much better than application-specific proofs. Once you have a provably correct sandbox (which I think is possible today, if you exclude things like 3D acceleration), you can run whatever you want in it: old software, games, Flash, Windows 98. Application-specific proofs only work for applications written in the approved way.
What would a generic sandbox enforce? That an application never accesses the network? That it never accesses the local filesystem? That it never communicates with another process? Browsers need to do all those things and more. I think you need application-specific knowledge to be able to enforce the restrictions that matter.
To some extent, this is a question of what the requirements are. If a sandbox limits a browser to accessing certain files (a la chroot), is that secure? Or does it need to be more fine grained? This isn't something that can be proven, it's mostly a matter of user interface design.
I think there are good arguments for keeping security requirements relatively simple and coarse (including ease of implementation and making sure users can understand what guarantees are offered).
1. It's likely to have bugs because it's mixed with a constantly changing kernel and can't be proven correct
2. It isn't fine-grained enough
If pledge were completely bulletproof, but still limited in terms of what it could restrict, would that still be worthless? Granularity is an interesting problem but it's more subtle than typical criticisms of ad-hoc mitigations.
I think the idea that you can allow a program to get itself in an attacker-controlled state and that will be ok as long as you blacklist what the program can do is fundamentally unworkable. So yes, I think pledge-like approaches are always going to be worthless in the long term - if the program is under the attacker's control, it will almost certainly have enough access to be able to do damage (with a sufficiently skilled attacker), because every program does something, particularly if we're talking about a large and complicated program like a browser. (You could potentially segregate the browser into multiple processes with distinct responsibilities, but I'm not convinced that helps, because those processes still have to send commands to each other and so an attacker who can subvert one can probably control the others).
If it had the level of granularity to express restrictions like "should be able to write only files that the local user has chosen via the save dialogue" then it might become an effective security layer, but at that point we're not really talking about a sandbox any more.
FWIW, Apple's Mac sandbox and Sandstorm both have open/save support. It's definitely user-friendly and nice polish, but I don't think it's a make-or-break issue.
> "should be able to write only files that the local user has chosen via the save dialogue"
The web platform, incidentally, supports this! You can invoke a "choose file" dialog, and then your web page gets access to the one file the user chose.
In capability-based security circles, this pattern is called a "Powerbox". The pattern works especially well in capability systems, where it can be used to choose more than just files.
For anything halfway complex, you can't reasonably find all the bugs for precisely the same reason you can't reasonably get full path code coverage out of your tests. The possibilities around interactions (this is where bugs mostly live) scale very, very high as more components are involved. A simple example is that ten boolean flags or checkboxes that interact with each other--or, more accurately, possibly interact with each other, if you can't prove they don't--means 2^10 possible states to check. Most things don't just take two values. Add system-level and user-level non-determinism and good luck.
In quality, we handle this via testing by state equivalence, predicting how common a set of interactions will be and prioritizing accordingly, and other shortcut techniques meant to put a finite amount of effort around reducing risk to whatever won't sink your product, but it's almost impossible to reduce to zero. You have to spend a metric crapton of money to do it, which is why A) you mostly only see that kind of goal in stuff like aerospace and B) planes cost an awful lot.
I haven't even gotten to the part where you don't know all the possible defective side effects that could be there and probably wouldn't think to look for everything possible even if you theoretically could. Keep in mind that you're treating the application behavior as inherently untrustworthy, so you can't just assume you know how it'd fail either. For all you know it'll interact with an OS bug in a novel way. There are surprises everywhere.
The sandbox idea is a really good one because it means you can do this once, presumably in a system of controlled complexity architected in a way to be highly testable and highly reviewable. That's your best bet for getting near zero defects: high modularity with strict interfaces and limited interactions all of which are highly deterministic. You definitely won't get that with something as complex as an entire browser platform.
Making the job as small and easy as possible and only doing it once are probably the key here.
There is "Browser in the Box": http://www.sirrix.com/content/pages/BitBox_en.htm
And then there was also VMWare's Secure Browser Appliance (in 2005! although I cannot find any recent mentions of it): https://rcpmag.com/articles/2005/12/13/vmwares-secure-browse...
Taking this to a new level by implementing a sandbox tailor-made for this purpose might be a worthwhile approach. However, for it to be effective you will always need to inconvenience your users: As soon as the browser running in the sandbox has access to the full filesystem, you are back to where you started. And if the browser does not have full access to the filesystem (but e.g. only to a specific "Downloads" folder as in the current sandboxes) you inconvenience your users: E.g. for uploading files, you first need to copy them to the Downloads folder.
No, you need a "portal" or "intent" or "capability" whatever you want to call it. Browser asks sandbox to ask user to select a file, and browser gets that file. Android has been able to do this for a while, but full sdcard access is so easy that everyone uses it instead. Flatpak nee xdg-app will do this.
I mean, with the number of VM languages out there like Java, PHP/Hack, .NET, various LISPs, etc. you'd figure that some hardware support for boxing/tagging/GC would be a standard feature by now, but nope. Instead, the best approach we have for secure and performant software with x86 is 1) write complicated system in tedious assembly++ 2) run under VM.
The funny thing is that it all once was a standard feature of hardware, back in the Lisp Machines days.
It was the fact that AT&T could not charge money for UNIX and made its source available for free that changed that.
Check Burroughs, Xerox PARC Star, UK Royal Navy Flex among a few others.
... isn't that the job of a normal OS kernel? The article may call it a "sandbox" but it sounds like normal access control in any OS, not much sandboxing left when asking for all the apis?
These days just about every application is user-hostile in some way. Even open source Windows applications, depending on where you download them from, might come with a hostile installer. Programs install background tasks. Programs track you.
Mobile operating systems have been a step in the right direction. But a good operating system should allow us to run whatever binaries we find anywhere on the Internet and not be able to do anything harmful to us.
Driver protections in the OS prevent people who write popular software from remotely taking over large numbers of computers. They're not intended to protect against your laptop getting physically stolen.
The OP here, on the other hand, I'm still confused what precise threat model it's concerned about :)
"When asked whether it would be prudent to build a defensive wall enclosing the city, Lycurgus answered, "A city is well-fortified which has a wall of men instead of brick."
https://en.wikipedia.org/wiki/Laconic_phrase
"It is said that if you know your enemies and know yourself, you will not be imperiled in a hundred battles; if you do not know your enemies but do know yourself, you will win one and lose one; if you do not know your enemies nor yourself, you will be imperiled in every single battle."
https://en.wikiquote.org/wiki/Sun_Tzu
Moral: https://en.wikipedia.org/wiki/Code_signing + https://en.wikipedia.org/wiki/Web_of_trust + https://en.wikipedia.org/wiki/Quality_assurance
I would like an OS-level sandbox that doesn't treat its users like idiots. But this is not what's currently happening (especially the "don't treat the user like an idiot" part). iOS and Android have always been closed platforms, and OSX and Windows are currently locked down at high speed.
The browser platform might be a mess, but it's less of a mess than the sum of all the underlying operating systems the browser is running on, and the only open-yet-secure platform that exists.
https://blogs.gnome.org/mclasen/2016/07/08/portals-using-gtk...
Specially in the way that they are also moving away from C as well.
Furthermore, even if applications are sandboxed, that only prevents vulnerabilities from being exploited with other applications. A web page able to compromise my web browser would still be able to get all my browsing history, my usernames, my passwords… The sandbox would not help with that.
This does not necessarily make it worth it to rewrite everything in Rust, but it is worth considering writing any new software in Rust instead of C, especially if this new software is at a low level like compilers, the kernel, and libraries. Other applications can be written in a higher-level language with garbage collection and static typing instead of C.
You're right that stuffing all of Chromium into a single sandbox would not be very good, because pages would be able to attack the browser (history, passwords, etc) and each other. You'd want to run each renderer in its own sandbox (which to some extent Chrome already does).
What is the basis for this comment? It sounds reasonable, but how would one test it?
Edit: "factoring" is one word for it.
Many features of high level languages are attempts to add modularity and thus break the complexity up into manageable pieces. Functions, classes with "private" features, UNIX-style[1] tools, and other types of modular programming are ways to separate local complexity from the global environment.
A complex module with many internal parts adds a lot of complexity to a program, but by restricting the interfaced we greatly reduce how much complexity is exposed to the parent environment. A simple interface with only a few parts can hide many more parts that would have otherwise been potential interactions with the global environment (bug/attack surface).
Even better, well defined interfaces allow the separate modules to be implemented and debugged separately. Which would you rather debug? One 1000-line program or 10 separate 100-line programs? While they are the same amount of code, smaller programs are much easier to understand[2].
[1] http://www.catb.org/esr/writings/taoup/html/ch01s06.html#id2...
[2] http://www.catb.org/esr/writings/taoup/html/ch01s06.html#id2...
TL;DR - "KISS: Keep It Simple, Stupid!"
Modularity is not a magic wand (Brooks' "silver bullets" aren't an strong enough concept for what you are debunking) that makes all the problems of software developing go away.
You are fighting a straw men. Yes, it's a straw men that some people argue that it's a good fighter, but I'd rather just ignore those people.
By the other side, you are attacking it by an angle that I've never thought about.
* The OS should be the sandbox. It has all the features of a sandbox; they just need to be secure.
* In addition to userland processes, if we trust the compiler of a high-level language without unsafe features (like Java), we should be able to compile programs with it and load them directly into the kernel. (User policy is enforced by the compiler.) This is similar to what Singularity does, and it has a number of advantages. First, since there is no task-switch boundary, we reap a speed benefit. Second is attendant to this; since there is zero cost to switch processes, people are encouraged to separate their applications into multiple processes, encouraging modularity.
* Second, the OS kernel itself should be written in a high-level language.
* Finally we need security in the compiler itself. This is achieved through the Futamura projections. That is, all that needs to written of the compiler is an interpreter; the actual compiler is condensed into the notion of a partial evaluator; the partial evaluator essentially figures out how to substitute any given program into the interpreter efficiently, hence compiling it.
He is writing that the current browser sandbox model is not secure–all in a dramatic, clickbaity manner.
After many esoteric lines, then he says (maybe it's the tl;dr)...
"We need a highly secure (ideally provably secure) sandbox that doesn’t have any features! Then, you can run an insecure browser inside, where security doesn’t matter."
Then again some more lines of confusion.
So, what does he suggest? Putting the browser in a VM?
tl;dr: Right now there is a competition between features and security, and security is losing. By separating them, they wouldn't need to compete, and we could have both. It isn't a good idea for a sandbox to directly handle things like CSS transforms.
Is my writing really esoteric?
The idea sounds ok once you clarified at the first glance but how does it work, will it work, what would be the implications. And many more questions. Currently I see the core idea surrounded by many vague statements.
And btw you can do this today already: just start a VM with a browser (might be a bit resource heavy and the integration into the main OS subpar). Or Docker with a browser. Not sure though if latter fulfills your security requirements.
But at the end, the browser is more then an isolated piece of software in a VM. An integration on OS-level is required and trivial stuff like a full-screen mode is possible but might complicate matters within a VM. Or 3d acceleration and everything where a direct access to the API is required. And suddenly the VM is piping everything through the main OS because a browser just needs access to all the OS APIs and then you end at square 1. So, I also find your idea a bit confusing.
But I don't know what sandbox escapes for Chromium look like? My guess would be that it involves things like browser plugins, or nasty stuff like WebGL. In which case sandboxing isn't failed, we're just not doing enough of it.
Blink raised the implementation quality bar with it’s tab-per-process design and privilege dropping.
These were Chrome features, not Blink features. Blink didn't even exist when they were developed.
Call me crazy, but security sensitive application should not have direct access to 3D acceleration, microphone, camera, USB etc.
> (It should also be possible to block or control access to each of these.)
The good news is that the capabilities of the sandbox don't need to be every-expanding, the way browsers have been. The sandbox should support everything the hardware can do, and then there are policy decisions about what capabilities web pages actually get.
Until you can emulate a hardware GPU in software at the same performance point, your sandbox is unusable. The web is more than text.
[1] Putting USB anywhere near the web may be the stupidest idea I've ever heard. Attempts to add USB access to the browser should be seen as an attack. A camera or microphone can be a serious security problems, but failures in those features can (at least theoretically) be limited to features related to a specific hardware. Failures related to the USB buss can grant access to a lot of hardware that was never designed for security.
- Strip down the features of the application to minimize attack surface. (see bloated, badly designed web apis...)
- Don't let sensitive code be produced by interns.
What if I (and users) want those features? Ah, I remember, just install a plugin, which is closed source thus more secure... wait a minute.