Saturday, November 23, 2024

QuickShell: Sharing Is Caring about an RCE Attack Chain on Quick Share

Must read

Authors: Shmuel Cohen, Sr. Security Researcher | Or Yair, Security Research Team Lead

Google’s Quick Share is a peer–to-peer data-transfer utility for Android, Windows, and Chrome operating systems. It uses a variety of communication protocols—including Bluetooth, Wi-Fi, Wi-Fi Direct, Web real-time communication (WebRTC), and near-field communication (NFC)—to send files between compatible devices that are in close proximity to each other. 

Comparable to Apple’s AirDrop, Google originally developed a utility called Nearby Share with capabilities similar to that of Quick Share. In July 2023, Google even released a Windows version of the utility. However, in January 2024, Google announced it would join its Nearby Share technology with Samsung’s Quick Share to offer one, unified solution for Android users under the Quick Share name. Google indicated in that same announcement that it was working with manufacturers like LG to include the new Quick Share version on Windows PCs as a pre-installed application.

While sending files from device to device sounds like an easy task in theory, it can be quite complex. We couldn’t help but wonder about the potential bugs that might be hiding in the Windows version, given this was Google’s first foray into developing a native Windows application that supports so many communication protocols and includes significant functionality outside its core competency of web services. Much of the application code for Quick Share for Windows is also in an open-source repository and the app may be pre-installed on many new Windows PCs in the near future, two additional reasons it may be an attractive target for malicious actors. 

So, our most recent research project—which we first presented at DEF CON 32 (2024)—set out to explore the intricacies and potential vulnerabilities of this relatively new file-sharing solution. What we found was 10 unique vulnerabilities, some of which we were able to assemble into an innovative remote code execution (RCE) attack chain against Quick Share for Windows. 

Below, we’ll first provide a high-level overview of the key findings and takeaways from this research. Next, we’ll dive into the details behind Quick Share’s communication protocol. Then, we will discuss the research process that led to the discovery of 10 vulnerabilities and explain how we were able to chain several of them together to develop an RCE attack. Finally, we will highlight the vendor response and explain how we are sharing this information with the broader security community to help organizations protect themselves.

Overview

Key Findings

The Quick Share application implements its own specific application-layer communication protocol to support file transfers between nearby, compatible devices. By investigating how the protocol works, we were able to fuzz and identify logic within the Quick Share application for Windows that we could manipulate or bypass. As a result, we discovered 10 unique vulnerabilities that we were able to assemble into an innovative and unconventional RCE attack chain that allowed us to run code on Windows computers with Quick Share installed. 

The vulnerabilities included: 

  1. Remote Unauthorized File Write in Quick Share for Windows
  2. Remote Unauthorized File Write in Quick Share for Android
  3. Remote Forced Wi-Fi Connection in Quick Share for Windows
  4. Remote Directory Traversal in Quick Share for Windows
  5. Remote DoS in Quick Share for Windows – Endless Loop
  6. Remote DoS in Quick Share for Windows – Assert Failure
  7. Remote DoS in Quick Share for Windows – Assert Failure
  8. Remote DoS in Quick Share for Windows – Unhandled Exception
  9. Remote DoS in Quick Share for Windows – Unhandled Exception
  10. Remote DoS in Quick Share for Windows – Unhandled Exception

Google fixed all of the vulnerabilities and decided to issue two CVEs:

Takeaways

While this research attempted to exploit vulnerabilities specifically within Quick Share’s communication protocol, we believe the implications are relevant to the software industry as a whole and suggest several important takeaways:

  • From an offensive perspective, ethical hackers often have limited capabilities at their disposal, many of which may not appear to directly help them accomplish what they hope to. We believe our research has shown how seemingly basic or insignificant capabilities can be turned into something much greater. We all know by now about the concept of chaining vulnerabilities to solve known problems—such as bypassing the stack cookie or other memory corruption mitigations—but it is also possible for researchers to use the abilities they possess to produce a very unconventional flow to achieve what they are aiming for.
  • From a defensive perspective, our research has proven that a relatively minor vulnerability could be the key to a successful breach. If we didn’t have a DoS vulnerability to crash Quick Share, for example, then creating a lasting Wi-Fi connection would not have been possible and our entire RCE chain would have been disabled. Seemingly harmless known issues and bugs are regularly left unfixed in many software products, because it is not always possible to fix everything. However, these issues can present significant security risks under the right circumstances. We believe it is critical for software vendors to recognize that mitigating known issues and bugs may sometimes be the key for mitigating critical risks.
  • It is crucial for organizations that produce software to not only look for specific programming mistakes, like memory corruption bugs, within their code. When examining a program’s security, it is essential to take a big-picture perspective and try to identify whether simple logic or simple intended behaviors might present a security risk.

