I found a zero-click vulnerability in macOS Calendar, which allows an attacker to add or delete arbitrary files inside the Calendar sandbox environment. This could lead to many bad things including malicious code execution which can be combined with security protection evasion with Photos to compromise users’ sensitive Photos iCloud Photos data. Apple has fixed all of the vulnerabilities between October 2022 and September 2023.
If you like to see my presentation video about this, you can check my Disobey 2024 presentation: https://www.youtube.com/watch?v=9NlQXLLQrvk
Phase 1: Arbitrary file write and delete vulnerability in Calendar (CVE-2022–46723)
An attacker can send malicious calendar invites to the victim that include file attachments. The filename of the attachment is not properly sanitized. The attacker can exploit this to conduct a successful directory traversal attack by setting an arbitrary path to a file in the ATTACH section with: “FILENAME=../../../PoC.txt”.
This will cause the file to be added to ~/Library/Calendar/PoC.txt instead of ~/Library/Calendar/[CalendarID]/Attachments/[eventid]/ .
If the attacker-specified file already exists, then the specified file will be saved with the name “PoC.txt-2”. However, if the event/attachment sent by the attacker is later deleted the file with the original name (PoC.txt) will be removed. This vulnerability can be used to remove existing files from the filesystem (inside the filesystem “sandbox”).
Vulnerability seems to exist at least in latest macOS Montrey 12.5. MacOS 13.0 beta4 doesn’t seem to be vulnerable anymore.
Phase 2: Leveraging the arbitrary file write vulnerability to gain Remote Code Execution (RCE)
When this vulnerability was found Ventura was about to be released. macOS version upgrade process can be leveraged to gain remote code execution via the Open File functionality in Calendar.
In order to gain RCE we will exploit the previously discovered arbitrary file write vulnerability to infect the calendar with multiple files. When combined, they will trigger the RCE exploit when macOS Monterey is upgraded to Ventura.
Injected file #1: 000Hacked-$RANDOM.calendar
This file contains calendar data which looks like “Siri Suggested” -calendar.
Suggested repeating event with alert-functionality. This will open other injected files.
Injected file #2: CalendarTruthFileMigrationInProgress file
This file will make sure that existing calendars in the old calendar format will be upgraded and merged to the new database.
Injected file #3: CalPoCInit.dmg
An alert embedded in the Calendar event in the injected file #1 will trigger opening the file ~/Library/Calendars/CalPoCInit.dmg
CalPoCInit.dmg includes a reference to a background image which will point to an external samba server. This reference is a Bookmark in the .DS_Store. It’s stored inside the root of this image file. Mount will happen without a quarantine flag even though CalPoCInit.dmg mount is in quarantine.
Injected file #4: stage1.url
Second alert from the calendar event embedded in the injected file #1 will open the file ~/Library/Calendars/stage1.url
This file stage1.url includes an URL to an application inside the previously mounted samba mount triggered by the injected file #3. This URL is file:///Volumes/CalPoCPayload/MyMidiTest.app.
This will cause Finder to open /Volumes/CalPoCPayload/, which will automatically trigger indexing. This will cause MyMidiTest.app to be indexed. This is needed for the unique URL registration to happen.
Inside our application bundle the MyMidiTest.app/Contents/Info.plist file includes a trigger that will cause a handler to be registered for a custom URL Type:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>MyMidi URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>mymiditest</string>
</array>
</dict>
</array>
Injected file #5: stage2.url
Third and the last alert from from the calendar event embedded in the injected file #1 will open the file ~/Library/Calendar/stage2.url which includes a reference to the custom url “mymiditest://” which will launch our malicious application without any user interaction whatsoever.
This is possible because the application is inside the samba mount from our exploit which does not have a quarantine flag.
mymiditest app will write files needed for the Phase 3 to /var/tmp/ and launch the script in Terminal with “open /var/tmp/PhotosPoC.sh”. The objective is to make a bit more room on our sandbox.
In order to demonstrate the superpowers gained by the previous two phases of the exploit chain, I chose to abuse Photos to leak sensitive user data, namely private pictures. Access to users’ sensitive files like Photos should be restricted and blocked by TCC. However, by having the exploit change the configuration of Photos it is possible to get access to pictures which are stored on iCloud. This is done by changing the System Photo Library to point to a path which is not protected by TCC.
The attacker can create a configuration file for Photos which uses a different System Photo Library for Photos. Configuration can be imported via “defaults import”.
Phase 2 of this PoC exploit chain has prepared and automatically dropped a configuration which uses /var/tmp/mypictures/Syndication.photoslibrary as a System Photo Library for Photos, cloudphotod and photolibraryd. You can find these malicious configurations created automatically in Phase 2 from the /var/tmp/mypictures/*.plist.
When the exploit chain runs PhotosPoC.sh, all running Photos-related applications will be killed and a new configuration will be imported with defaults.
Original configuration will be backed up to /var/tmp/mypictures/*-orig.plist
Malicious configuration will be imported from /var/tmp/mypictures/ .
New photo library will be opened by the exploit chain in Photos with “open /var/tmp/mypictures/Syndication.photoslibrary.
Syndication.photoslibrary is an empty template library.
Now Photos will be running with the new System Photo Library and iCloud sync will be enabled and original files will be downloaded to an unprotected directory.
When those files are synchronized to disk they will be copied to a new directory in /var/tmp/PoCLoot$RANDOM/. This sensitive and private data could also be copied to external resources and data could be posted to external web-servers with the curl command by the exploit with trivial modifications.