Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
0xmachos committed Dec 18, 2021
1 parent 4da68ec commit 9e36159
Show file tree
Hide file tree
Showing 3 changed files with 313 additions and 0 deletions.
57 changes: 57 additions & 0 deletions entitlements/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@

# Entitlements

Collection of scripts for determining which [Entitlements](https://developer.apple.com/documentation/bundleresources/entitlements) macOS (Mach-O) binaries have.

Inspired by:
* [Cedric Owens](https://twitter.com/cedowens)'s [EntitlementCheck](https://github.com/cedowens/EntitlementCheck)
* [Jonathan Levin](https://twitter.com/morpheus______)'s [OS X/iOS Entitlement Database](http://newosxbook.com/ent.jl)

For lists of and descriptions of Entitlements see:
* Apple Developer Documentation
* [Bundle Resources > Entitlements](https://developer.apple.com/documentation/bundleresources/entitlements)
* [Security > App Sandbox](https://developer.apple.com/documentation/security/app_sandbox)


# Hardened Runtime


## Sources
* [Notarization: the hardened runtime](https://eclecticlight.co/2021/01/07/notarization-the-hardened-runtime/) by [Howard Oakley](https://twitter.com/howardnoakley)
* [The ‘hardened runtime’ explained](https://eclecticlight.co/2019/08/10/the-hardened-runtime-explained/) by [Howard Oakley](https://twitter.com/howardnoakley)
* [Hardened Runtime](https://developer.apple.com/documentation/security/hardened_runtime) by Apple
* [Your Apps and the Future of macOS Security (WWDC2018 Session 702)](https://developer.apple.com/videos/play/wwdc2018/702/) (22:00 mark) by Apple

# Interesting Entitlements


## `com.apple.private.security.clear-library-validation`
* Formerly `com.apple.security.cs.disable-library-validation`
* Can load arbitrary unsigned plugins/frameworks
* [About com.apple.private.security.clear-library-validation](https://theevilbit.github.io/posts/com.apple.private.security.clear-library-validation/) by [Csaba Fitzl](https://twitter.com/theevilbit)


## `com.apple.security.cs-allow-dyld-environment-variables`
* [Allow DYLD Environment Variables Entitlement](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-dyld-environment-variables/)
* Allows injecting Dynamic Libraries (dylib's) via the `DYLD_INSERT_LIBRARIES` environment variable
* [DYLD_INSERT_LIBRARIES DYLIB injection in macOS / OSX](https://theevilbit.github.io/posts/dyld_insert_libraries_dylib_injection_in_macos_osx_deep_dive/) by [Csaba Fitzl](https://twitter.com/theevilbit)


## `com.apple.security.get-task-allow`
* Allows other processes to attach via a debugger
## `com.apple.security.cs.allow-unsigned-executable-memory`
* [Allow Unsigned Executable Memory Entitlement](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-unsigned-executable-memory/)
* Allows overriding or patching C code
* Via `NSCreateObjectFileImageFromMemory` (which is fundamentally insecure)
* Or use the DVDPlayback framework
## `com.apple.security.files.downlaods.read-only`
* [`com.apple.security.files.downloads.read-only`](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_files_downloads_read-only/)
* May have access to files the user has selected in an open or save dialog
## `com.apple.security.files.downloads.read-write`
* May have access to files the user has selected in an open or save dialog
## `com.apple.security.files.all`
## `com.apple.security.files.user-selected.read-only`
## `com.apple.security.files.user-selected.read-write`
## `com.apple.private.tcc.allow`
* May have TCC access to some protected portions of the OS

105 changes: 105 additions & 0 deletions entitlements/dump-entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/usr/bin/env zsh
# # macos-scripts/entitlements/dump-entitlements

# dump-entitlements

set -uo pipefail
# -o pipefail force pipelines to fail on first non-zero status code
# -u prevent using undefined variables

IFS=$'\n\t'
# Set Internal Field Separator to newlines and tabs
# This makes bash consider newlines and tabs as separating words
# See: http://redsymbol.net/articles/unofficial-bash-strict-mode/


function usage {
echo
echo " Find all binaries on disk, dump their entitlements, uniquely sort the entitlements"
echo " Usage: ./dump-entitlements {find | dump | sort}"
echo

echo " find Find all binaries on disk and dump them to ${BINARIES_FILENAME}"
echo " dump Process ${BINARIES_FILENAME} and dump the entitlements for each binary to ${ENTITLEMENTS_FILENAME}"
echo " sort Uniquely sort ${ENTITLEMENTS_FILENAME} to ${SORTED_ENTITLEMENTS_FILENAME}"
echo

exit 0
}


### Utility Functions ###
# ctrl_c

function ctrl_c {
echo -e "\\n[❌] ${USER} has chosen to quit!"
exit 1
}

### END Utility Functions ###


function find_binaries {
# find_binaries

sudo --prompt="[⚠️ ] sudo required to search everywhere" -v

sudo find / -type f -exec file {} \; -print | grep 'Mach-O' | awk -F ':' '{print $1}' > "${BINARIES_FILENAME}"
}


function dump_entitlements {
# dump_entitlements

while read binary; do
/usr/bin/codesign --display --entitlements - "${binary}" 2>&1 > "${ENTITLEMENTS_FILENAME}"
done < "${BINARIES_FILENAME}"
}


function sort_entitlements {
# sort_entitlements

awk '{print $2}' "${ENTITLEMENTS_FILENAME}" | grep com.apple | sort -u > "${SORTED_ENTITLEMENTS_FILENAME}"
}


function main {

trap ctrl_c SIGINT
# Detect and react to the user hitting CTRL + C

declare -r ARG=${1:-"usage"}
declare -r DATE=$(date +"%d-%m-%Y")
declare -r BINARIES_FILENAME="Mach-O.txt-${DATE}"
declare -r ENTITLEMENTS_FILENAME="entitlements-${DATE}.txt"
declare -r SORTED_ENTITLEMENTS_FILENAME="sorted-entitlements-${DATE}.txt"

case "${ARG}" in

usage|help|-h|--help|🤷‍♂️|🤷‍♀️|"¯\_(ツ)_/¯")
usage
;;

find|-f|--find)
echo "[⚠️ ] This takes a looong time to run"
echo "Will dump list of binaries to ${BINARIES_FILENAME}"
sleep 3
find_binaries
;;

dump|-d|--dump)
dump_entitlements
;;

sort|-s|--sort)
sort_entitlements
;;

*)
usage
;;
esac
}

main "$@"
151 changes: 151 additions & 0 deletions entitlements/treebeard
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
#!/usr/bin/env zsh
# macos-scripts/entitlements/treebeard

# treebeard

set -uo pipefail
# -o pipefail force pipelines to fail on first non-zero status code
# -u prevent using undefined variables

IFS=$'\n\t'
# Set Internal Field Separator to newlines and tabs
# This makes bash consider newlines and tabs as separating words
# See: http://redsymbol.net/articles/unofficial-bash-strict-mode/


### Define Colours ###
tput sgr0;
# reset colors

RESET=$(tput sgr0)
readonly RESET
RED=$(tput setaf 1)
readonly RED
YELLOW=$(tput setaf 3)
readonly YELLOW
GREEN=$(tput setaf 64)
readonly GREEN
### END Colours ###


function usage {
echo
echo " "
echo " Usage: ./treebeard"
echo

echo " shit some shit"
echo

exit 0
}


### Utility Functions ###
# ctrl_c

function ctrl_c {
echo -e "\\n[❌] ${USER} has chosen to quit!"
exit 1
}

### END Utility Functions ###

function get_binaries {
# get_binaries

for binary in /Applications/*.app/Contents/MacOS/* \
/usr/bin/* \
/usr/local/bin/* \
/usr/sbin/*; do

if [[ "${binary}" =~ Xcode.app ]]; then
continue
# Skip Xcode because it takes ages to run codesign on it
elif [[ "${binary}" =~ Safari.app ]]; then
continue
# Skip Safari because it is a system application
# TODO: Skip other systems apps like Pages?
fi

binaries+=("${binary}");

done
}


function check_hardened_runtime {
# check_hardened_runtime
#

declare -r binary_to_check=${1:?binary_to_check not passed to check_hardened_runtime}

if codesign --display --verbose "${binary_to_check}" 2>&1 | awk 'FNR == 4 {print $4}' | grep --quiet 'runtime'; then
# awk: print 4th column of 4th line
# e.g. flags=0x0(none), flags=0x10000(runtime), flags=0x12000(library-validation,runtime)
# For bitmask values see:
# https://github.com/apple/darwin-xnu/blob/8f02f2a044b9bb1ad951987ef5bab20ec9486310/osfmk/kern/cs_blobs.h
return 0
else
return 1
fi
}


function check_entitlements {
# check_entitlements

declare -r binary=${1:?binary_to_check not passed to check_entitlements}

declare -a entitlements
entitlements=(com.apple.security.cs.allow-dyld-environment-variables\
com.apple.security.cs.disable-library-validation\
com.apple.private.security.clear-library-validation\
com.apple.security.get-task-allow\
com.apple.security.cs.allow-unsigned-executable-memory\
com.apple.security.files.downloads.read-only\
com.apple.security.files.all\
com.apple.security.files.user-selected.read-only\
com.apple.private.security.clear-library-validation\
com.apple.private.tcc.allow)

codesign_entitlements_output=$(/usr/bin/codesign --display --entitlements - "${binary}" 2>&1)
current_binary="${binary}"

for entitlement in "${entitlements[@]}"; do

if echo "${codesign_entitlements_output}" | grep --quiet "${entitlement}"; then

if [[ "${current_binary}" = "${binary}" ]]; then

echo
if check_hardened_runtime "${binary}"; then
echo "${binary} (${GREEN}Hardened Runtime${RESET})"
else
echo "${binary}"
fi

current_binary=""
fi
echo "${entitlement}"
fi
done
}


function main {

trap ctrl_c SIGINT
# Detect and react to the user hitting CTRL + C

declare -a binaries

get_binaries

for binary in "${binaries[@]}"; do
check_entitlements "${binary}"
done

}

main "$@"

0 comments on commit 9e36159

Please sign in to comment.