QuickShare Protocol Overview

Quick Share utilizes various communication methods like—Bluetooth and Wi-Fi—to send files. However, these protocols are not designed specifically to support file transfers, but rather to create a stable connection between devices for the purpose of communicating. As such, Quick Share still needs to implement its own specific application-layer communication protocol over these protocols. 

To better understand this protocol, we began by exploring the most basic functions that Quick Share uses to send and receive packets between devices. We identified generic functions that appeared to be used for all supported communication methods and developed a DLL that hooks them, giving us a clear view of all the packets that are sent and received by the app in their binary form. 

Protobuf & OfflineFrame

We then dove into the Read and Write functions, where we could see all of Quick Share’s communication. The functions existed as part of a base class that was called BaseEndpointChannel—that was the base class for all other “channel” implementations for each communication method. That confirmed that hooking these functions would enable us to see all the packets that Quick Share sends and receives, regardless of the communication protocol being used and regardless of whether the protocol changed in the middle of a file transfer session. 

Within the Read function, we were able to understand that almost all packets being sent and received during a Quick Share session were parsed into an OfflineFrame object, making OfflineFrame like a base class for all packet types.

But the OfflineFrame class is not an ordinary C++ class, as it is generated by Protobuf. We were able to see this proto file is being compiled into .cpp files that define the OfflineFrame and provide functions to serialize it to and from bytes.

QuickSniff Tool 

We needed a tool that would allow us to sniff the communication, so we wrote a DLL that hooks the Read and Write functions. It textually logs each packet that is being sent and received with all of its fields. With the ability to “sniff” QuickShare packets using our new tool, we were able to better understand Quick Share’s protocol. 

Nearby Connections API

As part of our research, we understood that Quick Share uses the Nearby Connections API to discover, connect, and exchange data with nearby devices in real-time, regardless of network connectivity. Quick Share uses the Nearby Connections API with its own implementation. The API: 

  • Allows different apps to communicate with nearby devices—each app identifies its unique implementation using a Service ID.
  • Is based on Protobuf, which is used to serialize structured objects.
  • Is mostly encrypted, which is handled using Google’s Ukey2 library.
  • Has multiple connection strategies, including peer-to-peer, star, and cluster.

We focused on the peer-to-peer strategy, which uses an Initiator and Responder that functions similarly to a Client and Server. 

Initial Connection

The first stage of communication is the Connection Request packet. Following that, the Initiator starts with the encryption key-exchange handshake, which includes the following steps: 

  • The Initiator sends a Ukey2 Client Init packet to the Responder.
  • The Responder sends a Ukey2 Server Init packet back to the Initiator. 
  • The Initiator responds with a Ukey2 Client Finish packet.

At this point, the Ukey2 handshake is successfully completed. All subsequent packets are encrypted and are of type OfflineFrame.

The Responder then sends a Connection Response packet—indicating that it accepts the connection—and the Initiator then sends a similar one back. At this point, the generic Nearby Connections API communication concludes, and the proprietary implementation begins. 

Quick Share Implementation 

Quick Share’s proprietary communication protocol can use various types of OfflineFrame packets provided by the Nearby Connections API, as shown in the image below. 

We observed the following types in our analysis of Quick Share: 

  • Payload Transfer
  • Bandwidth Upgrade Negotiation 
  • Keep Alive 
  • Disconnection 
  • Auto Resume
  • Auto Reconnect
  • Connection Request
  • Connection Response

Our research focused specifically on the Payload Transfer and Bandwidth Upgrade Negotiation types. Once the connection is accepted by both sides, they send a Payload Transfer OfflineFrame packet of type BYTES, which contains binary data (binary data is represented as a base64 string when we present the OfflineFrame packet in its textual form).

With the help of another Protobuf file that we found in the Chromium open-source project, we were able to decode this binary data and discover that this Payload Transfer packet contained another Protobuf structure in its body field that was similar to an OfflineFrame, but different. Its type was classified as Paired Key Encryption.

