Virtually Unlimited Memory: Escaping the Chrome Sandbox
googleprojectzero.blogspot.com
googleprojectzero.blogspot.com
To obtain a reference to an object that is managed by a smart pointer, you would have to, at the minimum, explicitly dereference that pointer with *. In most cases, this also happens in an argument context, and the caller will maintain the pointer. It breaks when the pointer that's managing lifetime is a part of mutable state that the callee can touch somehow without returning - then it can cause the object to be freed while still holding a non-counting reference to it. At that point, you basically need something like Rust lifetime/ownership tracking to prevent such unsafe situations from happening.
I wish there was a nice way to remove a need for such things, like a weak pointer that work with unique_ptr, but I do not think it is possible to do this while preserving zero overhead implementation.
The only practical solution I can think of is a shared_ptr-like object limited to have unique_ptr semantics. This will have overhead, but it could be worth it for the security gains.
Solaris on SPARC, iOS and eventually Android, all make use of memory tagging.
It doesn't cover all cases, but still better than not having it at all.
I think the type of pointer you're asking for basically does exist. First, you want to distinguish the cases when you want a "full featured" weak pointer that can gracefully handle the destruction of its target object [1] (rarely the case), or you just want a non-owning pointer that detects when the prorammer screws up and lets the target object be destroyed prematurely [2].
The latter is essentially just a non-owning reference counting pointer. The optimizer should be able to discard matching increments and decrements of the reference counter in many cases.
> This will have overhead, but it could be worth it for the security gains.
The performance cost of avoiding "unsafe" C++ elements is measurable, but reasonably modest [3].
[1] https://github.com/duneroadrunner/SaferCPlusPlus#registered-...
[2] https://github.com/duneroadrunner/SaferCPlusPlus#norad-point...
[3] https://github.com/duneroadrunner/SaferCPlusPlus-BenchmarksG...
It would be nice if we could acknowledge this rather than rewrite everything again and still fail.
if the protections that sandboxing offered were so flimsy as to be a false sense of security, that would be an argument against sandboxing. but that does not seem to be the situation we're in.
I'm sure it somehow manages to happen here and there in Java code that's specifically managing data meant to be executed and a bug caused it to be mixed up with data not meant to be executed, but generally it's not something that happens in Java if you don't reach for APIs for starting programs. In C/C++, any code could potentially have any issue that disastrous. The fact that bugs enabled remote code execution can happen anywhere, not just near specific dangerous API calls or language features, is a uniquely C/C++ problem.
https://www.darkreading.com/informationweek-home/why-the-jav...
You may also be interested in JNI. Java is also written in C or some such, so it can't escape the realties of that language. Even if it would not be, it would probably run some kind of JITted assembly.
https://heimdalsecurity.com/blog/java-biggest-security-hole-...
Unless you're talking about some platonic ideal of Java, real world implementations have memory bugs.
Bug enabled RCE can't happen anywhere in a C codebase. It's comparatively rare, too, to other classes of bugs, and depends on how much an attacker can control the input.
>https://heimdalsecurity.com/blog/java-biggest-security-hole-...
I'm specifically talking about the rate and severity of bugs in non-malicious code. Java's sandboxing and plugin aspects were horribly flawed and were rightly put out to pasture.
>Bug enabled RCE can't happen anywhere in a C codebase. It's comparatively rare, too, to other classes of bugs, and depends on how much an attacker can control the input.
It's definitely not rare compared to the rate of RCE bugs in other languages. I'd be surprised if most C/C++ programmers who have written their own non-trivial programs haven't written at least one memory-mishandling bug that allowed RCE. I really don't think the fraction of Java programmers who have ever mis-used JNI or deserialization is nearly that high.
There is still too much code that relies on it, that could have been written without such constructs.
C++ has the best memory model out there. Why do they want to extract raw C pointers from smart ones? This seems like a bad practice if you need to do that.
Use-after-free is the least common case of CVE in C++ : https://resources.whitesourcesoftware.com/research-reports/w...
I will grant that the fuzzing targets were browsers, pdf readers, office suites and stuff which have some characteristics not shared by all C++ software.
In particular, a script engine and usually a way for “native” objects to get referenced or frobbed by scripting. Along with complex trees of object references, custom allocators, object pools etc.
I would have loved to have written a more substantive response but I didn’t want to download the PDF and check their analysis because they wanted to harvest my email.
What I can say is that a large proportion of real-world attacks where a hapless user gets pwned by a malicious file, document or script have a UAF somewhere down below as a root cause.
Not sure how UAF as a bug class got rated “least common” in their analysis? Would love to see some insight here, it doesn’t mesh at all with my lived experience but of course I could be missing something.
huh, they didn't ask me for any email (or maybe ublock handled it).
After looking at the paper I think the issue is that they are counting CWEs assigned to CVEs, but CWE assignment to CVEs is not very granular / accurate.
For a contrasting point of view here’s an alternative reference:
“FreeSentry: Protecting Against Use-After-Free Vulnerabilities Due to Dangling Pointers” - https://pdfs.semanticscholar.org/3829/df26d4ce686251b9b50308... - “In 2011 and 2012, the most exploited memory errors for Microsoft products were use-after-free vulnerabilities. It was also the most exploited vulnerability for both Windows Vista and Windows 7 and is the most common type of memory error that occurs in Internet Explorer.”. Ok, that’s a bit old. Also why doesn’t it show up in the data?
In an unscientific sanity check (bit slow to do because on mobile) I am not sure UAF is getting all the credit it deserves in CVE classification.
For example https://www.cvedetails.com/cve-details.php?t=1&cve_id=CVE-20... is a UAF (https://www.exploit-db.com/exploits/46184) but is listed as CWE category 264 (permissions, privileges and access controls).
CVE-2017-8540 https://www.cvedetails.com/cve/cve-2017-8540 is also a UAF but is listed as CWE category 119 (memory corruption / code exec), ref: https://www.exploit-db.com/exploits/42088
I think I could find a lot more. CWE assignment to CVEs is not really an exact science. I suspect UAFs are getting under-counted because the bugs just went into “privesc” or “memory corruption / buffer overflow” buckets.