From 9e36159667a490de255ba1c703aef167eb558b28 Mon Sep 17 00:00:00 2001 From: 0xmachos <0xmachos@gmail.com> Date: Sat, 18 Dec 2021 01:55:15 +0000 Subject: [PATCH] Initial commit --- entitlements/README.md | 57 +++++++++++++ entitlements/dump-entitlements | 105 +++++++++++++++++++++++ entitlements/treebeard | 151 +++++++++++++++++++++++++++++++++ 3 files changed, 313 insertions(+) create mode 100644 entitlements/README.md create mode 100755 entitlements/dump-entitlements create mode 100755 entitlements/treebeard diff --git a/entitlements/README.md b/entitlements/README.md new file mode 100644 index 0000000..2ae0e50 --- /dev/null +++ b/entitlements/README.md @@ -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 + diff --git a/entitlements/dump-entitlements b/entitlements/dump-entitlements new file mode 100755 index 0000000..f252968 --- /dev/null +++ b/entitlements/dump-entitlements @@ -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 "$@" \ No newline at end of file diff --git a/entitlements/treebeard b/entitlements/treebeard new file mode 100755 index 0000000..c28908c --- /dev/null +++ b/entitlements/treebeard @@ -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 "$@"