Both sides send each other a Paired Key Encryption packet, and right after that, a Paired Key Result. With the help of our QuickSniff tool, we noticed that the packets are probably used for enforcing the device discovery modes: Your Device, Contacts, and Everyone. Those modes allow users to configure who can see their device and who should be authorized to send data to their device. For example, users can choose that only their contacts are able to send data to them.

After this stage is complete, the Initiator that wants to send the file sends an Introduction packet. The Responder is prompted with a file introduction dialog, noting that the Initiator would like to send a file. To receive the file, the Responder must press the accept button, which will cause Quick Share to send an Accept packet to the Initiator. Both the Introduction and the Accept packets are contained in the body of a Payload Transfer OfflineFrame of type BYTES, just like the Paired Key Encryption and Paired Key Result packets were. Following the acceptance by the Responder, the Initiator sends the file over the “body” field of a Payload Transfer OfflineFrame of type FILE. And the process is complete.

Now that we know how Quick Share works, the following video shows a normal session from the user’s perspective: 

The Research Process

Fuzzing Vulnerabilities

Fuzzing is an automated software testing method that injects a variety of inputs and/or requests to a computer program with the intention of causing the program to crash, thereby identifying bugs. Now that we have a basic understanding of how Quick Share’s protocol works, we can fuzz Quick Share for Windows. 

We chose WinAFL, which is the most straightforward infrastructure for fuzzing in Windows. For instrumentation, we used DynamoRIO. And, since Protobuf is being used everywhere, we knew that the fuzzer could be more efficient if we made it grammar-aware. So, instead of using WinAFL’s default mutator, we used Google’s ‘libprotobuf-mutator’ that can be utilized to mutate (fuzz) only the fields of a Protobuf structure, instead of mutating a serialized Protobuf structure as a simple buffer of bytes and making it invalid for parsing..

We wanted to fuzz an entire file-sending session, not just a specific state. However, because a file-sending session requires acceptance on the Responder side, we would need to develop a way to initiate an automatic acceptance that wouldn’t rely on the user to actually press accept. 

Our first approach was to reverse engineer the relevant module and patch it so that every file was accepted. But, fortunately for us, we found in the Chromium open-source project that Google already implemented a built-in feature called “Auto-accept.” 

We located the relevant code in the binary and patched its “if”’ statement to make it work all the time. Now our fuzzing target would automatically accept every file, every time.

Next, we needed to implement a harness that could handle an entire session on each fuzzing iteration, rather than just sending a single packet. To achieve this, we created a simple binary format to hold all packets for an entire session, which would be sent in each fuzzing iteration. We used a simple structure: four bytes for the length, followed by a serialized OfflineFrame with that length.

With that, we were ready to fuzz Quick Share for Windows. But the process was very slow. 

As we investigated, we saw that the OnTransferComplete function was being called after each file transfer. Among other things, this function leads to calls to the functions StopAdvertising and, later on, StartAdvertising. These calls take time, as they destroy and recreate the resources that Quick Share uses for communication. On top of that, another function named RemoveEndpoint is called after each session. Apparently, this function sleeps for 500 milliseconds.

So again, we patched the relevant module to prevent these behaviors. This made our fuzzing process about 20 times faster. 

Unfortunately for us, this speed improvement created a persistent issue. The combination of DynamoRIO, which significantly slows down the fuzzing target due to its instrumentation, and our patch to increase file transfer speed led to an unhandled race condition that was too complex to manage. 

As a result, we received numerous crash reports that we were not able to reproduce. Therefore, we decided to abandon this approach and stick with the original functionality of Quick Share, despite its slowness. 

Results

Over time, the fuzzer did produce several good results, including four reproducible crashes:

  1. The first occurred due to an invalid UTF-8 string provided in the file name.
  2. The second happened when a field called “Endpoint ID” was not included in the Connection Request packet.
  3. The third was triggered if the “Payload ID” field was set to zero when sending a Payload Transfer packet.
  4. The last occurred when two sessions occurred quickly one after the other. If both sessions started with the same “nonce” value and had “UNKNOWN_VERSION” in the Connection Response, it caused a crash.

