New issue
Advanced search Search tips
Starred by 1 user

Issue metadata

Status: Fixed
Owner:
Closed: Mar 2018
Components:
EstimatedDays: ----
NextAction: ----
OS: Mac
Pri: 2
Type: Bug-Security



Sign in to add a comment
link

Issue 822424: Security: Local Privilege Escalation due to unsafe use of Distributed Objects in Google Software Updater on MacOS

Reported by ianbeer@chromium.org, Mar 15 2018 Project Member

Issue description

(This is a tracking bug. The issue has already been fixed upstream by the Google Software Updater.)

Google software updater ships with Chrome on MacOS and under certain circumstances installs a root service (com.google.Keystone.Daemon.UpdateEngine)
which lives here: /Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/GoogleSoftwareUpdateDaemon

(Note that the system version of this service is not installed under all circumstances - it will installed be if chrome is configured to update for all users, or if some other google software is installed eg Chrome Remote Desktop.)

This service vends a Distributed Object which exposes an API for updating google software running on the machine.

Distributed Objects are very very hard to safely use across a privileged boundary.

The GoogleSoftwareUpdateDaemon process attempts to "sanitize" objects passed to it by serializing
and deserializing them to a plist, however this still means we can attack the plist serializing code!

Specifically, with D.O. we can pass proxy objects which allow us to overload all objective-c
method calls. We can make the plist code think it's serializing a CFString, and then change our behaviour
to return a different CFTypeID so we become a dictionary for example.

The plist serialization code is not written to defend against such proxy objects, because D.O. should not be
used across a privilege boundary.

In this case I'm targetting the following code in CoreFoundation:

static void _flattenPlist(CFPropertyListRef plist, CFMutableArrayRef objlist, CFMutableDictionaryRef objtable, CFMutableSetRef uniquingset);

plist will be a proxy for the FakeCFObject I define. We can first pretend to be a CFString to pass some other type checks, then become a CFDictionary
(by simply returning a different return value for the _cfTypeID method.) We can then reach the following code:

    CFIndex count = CFDictionaryGetCount((CFDictionaryRef)plist);
    STACK_BUFFER_DECL(CFPropertyListRef, buffer, count <= 128 ? count * 2 : 1);
    CFPropertyListRef *list = (count <= 128) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2 * count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory);
    CFDictionaryGetKeysAndValues((CFDictionaryRef)plist, list, list + count);
    for (CFIndex idx = 0; idx < 2 * count; idx++) {
      _flattenPlist(list[idx], objlist, objtable, uniquingset);
    }

Since we're not a real CFDictionary we can return an arbitrary value for count. If we return a value < 0 it will be used to calculate the size of a stack buffer.
By passing a carefully chosen value this lets you move the stack pointer down an arbitrary amount, off the bottom of the stack and potentially into another thread's stack
or on to the heap, allowing memory corruption.

There will be dozens of other places where attack-controlled proxy objects will be able to interact with system code that was not written expecting to have
to deal with proxy objects.

The correct fix is to not use Distributed Objects across a privilege boundary, as per Apple's advice:
https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/DesigningDaemons.html

build this PoC:
clang -o ks_r00t ks_r00t.m -framework Foundation -framework CoreFoundation

This PoC exploit will run the shell script /tmp/x.sh as root.
 
ks_r00t.m
9.3 KB View Download

Comment 1 by awhalley@google.com, Mar 15 2018

Labels: Release-0-M66 M-66 CVE-2018-6084

Comment 2 by sheriffbot@chromium.org, Mar 16 2018

Project Member
Labels: -release-0-m66
This bug is a regression and does not impact stable. Removing incorrectly added Release- labels.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot

Comment 3 by sheriffbot@chromium.org, Mar 16 2018

Project Member
Labels: -Restrict-View-SecurityTeam Restrict-View-SecurityNotify

Comment 4 by sheriffbot@chromium.org, Mar 27 2018

Project Member
Labels: Security_Impact-Beta

Comment 5 by awhalley@google.com, Apr 17 2018

Labels: Release-0-M66

Comment 6 by awhalley@google.com, Apr 17 2018

Labels: -Security_Impact-Beta Security_Impact-Stable

Comment 7 by awhalley@chromium.org, Apr 25 2018

Labels: CVE_description-missing

Comment 8 by tsepez@chromium.org, May 3 2018

Components: Internals>Installer

Comment 9 by sheriffbot@chromium.org, Jun 22 2018

Project Member
Labels: -Restrict-View-SecurityNotify allpublic
This bug has been closed for more than 14 weeks. Removing security view restrictions.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot

Comment 10 by sheriffbot@chromium.org, Jul 28 2018

Project Member
Labels: -Pri-3 Pri-2

Comment 11 by awhalley@chromium.org, Jan 4

Labels: -CVE_description-missing CVE_description-submitted

Sign in to add a comment