Uncovering a ChromeOS remote memory corruption vulnerability

Microsoft discovered a memory corruption vulnerability in a ChromeOS component that can be triggered remotely, allowing attackers to perform either a denial-of-service (DoS) or, in extreme cases, remote code execution (RCE). Following our D-Bus blog post that focused on Linux, we searched for similar D-Bus patterns on other platforms by auditing D-Bus services and their handler code. After locating a local memory corruption issue, we discovered the vulnerability could be remotely triggered by manipulating audio metadata. Attackers could have lured users into meeting these conditions, such as by simply playing a new song in a browser or from a paired Bluetooth device, or leveraged adversary-in-the-middle (AiTM) capabilities to exploit the vulnerability remotely.

After carefully reviewing the implications, a Microsoft security researcher shared the vulnerability with Google in April 2022 and also reported it with the Chromium bug tracking system. Fixes for the vulnerability, which is assigned as CVE-2022-2587 and has a Common Vulnerability Scoring System (CVSS) score of 9.8 (classifying the vulnerability as critical), were quickly released and have been successfully deployed to end users. We’d like to thank the Google team and the Chromium community for their professional resolution and collaborative efforts.

This research coupled with the recent release of ChromeOS Flex, which can convert various legacy PCs and Macs into Chromebooks, emphasizes the importance of analyzing and monitoring security for devices running ChromeOS. Moreover, as even the most hardened operating systems might contain security bugs, we emphasize the need for strong monitoring of all cross-platform devices and operating systems. The best approach for protecting unmanaged devices is by using Microsoft Defender for Endpoint’s device discovery capabilities to monitor suspicious traffic and help detect attacker activities on such devices.

In this blog post, we share some information about the vulnerability and examine how it could be triggered as well as the possible implications. Displaying how our cross-domain expertise helps us uncover new and unknown threats in the effort to continually improve security for all, we also share details from our research with the larger security community to emphasize the importance of collaboration to secure platforms and devices.

An overview of ChromeOS security

One well-known operating system that uses D-Bus is ChromeOS. ChromeOS is a Google-proprietary Linux-based operating system that runs on Chromebooks, Chromeboxes, Chromebits and Chromebases. ChromeOS is a closed-source system with open-source components that are derived from ChromiumOS, and the operating system uses Google’s own Chrome browser as its principal user interface.

In terms of security, ChromeOS is well hardened; some of the security features on ChromeOS include:

  • Hardened sandbox (called minijail)
  • Verified boot
  • Locked-down filesystem (mounted with noexec, nosuid, nodev) and dm-verity
  • Root user restrictions (SECURE_NOROOT)
  • When development mode is entered, all locally stored data is wiped

As with other modern browsers, exploiting ChromeOS usually requires chaining vulnerabilities together. Due to hardening measures in ChromeOS, discovering vulnerabilities became a specific niche and, therefore, the number of public vulnerabilities is quite low compared to other operating systems. ChromeOS vulnerabilities generally fall into one of three different classes:

  1. ChromeOS-specific logic vulnerabilities
  2. ChromeOS-specific memory-corruption vulnerabilities
  3. Broader threats such as Chrome browser vulnerabilities

In this case, the discovered vulnerability falls under the second class, ChromeOS-specific memory-corruption vulnerabilities.

Bug hunting

Having discussed and extensively researched D-Bus, we continued this analysis by enumerating the D-Bus services offered on ChromeOS. In general, D-Bus is an Inter-Process-Communication (IPC) mechanism that’s popular on desktop platforms, specifically Linux.

ChromeOS’s developer mode offers the dbus-send utility to send messages over D-bus. As there are many D-Bus services offered on ChromeOS (usually identified by the “org.chromium” prefix), we automated the process and used the dbus-send utility to fetch the full tree of services and their exported methods and signals.

Because most D-Bus services support the org.freedesktop.DBus.Introspectable interface, it’s possible to dynamically fetch exported methods and signals without reading the source code or reverse-engineering the binaries.

Fetching all the exported service names can be performed using the following command:

dbus-send --system --dest=org.freedesktop.DBus --type=method_call --print-reply /org/freedesktop/DBus org.freedesktop.DBus.ListNames

Using org.chromium.ResourceManager as an example, each service can then be enumerated for its declared methods and signals via the following command:

dbus-send --system --dest=org.chromium.ResourceManager --type=method_call --print-reply /org/chromium/ResourceManager org.freedesktop.DBus.Introspectable.Introspect

Considering that the more input a method receives, the higher the probability of finding a security issue, we then focused on methods that export arbitrarily large inputs, such as strings or arrays. It wasn’t long before we found an interesting service: org.chromium.cras.

The vulnerability

The org.chromium.cras D-Bus name is owned by CRAS (ChromiumOS Audio Server), which has a well-documented architecture under the ChromiumOS wiki pages. In essence, CRAS is a server that resides between the operating system and ALSA (Advanced Linux Sound Architecture) as a means of routing audio to newly attached audio-supporting peripherals, like USB speakers and Bluetooth headsets.

Reviewing the exported methods uncovered one method with a particularly interesting handling function: SetPlayerIdentity, which gets one string (an argument called identity) as an input. Since ChromiumOS is open-sourced, tracking the calls is straightforward:

  1. In cras_dbus_control.c, the handler function for SetPlayerIdentity is handle_set_player_identity, which extracts the identity argument from the D-Bus message and invoke the cras_bt_player_update_identity function.
  2. In cras_bt_player.c, the function cras_bt_player_update_identity that was called checks that the identity input value is not null and is different than the current player identity string (saved under player.identity). If so, it copies the identity variable to player.identity using the C library function strcpy. Of note, “player” is a global variable in the cras_bt_player module and includes an identity field in it, among others.