Upon further exploration of these crashes, it became apparent that they were non-exploitable denial of service (DoS) vulnerabilities. The UTF-8 issue resulted from an unhandled exception. The next two crashes were due to assert checks that closed the application, despite it being unreasonable for a remote attacker to trigger them. The final crash was also caused by an unhandled exception, which did not lead to any memory corruption or unexpected behavior that could be exploited.

Another very interesting finding by the fuzzer was a reproducible timeout. When a file is received, Quick Share attempts to open it to check if a file with the same name already exists. If the file successfully opens, it means that it exists and Quick Share just adds an index number suffix to the file name, exactly like browsers do. Quick Share tries to add the suffix behind the file extension, so it splits the file name into two parts: the name and the extension.

However, if the name behind the extension has a null terminator in it, anything added after the null terminator is irrelevant. When the file name is passed to the open function, it only reads the string up to the null terminator. This causes Quick Share to get stuck in an endless loop, continuously incrementing indexes while mistakenly thinking it’s searching for an available index, when in fact it’s trying to open the same file repeatedly.

Overall, we managed to get the fuzzer working consistently, but each fuzzing iteration took too much time. When we did identify some crashes, they weren’t necessarily exploitable. So, we decided it was time to move on instead of continuing our efforts to improve the fuzzer.

Logic Vulnerabilities

We felt confident enough working with Quick Share and the protocol to start searching for vulnerabilities that exploit the logic of the code. One observation we’d made based on our work with the protocol was that the code is extremely generic, full of abstract and base classes and a handler class for each packet type. Additionally, the code is filled with threads and asynchronous methods all over the place. We’ll explain the significance of this in the section below.

File Transfer Acceptance Bypass

As noted earlier, to send a file, the Initiator first needs to send an Introduction packet, and wait for an Accept packet from the Responder. After that, that Initiator will send a PayloadTransfer packet containing their file. 

The observations we noted above regarding the generic nature of the code gave us an idea. Since everything is so generic and filled with different threads and every packet is so “beautifully” handled by each handler separately, could we just trigger the handler for the packet with the actual file directly? What would happen if we skipped the Introduction and Accept packets and sent the PayloadTransfer packet directly? Would the packet again so “beautifully” be forwarded to the right handler, skipping the need for the user’s acceptance, but the file would actually be created? We found out that the file would be sent to the Responder anyway, resulting in a complete bypass of the need for acceptance on the Responder side.

To make things even better, we discovered that this works for any discovery mode. So even if a device is configured to accept files only from the user’s contacts, we could still send a file to the device without requiring acceptance. 

Forced Wi-Fi Connection

In the context of data transfer, “medium” refers to the channel through which information is transmitted (e.g., Bluetooth, Wi-Fi). When sending a file, Quick Share checks whether there’s a need to upgrade the medium to enhance bandwidth and achieve a better transmission speed.

In another piece of research focused on Bandwidth Upgrade Negotiation, researchers forced an Android device to connect to a rough Wi-Fi network to carry out a man-in-the-middle (MITM) attack. This attack lasted a maximum of 30 seconds and has since been mitigated by Google. So, if your Android phone receives a bandwidth upgrade via Quick Share today, other network connections will not be redirected to that Wi-Fi network. But what about on Windows? 

We noticed that one of the upgrade methods is a Wi-Fi HotSpot access point. With this option, the Initiator creates a temporary hotspot and sends the credentials to connect to the Responder. This process can also be initiated from the Responder’s side. When the transfer is completed, the hotspot is closed. 

However, during this time, the Internet connection of the Responder device is still working (even though it is connected to the Initiator’s hotspot). We started to sniff network packets from the Initiator device and found out that all the traffic from the Responder goes through our device. Meaning, we could get a MITM for the time of the transfer and sniff all of the Responder’s Internet traffic. However, since encryption is standard for today’s application layer, manipulating the traffic to achieve an RCE was not likely to succeed except in very specific circumstances. 

Path Traversal

When sending files is involved, we always consider path traversal. The first thing that came to mind was to craft a special file name that would trigger a path traversal, with the hope of writing our executable to the startup folder to achieve an RCE. The simplest attempt of course failed, as Quick Share does look for path traversals.

Next, we tried the MagicDot concept based on Or’s research from April of this year. Passing a triple-dot file name led Quick Share to try and open the Downloads folder as a file—to understand the exact reason, check out the full MagicDot research. This did lead us to a path traversal, but not an exploitable one, as QuickShare just crashed trying to open a folder as a file.

