exploit-db-mirror/exploits/multiple/dos/46475.txt
Offensive Security 55fab34db7 DB: 2019-03-02
10 changes to exploits/shellcodes

Linux Kernel 3.10.0 (CentOS7) - Denial of Service
Linux Kernel 3.10.0 (CentOS 7) - Denial of Service
Google Chrome < M72 - PaymentRequest Service Use-After-Free
Google Chrome < M72 - RenderFrameHostImpl::CreateMediaStreamDispatcherHost Use-After-Free
Google Chrome < M72 - Use-After-Free in RenderProcessHostImpl Binding for P2PSocketDispatcherHost
Google Chrome < M72 - FileWriterImpl Use-After-Free
tcpdump < 4.9.3 - Multiple Heap-Based Out-of-Bounds Reads
Linux < 4.14.103 / < 4.19.25 - Out-of-Bounds Read and Write in SNMP NAT Module
macOS XNU - Copy-on-Write Behavior Bypass via Mount of User-Owned Filesystem Image

Cisco WebEx Meetings < 33.6.6 / < 33.9.1 - Privilege Escalation
2019-03-02 05:01:54 +00:00

53 lines
No EOL
2.9 KiB
Text

There's a use-after-free in the implementation of the FileWriter component of the mojo bindings for the filesystem API.
The browser-process side of this API is defined in https://cs.chromium.org/chromium/src/third_party/blink/public/mojom/filesystem/file_writer.mojom?type=cs&sq=package:chromium&g=0
The method we are interested in is the Write method - this takes a parameter of type blink.mojom.Blob. The implementation of this method is as follows:
void FileWriterImpl::Write(uint64_t position,
blink::mojom::BlobPtr blob,
WriteCallback callback) {
blob_context_->GetBlobDataFromBlobPtr(
std::move(blob),
base::BindOnce(&FileWriterImpl::DoWrite, base::Unretained(this),
std::move(callback), position));
}
Note that the last argument to GetBlobDataFromBlobPtr is a callback object bound to base::Unretained(this).
And the implementation of GetBlobDataFromBlobPtr:
void BlobStorageContext::GetBlobDataFromBlobPtr(
blink::mojom::BlobPtr blob,
base::OnceCallback<void(std::unique_ptr<BlobDataHandle>)> callback) {
DCHECK(blob);
blink::mojom::Blob* raw_blob = blob.get();
raw_blob->GetInternalUUID(mojo::WrapCallbackWithDefaultInvokeIfNotRun(
base::BindOnce(
[](blink::mojom::BlobPtr, base::WeakPtr<BlobStorageContext> context,
base::OnceCallback<void(std::unique_ptr<BlobDataHandle>)> callback,
const std::string& uuid) {
if (!context || uuid.empty()) {
std::move(callback).Run(nullptr);
return;
}
std::move(callback).Run(context->GetBlobDataFromUUID(uuid));
},
std::move(blob), AsWeakPtr(), std::move(callback)),
""));
}
However, the call to GetInternalUUID is a mojo interface method; and if the renderer instead of providing a handle to a browser-process-hosted Blob object instead provides a handle to a renderer-hosted Blob implementation, then during this call into the renderer we can destroy the renderer handle to the FileWriter, triggering the immediate destruction of the FileWriterImpl. When the callback is then subsequently called after GetInternalUUID returns, the base::Unretained reference to the stale object will be used.
To reproduce you need a local build of chrome; run the attached script
$ python ./copy_mojo_js_bindings.py /path/to/chrome/.../out/Asan/gen
$ python -m SimpleHTTPServer&
$ out/Asan/chrome --enable-blink-features=MojoJS --user-data-dir=/tmp/nonexist 'http://localhost:8000/file_writer.html'
Note that this is *not* a renderer bug; it's a browser process bug that's reachable from the renderer. The attached poc is using the MojoJS bindings to trigger the issue, but a compromised renderer could perform the same actions without any special settings.
Proof of Concept:
https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/46475.zip