Hacking the Apple Webcam (again)
Gaining unauthorized camera access via Safari UXSS: the story of how a shared iCloud document can hack every website you’ve ever visited.
It’s been over a year since my last Apple camera hacking project, so I decided to give it another go.
My hack successfully gained unauthorized camera access by exploiting a series of issues with iCloud Sharing and Safari 15. While this bug does require the victim to click “open” on a popup from my website, it results in more than just multimedia permission hijacking. This time, the bug gives the attacker full access to every website ever visited by the victim. That means in addition to turning on your camera, my bug can also hack your iCloud, PayPal, Facebook, Gmail, etc. accounts too.
This research resulted in 4 0day bugs (CVE-2021-30861, CVE-2021-30975, and two without CVEs), 2 of which were used in the camera hack. I reported this chain to Apple and was awarded $100,500 as a bounty.
Apple fixed my last 0day chain (CVE-2020-3852 + CVE-2020-3864 + CVE-2020-3865) by making camera access drastically more difficult. Now multimedia access is only allowed when the protocol is “https:” and the domain matches your saved settings. This means that cleverly malformed URIs won’t cut it anymore. Now we need to genuinely inject our evil code into the target origin. In other words, we need to find a Universal Cross-Site Scripting (UXSS) bug.
But what exactly is UXSS? Google Project Zero has a nice summary in their paper, “Analysis of UXSS exploits and mitigations in Chromium” –
“UXSS attacks exploit vulnerabilities in the browser itself […] to achieve an XSS condition. As a result, the attacker does not just get access to user session on a single website, but may get access to any [website].”
The authors of this paper go on to call UXSS “among the most significant threats for users of any browser” and “almost as valuable as a Remote Code Execution (RCE) exploit with the sandbox escape.” Sounds pretty great, right? Imagine building a website that can jump into https://zoom.com to turn on the camera, hop into https://paypal.com to transfer money, and hijack https://gmail.com to steal emails.
Before we go any further, I should clarify how exactly this bug differs from my last Safari Camera Hacking project. That bug specifically targeted stored multimedia permissions. It did not give me the ability to execute code on arbitrary origins. Check out my attack diagram to see which origins were being used. In other words, that hack let me leverage Skype’s camera permission but did not let me steal Skype’s cookies.
Let’s try to find a UXSS bug in the latest version of Safari (Safari v15 beta at time of writing). As always, the first step is to do a lot of research into prior work. After all, the best security research comes from standing on the shoulders of giants.
The Attack Plan
After reading numerous write-ups about patched Safari UXSS bugs, I decided to focus my research on webarchive files. These files are created by Safari as an alternative to HTML when a user saves a website locally.
Safari saving a website as a Webarchive file
A startling feature of these files is that they specify the web origin that the content should be rendered in.
Webarchive File Format
This is an awesome trick to let Safari rebuild the context of the saved website, but as the Metasploit authors pointed out back in 2013, if an attacker can somehow modify this file, they could effectively achieve UXSS by-design.
According to Metasploit, Apple did not view this attack scenario as very realistic because “the webarchives must be downloaded and manually opened by the client.” Granted this decision was made nearly a decade ago, when the browser security model wasn’t nearly as mature as it is today.
Apple’s decision to support this ultra-powerful filetype gave way to an era of hackers trying to forcefully open them on victims’ machines. Fundamentally, this attack can be broken into two steps:
1) Forcefully download an evil webarchive file
2) Forcefully open it
Until recently, there were no protections to prevent step #1. Prior to Safari 13, no warnings were even displayed to the user before a website downloaded arbitrary files. So planting the webarchive file was easy. (Now with Safari 13+, users are prompted before each download)
Opening the webarchive file was trickier, but still manageable by somehow navigating to the file:// URI scheme. Back when Safari’s error pages lived on the file:// scheme, hackers figured out how to purposely invoke an error page to just alter its pathname, a hack delightfully dubbed “Errorjacking.” See here and here for two variations. Another approach that worked back in the day was to simply set the
Fast forward to 2022 and things get a lot harder. Not only are auto-downloads prevented by default, but webarchive files are considered malicious applications by macOS Gatekeeper. This means that users can’t even manually open foreign webarchives themselves anymore. Apple seems to have changed their 2013 stance about how dangerous these files can be.
Download prompt in Safari 13+
Gatekeeper Launch Prevention
Still, webarchive files just seem too juicy to give up on. Let’s explore how this old-school hack can still occur on the latest Safari and macOS builds.
Exploration of custom URI Schemes
I found success with my last Safari Camera Hacking project by conducting a deep dive into official IANA-registered URI schemes. This project was heavily guided by RFCs and public documentation. But there is an entire world of custom URL schemes that I neglected to talk about. These unofficial and (mostly) undocumented schemes are usually used by third party iOS/macOS apps as a form of deep linking. There is actually an entire community built around discovering and using these schemes cross-app for both fun and hacking projects.
An interesting note is that several first-party system apps such as Apple Help Viewer (help://), FaceTime (facetime-audio://), and Apple Feedback (applefeedback://) also support custom URI schemes. Abusing these schemes from a website in Safari is not a novel technique. Indeed, hackers have been finding ways to use custom schemes to launch (and exploit bugs in) system applications for a while now. Hacks range from annoyingly placing calls, aiding in social engineering, to arbitrary file execution. Seriously, there is some awesome research in this space.
To help combat these attacks, modern versions of Safari warn the user before blindly launching secondary applications. That is, unless they are one of the hardcoded exceptions identified in this great Blackhat presentation.
Custom URI Schemes that Safari will launch without Prompt
All of these schemes are registered with Launch Services, so you can list them (and others) via this command:
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -dump | grep -B6 bindings:.*: | grep -B6 apple-internal
After digging through internal Apple schemes and cross-referencing them with the ones trusted by Safari, I found one that caught my eye– “icloud-sharing:”. This scheme appears to be registered by an iCloud Sharing Application called “ShareBear.”
LaunchServices data about the icloud-sharing: scheme
ShareBear was interesting to me because sharing iCloud documents seemed like a plausible path towards downloading & launching webarchive files. I couldn’t find any publicly available documentation or research about this scheme so I just started poking at it myself.
At this point we have identified an application that can be automatically launched by Safari, however we do not know how to correctly open it yet. Luckily, it was pretty straight forward.
Some quick research shows that iCloud File Sharing can generate a public Share Link.
Creating a public iCloud Share Link
Great, so what does ShareBear do now? Some quick testing showed this behavior:
ShareBear Behavior Flowchart
There is a subtle, but wildly impactful, design flaw with this behavior. Let’s dig into what happens if the user has not opened this file before. The user will be shown a prompt, similar to the one below.
ShareBear Open Prompt
This innocuous little prompt, with the default value of “Open,” seems pretty straightforward. A user should expect to have the image, example.png, opened if they agree. But in actuality, they are agreeing to much more than that.
Once the user clicks Open, the file is downloaded onto the victim’s machine at the location /Users/
In essence, the victim has given the attacker permission to plant a polymorphic file onto their machine and the permission to remotely launch it at any moment. Yikes.
Agreed to view my PNG file yesterday? Well today it’s an executable binary that will be automatically launched whenever I want.
Apple fixed this behavior in macOS Monterey 12.0.1 as a result of my report without issuing a CVE because it is more of a design flaw than a bug per-se.
Bonus Bug: Iframe Sandbox Escape
While fuzzing the icloud-sharing:// scheme, I stumbled upon a fun bug unrelated to the UXSS hunt. ShareBear appears to check the path of the URL for “/iclouddrive/*” before performing the behavior outlined above. If the path happens to be “/photos/*” then ShareBear makes a pretty silly mistake. It will tell Safari to open a new tab pointing to the iCloud web app… but it does not verify that the domain name is actually the iCloud web app.
In normal operation, the user is simply presented with the website, “https://photos.icloud.com.” However because this domain name is never validated, we can trick ShareBear into instructing Safari into opening a new tab to any website.
The implications of this behavior may not be obvious. This doesn’t seem all that different than just calling window.open(‘https://example.com’) normally. However there are situations in the web where websites aren’t allowed to do that. One example is if popup blocker is enabled. Another, more devious, example is when your website is inside of a sandboxed iframe.
An important rule for sandboxed iframes is that new windows opened from that iframe should inherit the same restrictions as the iframe itself. Otherwise escaping the sandbox would be as trivial as opening a popup.
Well this bug tricks Safari into opening a ‘fresh’ new tab without any sandbox restrictions!
Website trapped in a Sandboxed Iframe
So ShareBear neglecting to verify the domain gives us an easy popup-blocker bypass and an iframe sandbox escape. Nice! (fixed in Safari 15.2 without being assigned a CVE) Live demo on BugPoC – https://bugpoc.com/poc#bp-S4HH6YcO PoC ID: bp-S4HH6YcO, Password: loVEDsquId01. Note this demo will only work with Safari <15.2 pre macOS Monterey 12.1.
Now back to the Camera/UXSS hunt.
Quarantine and Gatekeeper
Quick reminder of where we are –