We did find a path traversal enabling us to create a file outside of the Downloads folder that, oddly enough, was sourced in Quick Share’s code that is responsible for removing path traversal strings. However, it had very hard constraints—including the fact that the final name of the file had to start with “Downloads” and the file itself had to always be in the user’s folder—and wasn’t powerful enough to achieve an RCE.

Summary 

At this point we had found the following 10 vulnerabilities: 

  1. Remote Unauthorized File Write in Quick Share for Windows
  2. Remote Unauthorized File Write in Quick Share for Android
  3. Remote Forced WiFi Connection in Quick Share for Windows
  4. Remote Directory Traversal in Quick Share for Windows
  5. Remote DoS in Quick Share for Windows – Endless Loop
  6. Remote DoS in Quick Share for Windows – Assert Failure
  7. Remote DoS in Quick Share for Windows – Assert Failure
  8. Remote DoS in Quick Share for Windows – Unhandled Exception
  9. Remote DoS in Quick Share for Windows – Unhandled Exception
  10. Remote DoS in Quick Share for Windows – Unhandled Exception

With them, we’d achieved five primary capabilities, including the ability to:

  • Create files in the victim’s Downloads folder
  • Create files in the user’s folder of the victim, because it’s the parent of the Downloads folder However, the file has to start with the prefix “Downloads”
  • Force the target device into connecting to a different Wi-Fi network, but only for about 30 seconds
  • Crash Quick Share in multiple ways
  • Force Quick Share into an endless loop, continuously opening a file we choose from the Downloads folder

While these findings were significant, we were looking for the holy grail–an RCE vulnerability that we didn’t have yet. 

RCE Chain 

As our next move, we decided to explore the possibility of chaining these vulnerabilities into an RCE and began with an idea. What if we could identify when executable files were downloaded to the Downloads folder by the browser and overwrite the executable files with our own malicious files before they were run? Then, when the victim ran the executable, we would have an RCE. 

Two of the vulnerabilities we found previously had promise in helping us achieve this goal, but they didn’t quite offer the capabilities we needed: 

  • First, we had the vulnerability that allowed us to see all of the victim’s Wi-Fi traffic. However, it only gave us access for approximately 30 seconds. We needed to figure out how to extend our access beyond 30 seconds and develop a technique to identify executable file names being downloaded by the victim, while the traffic was encrypted.
  • Next, we had the vulnerability that gave us the ability to create files in the Downloads folder. This was promising, as it is the same folder that web browsers (and Quick Share) place their downloaded files. However, we would need to up-level this capability to overwrite files in the Downloads folder, rather than just create them.

Forcing a Lasting Wi-Fi Connection

To work on making our Wi-Fi hotspot MITM exploit last longer, we needed to prevent Quick Share from returning to its original Wi-Fi network once a file-sending session was over. But how? After forcing a Windows computer with Quick Share to connect to our malicious Wi-Fi network, we instantly crashed the app with one of our DoS vulnerabilities. As a result, we were able to achieve a persistent Wi-Fi connection.

While such a crash might seem problematic on the surface, as it would effectively terminate our ability to communicate with the app and continue exploiting it, the Quick Share app solved this challenge for us. When Quick Share is installed, it creates a scheduled task that runs every 15 minutes to check if Quick Share is running. If it’s not, then Quick Share is re-started, and we don’t lose the ability to further exploit it. 

And with that, we have the first two links in our RCE attack chain.

Leveraging Encrypted Traffic Metadata

Although files downloaded over our forced Wi-Fi connection would be downloaded over HTTPS—meaning the traffic was encrypted—two elements of the metadata from the HTTPS session could be useful: 

  • First, was metadata about the domains the user communicated with during a session. The encryption of HTTPS is performed using the TLS protocol. The TLS session starts with an unencrypted Client Hello message sent by the client. Normally, a Server Name Indication Extension is added to this message, indicating the server’s domain. That means that if we are exposed to the victim’s traffic, we can determine the domains that they communicate with.
  • Second, was the metadata about the approximate size of data that is transferred in the session. When a file is being downloaded over HTTPS, it’s normally downloaded in one TCP session. Even though encryption might add some random padding, the amount of data that is being transferred from the server to the client during a download stays relatively the same. In addition, the size of an executable file is usually much bigger than the size of other pages or resources that may be transferred from a server to a client in an HTTPS session.