To the experienced security engineer, the mention of the strcpy function immediately raises red flags. The strcpy function is known to cause various memory corruption vulnerabilities since it doesn’t perform any bounds check and is therefore considered unsafe. As there are no bounds checks on the user-supplied identity argument before invoking strcpy (besides the default message length limitations for D-Bus messages), we were confident we could trigger a heap-based buffer overflow, therefore triggering a memory corruption vulnerability.

Heap-based buffer overflows can be the cause of multiple vulnerabilities, most notoriously leading to arbitrary code execution through various means. This could include overriding a function callback in an allocated object or overriding chunk metadata, which can trigger other unexpected behavior during the lifetime of a program.

Checking how the player.identity string is initialized shows that it’s set in the cras_bt_player_init function as the result of malloc(128), which means it’s allocated on the user’s heap with 128 bytes.

Code depicting the vulnerable function with the strcpy invocation in it
Figure 1. The vulnerable function with the strcpy invocation in it

Therefore, the vulnerability could be triggered using a single command line by sending the identity user-controlled D-Bus argument with more than 128 bytes, as displayed in our example code below:

dbus-send --system --dest=org.chromium.cras --type=method_call --print-reply /org/chromium/cras org.chromium.cras.Control.SetPlayerIdentity string:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

As most users don’t need to enable ChromeOS’s developer mode and, thus, can’t use the dbus-send utility, our next task was to find a way to trigger the bug without using developer mode.

Triggering the bug remotely

Thinking we spotted a local memory corruption issue, we wanted to better understand how to trigger the bug. Since the involved functions exclusively get triggered from D-Bus, we looked for functions that trigger the SetPlayerIdentity D-Bus method—if the arguments to those don’t have bounds checks, then those functions could be used to trigger the vulnerability.

Examining the open-source ChromiumOS repositories found that the CRAS audio client invokes the SetPlayerIdentity method (and exports a function with the same name). In turn, it’s called by the CRAS audio handler component’s method MediaSessionMetadataChanged, which extracts the identity from a metadata structure representing a song’s title:

Code depicting SetPlayerIdentity triggered from metadata changes
Figure 2. SetPlayerIdentity triggered from metadata changes

At this point, it was clear that the vulnerability could be triggered via changes to the audio metadata. Looking for MediaSessionMetadataChanged invocations revealed two interesting cases that could both be triggered remotely:

  1. From the browser: the browser’s media component invokes the function when metadata is changed, such as when playing a new song in the browser.
  2. From Bluetooth: the media session service in the operating system invokes the function when a song’s metadata changes, which can happen when playing a new song from a paired Bluetooth device.
Call tree depicting how browser or bluetooth devices can trigger MediaSessionMetadataChanged, then SetPlayerIdentity to be sent over D-Bus, triggering handle_control_message, then handle_set_player_identity, and finally the vulnerable function: cras_bt_player_update_identity.
Figure 3. Call tree displaying how browser or Bluetooth media metadata changes ultimately trigger the vulnerable function

Implications and reporting

We reported the vulnerability to Google in April 2022 as a part of the Chromium bug tracking system and were assigned Issue 1320917, which immediately got assigned as a priority 1 security bug. In parallel, we tracked the issue internally in Microsoft Security Vulnerability Research (MSVR), while using OSINT to look for indications of that vulnerability being used in the wild. We did not find any indications of in-the-wild exploitation.

The impact of heap-based buffer overflow ranges from simple DoS to full-fledged RCE. Although it’s possible to allocate and free chunks through media metadata manipulation, performing the precise heap-grooming is not trivial in this case and attackers would need to chain the exploit with other vulnerabilities to successfully execute any arbitrary code. Given the potential impact of the vulnerability, coupled with the fact that it could be remotely triggered, it’s a security risk that justifies the bug priority and how fast the fix was issued.

We were impressed with the speed of the fix and the effectiveness of the overall process. Within less than a week, the code was committed and, after several merges, made generally available to users. We thank the Google team and the Chromium community for their efforts in addressing the issue.

Improving security for all through research and threat intelligence sharing

As the threat and computing landscape continues to evolve, Microsoft strives to continuously improve security for all through research-driven protections and collaboration with customers, partners, and industry experts, regardless of the device or platform in use.

To defend against the evolving threat landscape, organizations must closely monitor all devices and operating systems across platforms, including unmanaged devices. Unmanaged devices are sometimes ignored or missed by security teams at join time, making them attractive targets for compromising, quietly performing lateral movements, jumping network boundaries, and achieving persistence for the sake of launching broader attacks. Microsoft Defender for Endpoint’s device discovery capabilities help organizations find certain unmanaged devices, including those running ChromeOS, and can detect if they are being operated by attackers when they start performing network interactions with servers and other managed devices.

Microsoft security researchers continually work to discover new vulnerabilities and threats, turning knowledge of a variety of wide-reaching issues into improved solutions that protect users and organizations across platforms every single day. This case displays how vulnerability disclosures and threat intelligence sharing are essential to effectively mitigate issues and protect users against present and future threats. Moreover, by expanding upon our prior research, we can also continue to make positive contributions to the overall security of devices worldwide, even on platforms we currently don’t directly support.

Jonathan Bar Or

Microsoft 365 Defender Research Team

READ MORE HERE