#!/bin/bash set -o pipefail set -e BASE_PATH=/tmp/system-audit GIT_DIR=/var/local/system-audit function collect_hashes() { target=$1 shift for dir in $@; do if ! [ -e "${dir}" ]; then echo "${dir}" >>${BASE_PATH}/missing wrap_git add --intent-to-add ${BASE_PATH}/missing continue fi find ${dir} -mindepth 1 \( -type f -or -type l \) -print0 | xargs -0 shasum -a 512 >>${target} done if [ -e ${target} ]; then wrap_git add --intent-to-add ${target} fi } function wrap_git() { git --work-tree=${BASE_PATH} --git-dir=${GIT_DIR} "$@" return $? } # Create target directory mkdir -p ${BASE_PATH} # Initialize the dir repo if not present if ! [ -e "${GIT_DIR}" ]; then mkdir -p $(dirname ${GIT_DIR}) wrap_git init fi if [ $# -lt 1 ]; then echo "Usage: $0 " exit 1 fi case "$1" in "collect") # Remove old hash-files rm -rf ${BASE_PATH}/* # [OSX / Linux] Changing this script will cause a different behaviour # so also this needs to be monitored. collect_hashes ${BASE_PATH}/script $0 # [OSX only] LaunchAgents and LaunchDaemons can be used to execute # programs on behalf of the user or the root user. They may be used # as attack vectors. collect_hashes ${BASE_PATH}/agents_daemons /System/Library/LaunchDaemons /Library/LaunchDaemons /System/Library/LaunchAgents /Library/LaunchAgents ~/Library/LaunchAgents # [OSX / Linux ] /etc (or /private/etc on OSX) does contain configuration # for system applications and might be used to change their behaviour. collect_hashes ${BASE_PATH}/etc /etc /private/etc # [OSX / Linux] Binary folders do contain the executables used by the # system itself. Exchanging them can cause harm to the system or leak # data. collect_hashes ${BASE_PATH}/bin /usr/bin /usr/local/bin ~/bin ;; "freeze") wrap_git commit -S -a -m "Status freeze as of $(date)" ;; "check") $0 collect $0 diff --exit-code echo "Everything is still in recorded state" ;; "init") if [ $($0 log --pretty=format:'%h [%G?]%d %s (%cr) <%an>' --abbrev-commit | wc -l) -gt 0 ]; then echo "The status was already initialized. Use 'collect' and 'diff' to review the state and 'freeze' to save it" exit 1 fi $0 collect $0 freeze ;; *) wrap_git "$@" ;; esac