If we know what domain the client communicated with, when large files are downloaded, and what their approximate size is, then we can make a well-educated guess about what the downloaded file is. 

Let’s use a popular software installer like Visual Studio Code as an example. Upon navigating to the VS Code downloads page, the user is pointed to a single download button for the latest VS Code version that matches their OS. If we know 95 MB were downloaded from this website, then we can confidently say that the latest VS Code installer—which is also 95 MB and is the largest resource on the website—was probably downloaded.

Defining MITM Domain Paths

Next, we defined what we call “Domain Paths”— a sequence of domains that we expect a victim to access before a download starts. For an example, we’ll look at Notepad++. When we click the download button on the Notepad++ website, the executable is not downloaded from the notepad-plus-plus.org domain. Instead, it references github.com, which actually redirects the request to another domain: objects.githubusercontent.com. This domain is the final domain, and the file is downloaded from there.

By just looking at this final domain, we would be unable to determine that the downloaded file is the installer of Notepad++. However, if we follow the access to previous domains (i.e., domain path), we can see that notepad-plus-plus.org was accessed, followed by github.com, followed by objects.githubusercontent.com in a limited time period. If the final domain downloads a file with an approximate size of the installer, then we can assume that it’s actually the installer.

In this way, we developed a new MITM technique. We first create a mapping of domain paths to executables that match the domain paths and their sizes. Then, we wait until the victim hits a certain domain path in a short time frame, and we start counting the downloaded data. Finally, we check if the size of the downloaded data is equal or slightly larger than the installer that matches this domain path. If it does, then we are safe to assume the expected installer was indeed the one that was downloaded. 

With that, we connected another link to our RCE chain with the ability to detect the name of an executable that is downloaded by a victim.

Overwriting Files

To achieve an RCE, we still needed the ability to overwrite files to replace the executable with our malicious one before it ran. However, this didn’t necessarily need to be a generic ability to overwrite files, but rather an ability to overwrite files only when files were being downloaded. First, we decided to attempt to overwrite a Google Chrome download while it was in process. For context, let’s understand the download process in Chrome: 

When Chrome downloads a file—regardless of which file it is—it starts by checking if the file name already exists. If it does, it adds a number surrounded by parenthesis to the final name for the download. If the file doesn’t exist, it keeps the original name. Then it starts downloading the file, but into a temporary file with a .crdownload extension. Once the download is fully complete, Chrome renames the temporary file to the actual name of the downloaded file and the process is complete. 

Since Chrome decides on the final name for the download at the beginning (before the download is complete), we thought there was a good potential to create confusion if we used our file acceptance bypass to send a file with the same name in the middle of this process—some soft of time-of-check to time-of-use (TOCTOU) exploit. But how could we know the name of the downloaded file and send it before the download was complete? 

Only if we waited until the last TCP packet was sent from the server to the client and held it, preventing the victim’s download from “finishing” even though we know it’s complete. This way, we have the approximate size of the file and can use it to determine the executable’s name using the MITM technique we explained before. Then, if we sent a file with the exact same name—VSCodeSetup.exe in this example—right before the download was finished, Chrome might be confused and fail to rename the temporary file, leaving our file as the presumably downloaded file.

Unfortunately, this did not work. Chrome just overwrote the file that we sent, finishing its download successfully and deleting our malicious file. 

To be successful, we knew that we needed to find a way to prevent Chrome from overwriting our file. It wasn’t long before we figured out that we might already possess this ability in one of the earlier vulnerabilities we discovered. We hoped that if we used the vulnerability that allowed us to force Quick Share into a continuous loop of opening and closing any file we chose from the Downloads folder, it would prevent Chrome from overwriting it. 

We were blown away—it worked! Once Chrome finished the download, it: 

  • Deleted the temporary .crdownload file
  • Failed to overwrite our malicious file
  • Reported that the download was finished successfully in its user interface 

When we clicked on the file in Chrome’s Downloads window, it actually ran our file! And with that, two more links were added to our RCE chain: sending a file without approval and forcing a continuous open loop. As a result, the RCE QuickShell attack chain was complete.

Demo

The following demo shows the RCE QuickShell attack chain in action.

Overall we found the following 10 vulnerabilities and another bug in Chrome that we reported to Google in January 2024: 

  1. Remote Unauthorized File Write in Quick Share for Windows
  2. Remote Unauthorized File Write in Quick Share for Android
  3. Remote Forced WiFi Connection in Quick Share for Windows
  4. Remote Directory Traversal in Quick Share for Windows
  5. Remote DoS in Quick Share for Windows – Endless Loop
  6. Remote DoS in Quick Share for Windows – Assert Failure
  7. Remote DoS in Quick Share for Windows – Assert Failure
  8. Remote DoS in Quick Share for Windows – Unhandled Exception
  9. Remote DoS in Quick Share for Windows – Unhandled Exception
  10. Remote DoS in Quick Share for Windows – Unhandled Exception

Google was able to reproduce and fix each of the vulnerabilities. They decided to issue two CVEs, and we received the following official response: 

This research explored Quick Share’s application-layer communication protocol in an effort to identify processes within the application that could be manipulated or bypassed to develop an RCE. We believe the implications of our findings could be far-reaching, based on the fact that Quick Share may be pre-installed on many Windows PCs in the near future and Windows is the most widely used desktop OS in the world. To help mitigate the potential impact of the vulnerabilities identified by this research, we have: 

  • Responsibly disclosed our research findings to Google, as noted above. Google did fix each of the vulnerabilities—including the critical ones that allowed us to force a persistent Wi-Fi connection and send files without approval—effectively disabling the RCE attack chain.
  • Shared our research openly with the broader security community here and at our recent DEF CON 32 presentation to enable software vendors and the organizations and end-users using them to better understand the risks associated with these vulnerabilities.
  • Provided a research repository that includes tools that enable the verification and exploitation of these vulnerabilities to serve as a basis for further research and development. This repository includes:
    • quick_shell: Implements the entire RCE chain, overwriting an installer executable downloaded by a victim Windows device with Quick Share.
    • quick_sniff: A sniffer that captures Quick Share’s protocol packets, prints them textually. In addition, for each device in the session, it creates a binary file in our custom format that holds all the sent packets in the order they were sent.
    • send_packets: Sends Quick Share’s protocol packets. As input, it receives a binary file in our custom format with packets to send (the same format that the quick_sniff tool outputs).
    • send_file_with_bypass: Exploits the vulnerabilities we reported for Quick Share for Android and Windows that allow sending a file without authorization or acceptance by the receiver, no matter what the current discovery mode is (“Your Devices”, “Contacts”, or “Everyone”).
    • force_wifi_connection: Forces a device with Quick Share to connect to a given Wi-Fi network. If performed against a Windows device with the vulnerable Quick Share version, then it also crashes its Quick Share app, creating a Wi-Fi connection to the given Wi-Fi network that lasts forever.
    • quick_fuzz: A fuzzer for Quick Share for Windows. Each fuzzing iteration sends a sequence of offline frames, simulating an entire transfer session.
  • Added original attack content to the SafeBreach platform that enables our customers to validate their environment against the vulnerabilities and techniques outlined in this research to significantly mitigate their risk.

For more in-depth information about this research, please: 

  • Contact your customer success representative if you are a current SafeBreach customer
  • Schedule a one-on-one discussion with a SafeBreach expert
  • Contact Kesselring PR for media inquiries 

Or Yair is a security research professional with more than six years of experience, currently serving as the Security Research Team Lead for SafeBreach Labs. Or started his professional career in the Israel Defense Force (IDF). His primary focus lies in vulnerabilities in Windows operating system’s components, though his past work also included research of Linux kernel components and some Android components. Or’s research is driven by innovation and a commitment to challenging conventional thinking. He enjoys contradicting assumptions and considers creativity a key skill for research. Or has already presented his vulnerability and security research discoveries internationally at conferences such as Black Hat USA, Europe, and Asia, DEF CON, SecTor, RSAC, Troopers, BlueHatIL, Security Fest, CONFidence, and more.

Shmuel Cohen is a cybersecurity professional with a diverse background. After serving in the Israel Defense Force (IDF) for three years, he pursued a bachelor of science degree in computer science. He had the privilege of working at CheckPoint, where he developed software and worked as a malware security researcher. As his interest grew in vulnerability research, he joined the SafeBreach team, where he has been able to focus his energies on exploring and addressing vulnerabilities in cybersecurity. Since joining SafeBreach Labs, he has had the opportunity to present original research once at Black Hat USA 2023, twice at Black Hat Asia 2024, and twice at CONfidence 2024.

Latest article