From f138cf0f78c03e3952801d01d25d5f8065ff1457 Mon Sep 17 00:00:00 2001 From: Ben Grande Date: Tue, 2 Jan 2024 12:17:16 +0100 Subject: [PATCH 1/3] Refactor permission-hardener - Organize comments from default configuration; - Apply and undo changes from a single file controlled by parameters; - Arrays should be evaluated as arrays and not normal variables; - Quote variables; - Brackets around variables; - Standardize test cases to "test" command; - Test against empty or non-empty variables with "-z" and "-n"; - Show a usage message when necessary; - Require root to run the script with informative message; - Permit the user to see the help message without running as root; - Do not create root directories without passing root check; - Use long options for "set" command; --- etc/permission-hardening.d/30_default.conf | 31 +- usr/bin/permission-hardening | 1043 +++++++++++--------- usr/bin/permission-hardening-undo | 136 --- 3 files changed, 615 insertions(+), 595 deletions(-) delete mode 100755 usr/bin/permission-hardening-undo diff --git a/etc/permission-hardening.d/30_default.conf b/etc/permission-hardening.d/30_default.conf index 8ff51c9..b6e4aeb 100644 --- a/etc/permission-hardening.d/30_default.conf +++ b/etc/permission-hardening.d/30_default.conf @@ -1,4 +1,4 @@ -## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP +## Copyright (C) 2012 - 2024 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. ## Please use "/etc/permission-hardening.d/20_user.conf" or @@ -9,10 +9,8 @@ ## ## Syntax: ## [filename] [mode] [owner] [group] [capability] +## [filename] [exactwhitelist|matchwhitelist|disablewhitelist|nosuid] ## -## To remove all SUID/SGID binaries in a directory, you can use the "nosuid" -## argument. - ## TODO: white spaces inside file name untested and probably will not work. ###################################################################### @@ -22,13 +20,9 @@ #whitelists_disable_all=true ###################################################################### -# SUID disablewhitelist +# SUID disables below (or in lexically higher) files: disablewhitelist ###################################################################### -## disablewhitelist disables below (or in lexically higher) files -## exactwhitelist and matchwhitelist. Add these here (discouraged) or better -## in file "/etc/permission-hardening.d/20_user.conf". - ## For example, if you are not using SELinux the following might make sense to ## enable. TODO: research #/utempter/utempter disablewhitelist @@ -37,7 +31,7 @@ #/fusermount disablewhitelist ###################################################################### -# SUID exact match whitelist +# SUID whitelist matches full path: exactwhitelist ###################################################################### ## In case you need to use 'su'. See also: @@ -45,10 +39,6 @@ #/bin/su exactwhitelist #/usr/bin/su exactwhitelist -###################################################################### -# SUID exact match whitelist -###################################################################### - ## https://manpages.debian.org/xserver-xorg-legacy/Xorg.wrap.1.en.html ## https://lwn.net/Articles/590315/ ## http://forums.whonix.org/t/permission-hardening/8655/25 @@ -56,12 +46,12 @@ #/lib/xorg/Xorg.wrap whitelist ###################################################################### -# SUID regex match whitelist +# SUID whitelist matches in any section of the path: matchwhitelist ###################################################################### -###################################################################### -# SUID regex match whitelist -###################################################################### +## Examples below are already configured: +#ssh-agent matchwhitelist +#/lib/openssh matchwhitelist ###################################################################### # Permission Hardening @@ -95,9 +85,12 @@ /etc/passwd- 0644 root root ###################################################################### -# SUID/SGID Removal +# SUID/SGID Removal: nosuid ###################################################################### +## To remove all SUID/SGID binaries in a directory, you can use the "nosuid" +## argument. +## ## Remove all SUID/SGID binaries/libraries. /bin/ nosuid diff --git a/usr/bin/permission-hardening b/usr/bin/permission-hardening index aa95cbf..7673dd7 100755 --- a/usr/bin/permission-hardening +++ b/usr/bin/permission-hardening @@ -1,510 +1,673 @@ #!/bin/bash -## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP +## Copyright (C) 2012 - 2024 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. ## https://forums.whonix.org/t/disable-suid-binaries/7706 ## https://forums.whonix.org/t/re-mount-home-and-other-with-noexec-and-nosuid-among-other-useful-mount-options-for-better-security/7707 ## To undo: -## sudo /usr/libexec/security-misc/permission-hardening-undo +## sudo permission-hardening disable -#set -x -set -e -set -o pipefail +set -o errexit -o nounset -o pipefail exit_code=0 - -mkdir --parents /var/lib/permission-hardening/private -mkdir --parents /var/lib/permission-hardening/existing_mode -mkdir --parents /var/lib/permission-hardening/new_mode -dpkg_admindir_parameter_existing_mode="--admindir /var/lib/permission-hardening/existing_mode" -dpkg_admindir_parameter_new_mode="--admindir /var/lib/permission-hardening/new_mode" +store_dir="/var/lib/permission-hardening" +dpkg_admindir_parameter_existing_mode="--admindir ${store_dir}/existing_mode" +dpkg_admindir_parameter_new_mode="--admindir ${store_dir}/new_mode" echo_wrapper_ignore() { - echo "run: $@" - "$@" 2>/dev/null || true + echo "run: $*" + "$@" 2>/dev/null || true } echo_wrapper_silent_ignore() { - #echo "run: $@" - "$@" 2>/dev/null || true + #echo "run: $@" + "$@" 2>/dev/null || true } echo_wrapper_audit() { - echo "run: $@" - return_code=0 - "$@" || \ - { \ - return_code="$?" ; \ - exit_code=203 ; \ - echo "ERROR: above command failed with exit code '$return_code'! calling function name: '${FUNCNAME[1]}'" >&2 ; \ - }; + echo "run: $*" + return_code=0 + "$@" || + { + return_code="$?" + exit_code=203 + echo "ERROR: above command failed with exit code '${return_code}'! calling function name: '${FUNCNAME[1]}'" >&2 + } } echo_wrapper_silent_audit() { - #echo "run (debugging): $@" - return_code=0 - "$@" || \ - { \ - return_code="$?" ; \ - exit_code=204 ; \ - echo "ERROR: above command '$@' failed with exit code '$return_code'! calling function name: '${FUNCNAME[1]}'" >&2 ; \ - }; + #echo "run (debugging): $@" + return_code=0 + "$@" || + { + return_code="$?" + exit_code=204 + echo "ERROR: above command '$*' failed with exit code '${return_code}'! calling function name: '${FUNCNAME[1]}'" >&2 + } +} + +make_store_dir(){ + mkdir --parents "${store_dir}/private" + mkdir --parents "${store_dir}/existing_mode" + mkdir --parents "${store_dir}/new_mode" } sanity_tests() { - echo_wrapper_silent_audit which \ - capsh getcap setcap stat find dpkg-statoverride getent xargs grep 1>/dev/null + echo_wrapper_silent_audit which \ + capsh getcap setcap stat find dpkg-statoverride getent xargs grep 1>/dev/null } add_nosuid_statoverride_entry() { - local fso_to_process - fso_to_process="$fso" - local should_be_counter - should_be_counter="$(find "$fso_to_process" -perm /u=s,g=s | wc -l)" || true - local counter_actual - counter_actual=0 + local fso_to_process + fso_to_process="${fso}" + local should_be_counter + should_be_counter="$(find "${fso_to_process}" -perm /u=s,g=s | wc -l)" || true + local counter_actual + counter_actual=0 - local line - while read -r line; do - true "line: $line" - counter_actual="$(( counter_actual + 1 ))" + local line + while read -r line; do + true "line: ${line}" + counter_actual="$((counter_actual + 1))" + + local arr file_name existing_mode existing_owner existing_group + IFS=" " read -r -a arr <<< "${line}" + file_name="${arr[0]}" + existing_mode="${arr[1]}" + existing_owner="${arr[2]}" + existing_group="${arr[3]}" + + if test "${#arr[@]}" = 0; then + echo "ERROR: arr is empty. line: '${line}'" >&2 + continue + fi + if test -z "${file_name}"; then + echo "ERROR: file_name is empty. line: '${line}'" >&2 + continue + fi + if test -z "${existing_mode}"; then + echo "ERROR: existing_mode is empty. line: '${line}'" >&2 + continue + fi + if test -z "${existing_owner}"; then + echo "ERROR: existing_owner is empty. line: '${line}'" >&2 + continue + fi + if test -z "${existing_group}"; then + echo "ERROR: existing_group is empty. line: '${line}'" >&2 + continue + fi + + ## -h file True if file is a symbolic Link. + ## -u file True if file has its set-user-id bit set. + ## -g file True if file has its set-group-id bit set. + + if test -h "${file_name}"; then + ## https://forums.whonix.org/t/disable-suid-binaries/7706/14 + true "skip symlink: ${file_name}" + continue + fi + + if test -d "${file_name}"; then + true "skip directory: ${file_name}" + continue + fi + + local setuid setuid_output setsgid setsgid_output + setuid="" + setuid_output="" + if test -u "${file_name}"; then + setuid=true + setuid_output="set-user-id" + fi + setsgid="" + setsgid_output="" + if test -g "${file_name}"; then + setsgid=true + setsgid_output="set-group-id" + fi + + local setuid_or_setsgid + setuid_or_setsgid="" + if test "${setuid}" = "true" || test "${setsgid}" = "true"; then + setuid_or_setsgid=true + fi + if test -z "${setuid_or_setsgid}"; then + continue + fi + + ## Remove suid / gid and execute permission for 'group' and 'others'. + ## Similar to: chmod og-ugx /path/to/filename + ## Removing execution permission is useful to make binaries such as 'su' + ## fail closed rather than fail open if suid was removed from these. + ## Do not remove read access since no security benefit and easier to + ## manually undo for users. + ## Are there suid or sgid binaries which are still useful if suid / sgid + ## has been removed from these? + new_mode="744" + + local is_exact_whitelisted + is_exact_whitelisted="" + for white_list_entry in ${exact_white_list}; do + if test "${file_name}" = "${white_list_entry}"; then + is_exact_whitelisted="true" + ## Stop looping through the whitelist. + break + fi + done + + local is_match_whitelisted + is_match_whitelisted="" + for matchwhite_list_entry in ${match_white_list}; do + if echo "${file_name}" | grep --quiet --fixed-strings "${matchwhite_list_entry}"; then + is_match_whitelisted="true" + ## Stop looping through the match_white_list. + break + fi + done + + local is_disable_whitelisted + is_disable_whitelisted="" + for disablematch_list_entry in ${disable_white_list:-}; do + if echo "${file_name}" | grep --quiet --fixed-strings "${disablematch_list_entry}"; then + is_disable_whitelisted="true" + ## Stop looping through the disablewhitelist. + break + fi + done + + if test "${whitelists_disable_all:-}" = "true"; then + true "INFO: whitelists_disable_all=true - ${setuid_output} ${setsgid_output} found - file_name: '${file_name}' | existing_mode: '${existing_mode}'" + elif test "${is_disable_whitelisted}" = "true"; then + true "INFO: white list disabled - ${setuid_output} ${setsgid_output} found - file_name: '${file_name}' | existing_mode: '${existing_mode}'" + else + if test "${is_exact_whitelisted}" = "true"; then + true "INFO: SKIP whitelisted - ${setuid_output} ${setsgid_output} found - file_name: '${file_name}' | existing_mode: '${existing_mode}'" + continue + fi + if test "${is_match_whitelisted}" = "true"; then + true "INFO: SKIP matchwhitelisted - ${setuid_output} ${setsgid_output} found - file_name: '${file_name}' | existing_mode: '${existing_mode}' | matchwhite_list_entry: '${matchwhite_list_entry}'" + continue + fi + fi + + echo "INFO: ${setuid_output} ${setsgid_output} found - file_name: '${file_name}' | existing_mode: '${existing_mode}' | new_mode: '${new_mode}'" + + # shellcheck disable=SC2086 + if dpkg-statoverride ${dpkg_admindir_parameter_existing_mode} --list "${file_name}" >/dev/null; then + true "OK Existing mode already saved previously. Not saving again." + else + ## Save existing_mode in separate database. + ## Not using --update as not intending to enforce existing_mode. + # shellcheck disable=SC2086 + echo_wrapper_silent_audit dpkg-statoverride ${dpkg_admindir_parameter_existing_mode} --add "${existing_owner}" "${existing_group}" "${existing_mode}" "${file_name}" + fi + + ## No need to check "dpkg-statoverride --list" for existing entries. + ## If existing_mode was correct already, we would not have reached this + ## point. Since existing_mode is incorrect, remove from dpkg-statoverride + ## and re-add. + + ## Remove from real database. + echo_wrapper_silent_ignore dpkg-statoverride --remove "${file_name}" + + ## Remove from separate database. + # shellcheck disable=SC2086 + echo_wrapper_silent_ignore dpkg-statoverride ${dpkg_admindir_parameter_new_mode} --remove "${file_name}" + + ## Add to real database and use --update to make changes on disk. + echo_wrapper_audit dpkg-statoverride --add --update "${existing_owner}" "${existing_group}" "${new_mode}" "${file_name}" + + ## Not using --update as this is only for recording. + # shellcheck disable=SC2086 + echo_wrapper_silent_audit dpkg-statoverride ${dpkg_admindir_parameter_new_mode} --add "${existing_owner}" "${existing_group}" "${new_mode}" "${file_name}" + + ## /lib will hit ARG_MAX if using bash 'shopt -s globstar' and '/lib/**'. + ## Using 'find' with '-perm /u=s,g=s' is faster and avoids ARG_MAX. + ## https://forums.whonix.org/t/disable-suid-binaries/7706/17 + done < <(find "${fso_to_process}" -perm /u=s,g=s -print0 | xargs -I{} -0 stat -c "%n %a %U %G" {}) + + ## Sanity test. + if test ! "${should_be_counter}" = "${counter_actual}"; then + echo "INFO: fso_to_process: '${fso_to_process}' | counter_actual : '${counter_actual}'" + echo "INFO: fso_to_process: '${fso_to_process}' | should_be_counter: '${should_be_counter}'" + exit_code=202 + echo "ERROR: counter does not check out." >&2 + fi +} + +set_file_perms() { + true "INFO: START parsing config_file: '${config_file}'" + local line + while read -r line || test -n "${line}"; do + if test -z "${line}"; then + continue + fi + + if [[ "${line}" =~ ^# ]]; then + continue + fi + + if [[ "${line}" =~ [0-9a-zA-Z/] ]]; then + true "OK line contains only white listed characters." + else + exit_code=200 + echo "ERROR: cannot parse line with invalid character. line: '${line}'" >&2 + ## Safer to exit with error in this case. + ## https://forums.whonix.org/t/disable-suid-binaries/7706/59 + exit "${exit_code}" + fi + + if test "${line}" = 'whitelists_disable_all=true'; then + whitelists_disable_all=true + echo "INFO: whitelists_disable_all=true - all whitelists disabled." + continue + fi + + #global fso + local mode_from_config owner_from_config group_from_config capability_from_config + if ! read -r fso mode_from_config owner_from_config group_from_config capability_from_config <<<"${line}"; then + exit_code=201 + echo "ERROR: cannot parse. line: '${line}'" >&2 + ## Debugging. + du -hs /tmp || true + echo "test -w /tmp: '$(test -w /tmp)'" >&2 || true + ## Safer to exit with error in this case. + ## https://forums.whonix.org/t/disable-suid-binaries/7706/59 + exit "${exit_code}" + fi + + ## Debugging. + #echo "line: '${line}'" + #echo "fso: '${fso}'" + #echo "mode_from_config: '${mode_from_config}'" + #echo "owner_from_config: '${owner_from_config}'" + + local fso_without_trailing_slash + fso_without_trailing_slash="${fso%/}" + + if test "${mode_from_config}" = "disablewhitelist"; then + ## TODO: test/add white spaces inside file name support + disable_white_list+="${fso} " + continue + fi + + if test "${mode_from_config}" = "exactwhitelist"; then + ## TODO: test/add white spaces inside file name support + exact_white_list+="${fso} " + continue + fi + + if test "${mode_from_config}" = "matchwhitelist"; then + ## TODO: test/add white spaces inside file name support + match_white_list+="${fso} " + continue + fi + + if test ! -e "${fso}"; then + true "INFO: fso: '${fso}' - does not exist. This is likely normal." + continue + fi + + ## Use dpkg-statoverride so permissions are not reset during upgrades. + + if test "${mode_from_config}" = "nosuid"; then + ## If mode_from_config is "nosuid" the config does not set owner and + ## group. Therefore do not enforce owner/group check. + add_nosuid_statoverride_entry + else + local string_length_of_mode_from_config + string_length_of_mode_from_config="${#mode_from_config}" + if test "${string_length_of_mode_from_config}" -gt "4"; then + echo "ERROR: Mode '${mode_from_config}' is invalid!" >&2 + continue + fi + if test "${string_length_of_mode_from_config}" -lt "3"; then + echo "ERROR: Mode '${mode_from_config}' is invalid!" >&2 + continue + fi + + if ! grep --quiet --fixed-strings "${owner_from_config}:" "${store_dir}/private/passwd"; then + echo "ERROR: owner_from_config '${owner_from_config}' does not exist!" >&2 + continue + fi + + if ! grep --quiet --fixed-strings "${group_from_config}:" "${store_dir}/private/group"; then + echo "ERROR: group_from_config '${group_from_config}' does not exist!" >&2 + continue + fi + + local mode_for_grep + mode_for_grep="${mode_from_config}" + first_character_of_mode_from_config="${mode_from_config::1}" + if test "${first_character_of_mode_from_config}" = "0"; then + ## Remove leading '0'. + mode_for_grep="${mode_from_config:1}" + fi + + local stat_output + stat_output="" + if ! stat_output="$(stat -c "%n %a %U %G" "${fso_without_trailing_slash}")"; then + echo "ERROR: failed to run 'stat' for fso_without_trailing_slash: '${fso_without_trailing_slash}'!" >&2 + continue + fi local arr file_name existing_mode existing_owner existing_group - arr=($line) + IFS=" " read -r -a arr <<< "${stat_output}" file_name="${arr[0]}" existing_mode="${arr[1]}" existing_owner="${arr[2]}" existing_group="${arr[3]}" - if [ "$arr" = "" ]; then - echo "ERROR: arr is empty. line: '$line'" >&2 - continue + if test "${#arr[@]}" = 0; then + echo "ERROR: arr is empty. stat_output: '${stat_output}' | line: '${line}'" >&2 + continue fi - if [ "$file_name" = "" ]; then - echo "ERROR: file_name is empty. line: '$line'" >&2 - continue + if test -z "${file_name}"; then + echo "ERROR: file_name is empty. stat_output: '${stat_output}' | line: '${line}'" >&2 + continue fi - if [ "$existing_mode" = "" ]; then - echo "ERROR: existing_mode is empty. line: '$line'" >&2 - continue + if test -z "${existing_mode}"; then + echo "ERROR: existing_mode is empty. stat_output: '${stat_output}' | line: '${line}'" >&2 + continue fi - if [ "$existing_owner" = "" ]; then - echo "ERROR: existing_owner is empty. line: '$line'" >&2 - continue + if test -z "${existing_owner}"; then + echo "ERROR: existing_owner is empty. stat_output: '${stat_output}' | line: '${line}'" >&2 + continue fi - if [ "$existing_group" = "" ]; then - echo "ERROR: existing_group is empty. line: '$line'" >&2 - continue + if test -z "${existing_group}"; then + echo "ERROR: ${existing_group} is empty. stat_output: '${stat_output}' | line: '${line}'" >&2 + continue fi - ## -h file True if file is a symbolic Link. - ## -u file True if file has its set-user-id bit set. - ## -g file True if file has its set-group-id bit set. + ## Check there is an entry for the fso. + ## + ## example: dpkg-statoverride --list | grep /home + ## output: + ## root root 755 /home + ## + ## dpkg-statoverride does not show leading '0'. + local dpkg_statoverride_list_output="" + local dpkg_statoverride_list_exit_code=0 + dpkg_statoverride_list_output="$(dpkg-statoverride --list "${fso_without_trailing_slash}")" || { + dpkg_statoverride_list_exit_code=$? + true + } - if test -h "$file_name" ; then - ## https://forums.whonix.org/t/disable-suid-binaries/7706/14 - true "skip symlink: $file_name" - continue - fi + if test "${dpkg_statoverride_list_exit_code}" = "0"; then + true "There is an fso entry. Check if owner/group/mode match." + local grep_line + grep_line="${owner_from_config} ${group_from_config} ${mode_for_grep} ${fso_without_trailing_slash}" + if echo "${dpkg_statoverride_list_output}" | grep --quiet --fixed-strings "${grep_line}"; then + true "OK The owner/group/mode matches. No further action required." + else + true "The owner/group/mode do not match, therefore remove and re-add the entry to update it." + ## fso_without_trailing_slash instead of fso to prevent + ## "dpkg-statoverride: warning: stripping trailing /" - if test -d "$file_name" ; then - true "skip directory: $file_name" - continue - fi + # shellcheck disable=SC2086 + if dpkg-statoverride ${dpkg_admindir_parameter_existing_mode} --list "${fso_without_trailing_slash}" >/dev/null; then + true "OK Existing mode already saved previously. No need to save again." + else + ## Save existing_mode in separate database. + ## Not using --update as not intending to enforce existing_mode. + # shellcheck disable=SC2086 + echo_wrapper_silent_audit dpkg-statoverride ${dpkg_admindir_parameter_existing_mode} --add "${existing_owner}" "${existing_group}" "${existing_mode}" "${fso_without_trailing_slash}" + fi - local setuid setuid_output setsgid setsgid_output - setuid="" - setuid_output="" - if test -u "$file_name" ; then - setuid=true - setuid_output="set-user-id" - fi - setsgid="" - setsgid_output="" - if test -g "$file_name" ; then - setsgid=true - setsgid_output="set-group-id" - fi + # shellcheck disable=SC2086 + echo_wrapper_silent_ignore dpkg-statoverride ${dpkg_admindir_parameter_new_mode} --remove "${fso_without_trailing_slash}" - local setuid_or_setsgid - setuid_or_setsgid="" - if [ "$setuid" = "true" ] || [ "$setsgid" = "true" ]; then - setuid_or_setsgid=true - fi - if [ "$setuid_or_setsgid" = "" ]; then - continue - fi + ## Remove from and add to real database. + echo_wrapper_silent_ignore dpkg-statoverride --remove "${fso_without_trailing_slash}" + echo_wrapper_audit dpkg-statoverride --add --update "${owner_from_config}" "${group_from_config}" "${mode_from_config}" "${fso_without_trailing_slash}" - ## Remove suid / gid and execute permission for 'group' and 'others'. - ## Similar to: chmod og-ugx /path/to/filename - ## Removing execution permission is useful to make binaries such as 'su' fail closed rather - ## than fail open if suid was removed from these. - ## Do not remove read access since no security benefit and easier to manually undo for users. - ## Are there suid or sgid binaries which are still useful if suid / sgid has been removed from these? - new_mode="744" - - local is_exact_whitelisted - is_exact_whitelisted="" - for white_list_entry in $exact_white_list ; do - if [ "$file_name" = "$white_list_entry" ]; then - is_exact_whitelisted="true" - ## Stop looping through the whitelist. - break - fi - done - - local is_match_whitelisted - is_match_whitelisted="" - for matchwhite_list_entry in $match_white_list ; do - if echo "$file_name" | grep --quiet --fixed-strings "$matchwhite_list_entry" ; then - is_match_whitelisted="true" - ## Stop looping through the match_white_list. - break - fi - done - - local is_disable_whitelisted - is_disable_whitelisted="" - for disablematch_list_entry in $disable_white_list ; do - if echo "$file_name" | grep --quiet --fixed-strings "$disablematch_list_entry" ; then - is_disable_whitelisted="true" - ## Stop looping through the disablewhitelist. - break - fi - done - - if [ "$whitelists_disable_all" = "true" ]; then - true "INFO: whitelists_disable_all=true - $setuid_output $setsgid_output found - file_name: '$file_name' | existing_mode: '$existing_mode'" - elif [ "$is_disable_whitelisted" = "true" ]; then - true "INFO: white list disabled - $setuid_output $setsgid_output found - file_name: '$file_name' | existing_mode: '$existing_mode'" + ## Save in separate database. + ## Not using --update as this is only for saving. + # shellcheck disable=SC2086 + echo_wrapper_silent_audit dpkg-statoverride ${dpkg_admindir_parameter_new_mode} --add "${owner_from_config}" "${group_from_config}" "${mode_from_config}" "${fso_without_trailing_slash}" + fi else - if [ "$is_exact_whitelisted" = "true" ]; then - true "INFO: SKIP whitelisted - $setuid_output $setsgid_output found - file_name: '$file_name' | existing_mode: '$existing_mode'" - continue - fi - if [ "$is_match_whitelisted" = "true" ]; then - true "INFO: SKIP matchwhitelisted - $setuid_output $setsgid_output found - file_name: '$file_name' | existing_mode: '$existing_mode' | matchwhite_list_entry: '$matchwhite_list_entry'" - continue - fi + true "There is no fso entry. Therefore add one." + + # shellcheck disable=SC2086 + if dpkg-statoverride ${dpkg_admindir_parameter_existing_mode} --list "${fso_without_trailing_slash}" >/dev/null; then + true "OK Existing mode already saved previously. No need to save again." + else + ## Save existing_mode in separate database. + ## Not using --update as not intending to enforce existing_mode. + # shellcheck disable=SC2086 + echo_wrapper_silent_audit dpkg-statoverride ${dpkg_admindir_parameter_existing_mode} --add "${existing_owner}" "${existing_group}" "${existing_mode}" "${fso_without_trailing_slash}" + fi + + ## Add to real database. + echo_wrapper_audit dpkg-statoverride --add --update "${owner_from_config}" "${group_from_config}" "${mode_from_config}" "${fso_without_trailing_slash}" + + ## Save in separate database. + ## Not using --update as this is only for saving. + # shellcheck disable=SC2086 + echo_wrapper_silent_audit dpkg-statoverride ${dpkg_admindir_parameter_new_mode} --add "${owner_from_config}" "${group_from_config}" "${mode_from_config}" "${fso_without_trailing_slash}" + fi + fi + if test -z "${capability_from_config}"; then + continue + fi + + if test "${capability_from_config}" = "none"; then + ## https://forums.whonix.org/t/disable-suid-binaries/7706/45 + ## sudo setcap -r /bin/ping 2>/dev/null + ## Failed to set capabilities on file '/bin/ping' (No data available) + ## The value of the capability argument is not permitted for a file. Or + ## the file is not a regular (non-symlink) file + ## Therefore use echo_wrapper_ignore. + echo_wrapper_ignore setcap -r "${fso}" + getcap_output="$(getcap "${fso}")" + if test -n "${getcap_output}"; then + exit_code=205 + echo "ERROR: removing capabilities for fso '${fso}' failed!" >&2 + continue + fi + else + if ! capsh --print | grep --fixed-strings "Bounding set" | grep --quiet "${capability_from_config}"; then + echo "ERROR: capability_from_config '${capability_from_config}' does not exist!" >&2 + continue fi - echo "INFO: $setuid_output $setsgid_output found - file_name: '$file_name' | existing_mode: '$existing_mode' | new_mode: '$new_mode'" - - if dpkg-statoverride $dpkg_admindir_parameter_existing_mode --list "$file_name" >/dev/null ; then - true "OK Existing mode already saved previously. No need to save again." - else - ## Save existing_mode in separate database. - ## Not using --update as not intending to enforce existing_mode. - echo_wrapper_silent_audit dpkg-statoverride $dpkg_admindir_parameter_existing_mode --add "$existing_owner" "$existing_group" "$existing_mode" "$file_name" - fi - - ## No need to check "dpkg-statoverride --list" for existing entries. - ## If existing_mode was correct already, we would not have reached this point. - ## Since existing_mode is incorrect, remove from dpkg-statoverride and re-add. - - ## Remove from real database. - echo_wrapper_silent_ignore dpkg-statoverride --remove "$file_name" - - ## Remove from separate database. - echo_wrapper_silent_ignore dpkg-statoverride $dpkg_admindir_parameter_new_mode --remove "$file_name" - - ## Add to real database and use --update to make changes on disk. - echo_wrapper_audit dpkg-statoverride --add --update "$existing_owner" "$existing_group" "$new_mode" "$file_name" - - ## Not using --update as this is only for recording. - echo_wrapper_silent_audit dpkg-statoverride $dpkg_admindir_parameter_new_mode --add "$existing_owner" "$existing_group" "$new_mode" "$file_name" - - ## /lib will hit ARG_MAX if using bash 'shopt -s globstar' and '/lib/**'. - ## Using 'find' with '-perm /u=s,g=s' is faster and avoids ARG_MAX. - ## https://forums.whonix.org/t/disable-suid-binaries/7706/17 - done < <( find "$fso_to_process" -perm /u=s,g=s -print0 | xargs -I{} -0 stat -c "%n %a %U %G" {} ) - - ## Sanity test. - if [ ! "$should_be_counter" = "$counter_actual" ]; then - echo "INFO: fso_to_process: '$fso_to_process' | counter_actual : '$counter_actual'" - echo "INFO: fso_to_process: '$fso_to_process' | should_be_counter: '$should_be_counter'" - exit_code=202 - echo "ERROR: counter does not check out." >&2 - fi -} - -set_file_perms() { - true "INFO: START parsing config_file: '$config_file'" - local line - while read -r line || [[ -n "${line}" ]]; do - if [ "$line" = "" ]; then - continue - fi - - if [[ "$line" =~ ^# ]]; then - continue - fi - - if [[ "$line" =~ [0-9a-zA-Z/] ]]; then - true "OK line contains only white listed characters." - else - exit_code=200 - echo "ERROR: cannot parse line with invalid character. line: '$line'" >&2 - ## Safer to exit with error in this case. - ## https://forums.whonix.org/t/disable-suid-binaries/7706/59 - exit "$exit_code" - fi - - if [ "$line" = 'whitelists_disable_all=true' ]; then - whitelists_disable_all=true - echo "INFO: whitelists_disable_all=true - all whitelists disabled." - continue - fi - - #global fso - local mode_from_config owner_from_config group_from_config capability_from_config - if ! read -r fso mode_from_config owner_from_config group_from_config capability_from_config <<< "$line" ; then - exit_code=201 - echo "ERROR: cannot parse. line: '$line'" >&2 - ## Debugging. - du -hs /tmp || true - echo "test -w /tmp: '$(test -w /tmp)'" >&2 || true - ## Safer to exit with error in this case. - ## https://forums.whonix.org/t/disable-suid-binaries/7706/59 - exit "$exit_code" - fi - - ## Debugging. - #echo "line: '$line'" - #echo "fso: '$fso'" - #echo "mode_from_config: '$mode_from_config'" - #echo "owner_from_config: '$owner_from_config'" - - local fso_without_trailing_slash - fso_without_trailing_slash="${fso%/}" - - if [ "$mode_from_config" = "disablewhitelist" ]; then - ## TODO: test/add white spaces inside file name support - disable_white_list+="$fso " - continue - fi - - if [ "$mode_from_config" = "exactwhitelist" ]; then - ## TODO: test/add white spaces inside file name support - exact_white_list+="$fso " - continue - fi - - if [ "$mode_from_config" = "matchwhitelist" ]; then - ## TODO: test/add white spaces inside file name support - match_white_list+="$fso " - continue - fi - - if [ ! -e "$fso" ]; then - true "INFO: fso: '$fso' - does not exist. This is likely normal." - continue - fi - - ## Use dpkg-statoverride so permissions are not reset during upgrades. - - if [ "$mode_from_config" = "nosuid" ]; then - ## If mode_from_config is "nosuid" the config does not set owner and - ## group. Therefore do not enforce owner/group check. - - add_nosuid_statoverride_entry - else - local string_length_of_mode_from_config - string_length_of_mode_from_config="${#mode_from_config}" - if [ "$string_length_of_mode_from_config" -gt "4" ]; then - echo "ERROR: Mode '$mode_from_config' is invalid!" >&2 - continue - fi - if [ "$string_length_of_mode_from_config" -lt "3" ]; then - echo "ERROR: Mode '$mode_from_config' is invalid!" >&2 - continue - fi - - if ! grep --quiet --fixed-strings "${owner_from_config}:" /var/lib/permission-hardening/private/passwd ; then - echo "ERROR: owner_from_config '$owner_from_config' does not exist!" >&2 - continue - fi - - if ! grep --quiet --fixed-strings "${group_from_config}:" /var/lib/permission-hardening/private/group ; then - echo "ERROR: group_from_config '$group_from_config' does not exist!" >&2 - continue - fi - - local mode_for_grep - mode_for_grep="$mode_from_config" - first_character_of_mode_from_config="${mode_from_config::1}" - if [ "$first_character_of_mode_from_config" = "0" ]; then - ## Remove leading '0'. - mode_for_grep="${mode_from_config:1}" - fi - - local stat_output - stat_output="" - if ! stat_output="$(stat -c "%n %a %U %G" "$fso_without_trailing_slash")" ; then - echo "ERROR: failed to run 'stat' for fso_without_trailing_slash: '$fso_without_trailing_slash'!" >&2 - continue - fi - - local arr file_name existing_mode existing_owner existing_group - arr=($stat_output) - file_name="${arr[0]}" - existing_mode="${arr[1]}" - existing_owner="${arr[2]}" - existing_group="${arr[3]}" - - if [ "$arr" = "" ]; then - echo "ERROR: arr is empty. stat_output: '$stat_output' | line: '$line'" >&2 - continue - fi - if [ "$file_name" = "" ]; then - echo "ERROR: file_name is empty. stat_output: '$stat_output' | line: '$line'" >&2 - continue - fi - if [ "$existing_mode" = "" ]; then - echo "ERROR: existing_mode is empty. stat_output: '$stat_output' | line: '$line'" >&2 - continue - fi - if [ "$existing_owner" = "" ]; then - echo "ERROR: existing_owner is empty. stat_output: '$stat_output' | line: '$line'" >&2 - continue - fi - if [ "$existing_group" = "" ]; then - echo "ERROR: $existing_group is empty. stat_output: '$stat_output' | line: '$line'" >&2 - continue - fi - - ## Check there is an entry for the fso. - ## - ## example: dpkg-statoverride --list | grep /home - ## output: - ## root root 755 /home - ## - ## dpkg-statoverride does not show leading '0'. - local dpkg_statoverride_list_output="" - local dpkg_statoverride_list_exit_code=0 - dpkg_statoverride_list_output="$(dpkg-statoverride --list "$fso_without_trailing_slash")" || { dpkg_statoverride_list_exit_code=$? ; true; }; - - if [ "$dpkg_statoverride_list_exit_code" = "0" ]; then - true "There is an fso entry. Check if owner/group/mode match." - local grep_line - grep_line="$owner_from_config $group_from_config $mode_for_grep $fso_without_trailing_slash" - if echo "$dpkg_statoverride_list_output" | grep --quiet --fixed-strings "$grep_line" ; then - true "OK The owner/group/mode matches. No further action required." - else - true "The owner/group/mode do not match, therefore remove and re-add the entry to update it." - ## fso_without_trailing_slash instead of fso to prevent - ## "dpkg-statoverride: warning: stripping trailing /" - - if dpkg-statoverride $dpkg_admindir_parameter_existing_mode --list "$fso_without_trailing_slash" >/dev/null ; then - true "OK Existing mode already saved previously. No need to save again." - else - ## Save existing_mode in separate database. - ## Not using --update as not intending to enforce existing_mode. - echo_wrapper_silent_audit dpkg-statoverride $dpkg_admindir_parameter_existing_mode --add "$existing_owner" "$existing_group" "$existing_mode" "$fso_without_trailing_slash" - fi - - echo_wrapper_silent_ignore dpkg-statoverride $dpkg_admindir_parameter_new_mode --remove "$fso_without_trailing_slash" - - ## Remove from and add to real database. - echo_wrapper_silent_ignore dpkg-statoverride --remove "$fso_without_trailing_slash" - echo_wrapper_audit dpkg-statoverride --add --update "$owner_from_config" "$group_from_config" "$mode_from_config" "$fso_without_trailing_slash" - - ## Save in separate database. - ## Not using --update as this is only for saving. - echo_wrapper_silent_audit dpkg-statoverride $dpkg_admindir_parameter_new_mode --add "$owner_from_config" "$group_from_config" "$mode_from_config" "$fso_without_trailing_slash" - fi - else - true "There is no fso entry. Therefore add one." - - if dpkg-statoverride $dpkg_admindir_parameter_existing_mode --list "$fso_without_trailing_slash" >/dev/null ; then - true "OK Existing mode already saved previously. No need to save again." - else - ## Save existing_mode in separate database. - ## Not using --update as not intending to enforce existing_mode. - echo_wrapper_silent_audit dpkg-statoverride $dpkg_admindir_parameter_existing_mode --add "$existing_owner" "$existing_group" "$existing_mode" "$fso_without_trailing_slash" - fi - - ## Add to real database. - echo_wrapper_audit dpkg-statoverride --add --update "$owner_from_config" "$group_from_config" "$mode_from_config" "$fso_without_trailing_slash" - - ## Save in separate database. - ## Not using --update as this is only for saving. - echo_wrapper_silent_audit dpkg-statoverride $dpkg_admindir_parameter_new_mode --add "$owner_from_config" "$group_from_config" "$mode_from_config" "$fso_without_trailing_slash" - fi - fi - if [ "$capability_from_config" = "" ]; then - continue - fi - - if [ "$capability_from_config" = "none" ]; then - ## https://forums.whonix.org/t/disable-suid-binaries/7706/45 - # sudo setcap -r /bin/ping 2>/dev/null - # Failed to set capabilities on file '/bin/ping' (No data available) - # The value of the capability argument is not permitted for a file. Or the file is not a regular (non-symlink) file - ## Therefore use echo_wrapper_ignore. - echo_wrapper_ignore setcap -r "$fso" - getcap_output="$(getcap "$fso")" - if [ ! "$getcap_output" = "" ]; then - exit_code=205 - echo "ERROR: removing capabilities for fso '$fso' failed!" >&2 - continue - fi - else - if ! capsh --print | grep --fixed-strings "Bounding set" | grep --quiet "$capability_from_config" ; then - echo "ERROR: capability_from_config '$capability_from_config' does not exist!" >&2 - continue - fi - - ## feature request: dpkg-statoverride: support for capabilities - ## https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=502580 - echo_wrapper_audit setcap "${capability_from_config}+ep" "$fso" - fi - done < "$config_file" - true "INFO: END parsing config_file: '$config_file'" + ## feature request: dpkg-statoverride: support for capabilities + ## https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=502580 + echo_wrapper_audit setcap "${capability_from_config}+ep" "${fso}" + fi + done <"${config_file}" + true "INFO: END parsing config_file: '${config_file}'" } parse_config_folder() { - touch /var/lib/permission-hardening/private/passwd - chmod og-rwx /var/lib/permission-hardening/private/passwd - touch /var/lib/permission-hardening/private/group - chmod og-rwx /var/lib/permission-hardening/private/group + touch "${store_dir}/private/passwd" + chmod og-rwx "${store_dir}/private/passwd" + touch "${store_dir}/private/group" + chmod og-rwx "${store_dir}/private/group" local passwd_file_contents_temp - # Query contents of password and group databases only once and buffer them - # - # If we don't buffer we sometimes get incorrect results when checking for entries using - # 'if getent passwd | grep --quiet '^root:'; ...' since 'grep' exits after the first match in - # this case causing 'getent' to receive SIGPIPE, which then fails the pipeline since - # 'set -o pipefail' is set for this script. + ## Query contents of password and group databases only once and buffer them + ## + ## If we don't buffer we sometimes get incorrect results when checking for + ## entries using 'if getent passwd | grep --quiet '^root:'; ...' since + ## 'grep' exits after the first match in this case causing 'getent' to + ## receive SIGPIPE, which then fails the pipeline since 'set -o pipefail' is + ## set for this script. passwd_file_contents_temp=$(getent passwd) - echo "$passwd_file_contents_temp" | tee /var/lib/permission-hardening/private/passwd >/dev/null + echo "${passwd_file_contents_temp}" | tee "${store_dir}/private/passwd" >/dev/null group_file_contents_temp=$(getent group) - echo "$group_file_contents_temp" | tee /var/lib/permission-hardening/private/group >/dev/null + echo "${group_file_contents_temp}" | tee "${store_dir}/private/group" >/dev/null - passwd_file_contents=$(cat /var/lib/permission-hardening/private/passwd) - group_file_contents=$(cat /var/lib/permission-hardening/private/group) + passwd_file_contents="$(cat "${store_dir}/private/passwd")" + group_file_contents="$(cat "${store_dir}/private/group")" shopt -s nullglob - for config_file in /etc/permission-hardening.d/*.conf /usr/local/etc/permission-hardening.d/*.conf; do + for config_file in \ + /etc/permission-hardening.d/*.conf \ + /usr/local/etc/permission-hardening.d/*.conf + do set_file_perms done } -sanity_tests -parse_config_folder +apply() { + check_root + make_store_dir + sanity_tests + parse_config_folder -echo "\ + echo "\ INFO: To compare the current and previous permission modes: -1. Install 'meld' (or similar) for an easier comparison of file changes: - sudo apt install --no-install-recommends meld + Install 'meld' (or preferred diff tool) for comparison of file mode changes: + sudo apt install --no-install-recommends meld -2. Use 'meld' to view the differences: - meld /var/lib/permission-hardening/existing_mode/statoverride /var/lib/permission-hardening/new_mode/statoverride" + Use 'meld' or another diff tool to view the differences: + meld ${store_dir}/existing_mode/statoverride ${store_dir}/new_mode/statoverride" +} -if [ ! "$exit_code" = "0" ]; then - echo "ERROR: Will exit with non-zero exit code: '$exit_code'" >&2 +spare() { + check_root + make_store_dir + + remove_file="${1}" + exit_code=0 + dpkg_admindir_parameter_existing_mode="--admindir ${store_dir}/existing_mode" + dpkg_admindir_parameter_new_mode="--admindir ${store_dir}/new_mode" + + if test ! -f "${store_dir}/existing_mode/statoverride"; then + return 0 + fi + + local line + while read -r line; do + ## example line: + ## root root 4755 /usr/lib/eject/dmcrypt-get-device + + local owner group mode file_name + if ! read -r owner group mode file_name <<< "${line}"; then + exit_code=201 + echo "ERROR: cannot parse line: ${line}" >&2 + continue + fi + true "owner: '${owner}' group: '${group}' mode: '${mode}' file_name: '${file_name}'" + + if test "${remove_file}" = "all"; then + proceed=true + verbose="" + remove_one=false + else + if test "${remove_file}" = "${file_name}"; then + proceed=true + verbose="--verbose" + remove_one=true + else + proceed=false + verbose="" + fi + fi + + if test "${proceed}" = "false"; then + continue + fi + + if test "${remove_one}" = "true"; then + set -o xtrace + fi + + if test -e "${file_name}"; then + chown ${verbose} "${owner}:${group}" "${file_name}" || exit_code=202 + ## chmod need to be run after chown since chown removes suid. + ## https://unix.stackexchange.com/questions/53665/chown-removes-setuid-bit-bug-or-feature + chmod ${verbose} "${mode}" "${file_name}" || exit_code=203 + else + echo "INFO: file_name: '${file_name}' - does not exist. This is likely normal." + fi + + dpkg-statoverride --remove "${file_name}" &>/dev/null || true + # shellcheck disable=SC2086 + dpkg-statoverride ${dpkg_admindir_parameter_existing_mode} --remove "${file_name}" &>/dev/null || true + # shellcheck disable=SC2086 + dpkg-statoverride ${dpkg_admindir_parameter_new_mode} --remove "${file_name}" &>/dev/null || true + + if test "${remove_one}" = "true"; then + set +o xtrace + break + fi + + done < "${store_dir}/existing_mode/statoverride" + + if test ! "${remove_file}" = "all"; then + if test ! "${remove_one}" = "true"; then + echo "INFO: no file removed. + + File '${remove_file}' has not removed from SUID Disabler and Permission Hardener during this invocation of this program. + + Note: This is expected if already done earlier. + + Note: This program expects the full path to the file. Example: + $0 disable /usr/bin/newgrp + + The following syntax will not work: + $0 disable program-name + + The following example will not work: + $0 disable newgrp + + To remove all: + $0 disable all + + This change might not be permanent (because of the permission-hardening.service systemd unit). For full instructions, see: + https://www.kicksecure.com/wiki/SUID_Disabler_and_Permission_Hardener + + To view list of changed by SUID Disabler and Permission Hardener: + https://www.kicksecure.com/wiki/SUID_Disabler_and_Permission_Hardener#View_List_of_Permissions_Changed_by_SUID_Disabler_and_Permission_Hardener + + For re-enabling any specific SUID binary: + https://www.kicksecure.com/wiki/SUID_Disabler_and_Permission_Hardener#Re-Enable_Specific_SUID_Binaries + + For completely disabling SUID Disabler and Permission Hardener: + https://www.kicksecure.com/wiki/SUID_Disabler_and_Permission_Hardener#Disable_SUID_Disabler_and_Permission_Hardener" + fi + fi +} + +check_root(){ + if test "$(id -u)" != "0"; then + echo "ERROR: Not running as root, aborting." + exit 1 + fi +} + +usage(){ + echo "Usage: ${0##*/} enable + ${0##*/} disable [FILE|all] + +Examples: + ${0##*/} enable + ${0##*/} disable all + ${0##*/} disable /usr/bin/newgrp" >&2 + exit "${1}" +} + +case "${1:-}" in + enable) shift; apply "$@";; + disable) + shift + case "${1:-}" in + "") usage;; + *) spare "${1}";; + esac + ;; + -h|--help) usage 0;; + *) usage 1;; +esac + +if test "${exit_code}" != "0"; then + echo "ERROR: Exiting with non-zero exit code: '${exit_code}'" >&2 fi -exit "$exit_code" +exit "${exit_code}" diff --git a/usr/bin/permission-hardening-undo b/usr/bin/permission-hardening-undo deleted file mode 100755 index ca22500..0000000 --- a/usr/bin/permission-hardening-undo +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/bash - -## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP -## See the file COPYING for copying conditions. - -#set -x -set -e -set -o pipefail - -if [ "$1" = "all" ]; then - remove_file="all" -elif [ ! "$1" = "" ]; then - remove_file="$1" -else - echo "ERROR: need to give parameter 'all' or a filename. - -examples: - -$0 all - -$0 /usr/bin/newgrp - " >&2 -fi - -exit_code=0 - -dpkg_admindir_parameter_existing_mode="--admindir /var/lib/permission-hardening/existing_mode" -dpkg_admindir_parameter_new_mode="--admindir /var/lib/permission-hardening/new_mode" - -undo_permission_hardening() { - if [ ! -f /var/lib/permission-hardening/existing_mode/statoverride ]; then - return 0 - fi - - local line - - while read -r line; do - ## example line: - ## root root 4755 /usr/lib/eject/dmcrypt-get-device - - local owner group mode file_name - if ! read -r owner group mode file_name <<< "$line" ; then - exit_code=201 - echo "ERROR: cannot parse line: $line" >&2 - continue - fi - true "owner: '$owner' group: '$group' mode: '$mode' file_name: '$file_name'" - - if [ "$remove_file" = "all" ]; then - do_proceed=true - verbose_maybe="" - else - if [ "$remove_file" = "$file_name" ]; then - do_proceed=true - verbose_maybe="--verbose" - remove_one=true - else - do_proceed=false - verbose_maybe="" - fi - fi - - if [ "$do_proceed" = "false" ]; then - continue - fi - - if [ "$remove_one" = "true" ]; then - set -x - fi - - if test -e "$file_name" ; then - chown $verbose_maybe "${owner}:${group}" "$file_name" || exit_code=202 - ## chmod need to be run after chown since chown removes suid. - ## https://unix.stackexchange.com/questions/53665/chown-removes-setuid-bit-bug-or-feature - chmod $verbose_maybe "$mode" "$file_name" || exit_code=203 - else - echo "INFO: file_name: '$file_name' - does not exist. This is likely normal." - fi - - dpkg-statoverride --remove "$file_name" &>/dev/null || true - dpkg-statoverride $dpkg_admindir_parameter_existing_mode --remove "$file_name" &>/dev/null || true - dpkg-statoverride $dpkg_admindir_parameter_new_mode --remove "$file_name" &>/dev/null || true - - if [ "$remove_one" = "true" ]; then - set +x - break - fi - - done < "/var/lib/permission-hardening/existing_mode/statoverride" -} - -undo_permission_hardening - -if [ ! "$remove_file" = "all" ]; then - if [ ! "$remove_one" = "true" ]; then - echo "INFO: none removed. - -File '$remove_file' has not removed from SUID Disabler and Permission Hardener during this invocation of this program. - -Note: This is expected if already done earlier. - -Note: This program expects the full path to the file. Example: - -$0 /usr/bin/newgrp - -The following syntax will not work: - -$0 program-name - -The following example will not work: - -$0 newgrp - -To remove all: - -$0 all - -This change might not be permanent (because of the permission-hardening.service systemd unit). For full instructions, see: -https://www.kicksecure.com/wiki/SUID_Disabler_and_Permission_Hardener - -To view list of changed by SUID Disabler and Permission Hardener: -https://www.kicksecure.com/wiki/SUID_Disabler_and_Permission_Hardener#View_List_of_Permissions_Changed_by_SUID_Disabler_and_Permission_Hardener - -For re-enabling any specific SUID binary: -https://www.kicksecure.com/wiki/SUID_Disabler_and_Permission_Hardener#Re-Enable_Specific_SUID_Binaries - -For completely disabling SUID Disabler and Permission Hardener: -https://www.kicksecure.com/wiki/SUID_Disabler_and_Permission_Hardener#Disable_SUID_Disabler_and_Permission_Hardener" - fi -fi - -if [ ! "$exit_code" = "0" ]; then - echo "ERROR: Will exit with non-zero exit code: '$exit_code'" >&2 -fi - -exit "$exit_code" From abf72c2ee4286ec069f75e66acf05a42f3645c89 Mon Sep 17 00:00:00 2001 From: Ben Grande Date: Tue, 2 Jan 2024 13:34:29 +0100 Subject: [PATCH 2/3] Rename file permission hardening script Hardener as the script is the agent that is hardening the file permissions. --- README.md | 10 +++++----- debian/security-misc.postinst | 6 +++--- .../25_default_passwd.conf | 4 ++-- .../25_default_sudo.conf | 4 ++-- .../25_default_whitelist_bubblewrap.conf | 4 ++-- .../25_default_whitelist_chromium.conf | 4 ++-- .../25_default_whitelist_dbus.conf | 4 ++-- .../25_default_whitelist_firejail.conf | 4 ++-- .../25_default_whitelist_fuse.conf | 4 ++-- .../25_default_whitelist_hardened_malloc.conf | 4 ++-- .../25_default_whitelist_mount.conf | 4 ++-- .../25_default_whitelist_pam.conf | 4 ++-- .../25_default_whitelist_policykit.conf | 4 ++-- .../25_default_whitelist_qubes.conf | 4 ++-- .../25_default_whitelist_selinux.conf | 4 ++-- .../25_default_whitelist_spice.conf | 4 ++-- .../25_default_whitelist_ssh.conf | 4 ++-- .../25_default_whitelist_sudo.conf | 4 ++-- .../25_default_whitelist_unix_chkpwd.conf | 4 ++-- .../25_default_whitelist_virtualbox.conf | 4 ++-- .../30_default.conf | 8 ++++---- lib/systemd/system-preset/50-security-misc.preset | 2 +- ...n-hardening.service => permission-hardener.service} | 2 +- usr/bin/{permission-hardening => permission-hardener} | 9 ++++----- 24 files changed, 54 insertions(+), 55 deletions(-) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_passwd.conf (80%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_sudo.conf (89%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_bubblewrap.conf (66%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_chromium.conf (63%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_dbus.conf (64%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_firejail.conf (74%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_fuse.conf (72%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_hardened_malloc.conf (68%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_mount.conf (81%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_pam.conf (69%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_policykit.conf (79%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_qubes.conf (81%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_selinux.conf (64%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_spice.conf (65%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_ssh.conf (69%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_sudo.conf (65%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_unix_chkpwd.conf (74%) rename etc/{permission-hardening.d => permission-hardener.d}/25_default_whitelist_virtualbox.conf (77%) rename etc/{permission-hardening.d => permission-hardener.d}/30_default.conf (94%) rename lib/systemd/system/{permission-hardening.service => permission-hardener.service} (93%) rename usr/bin/{permission-hardening => permission-hardener} (99%) diff --git a/README.md b/README.md index 4ac4fb6..a46b30a 100644 --- a/README.md +++ b/README.md @@ -430,23 +430,23 @@ include but are not limited to: - Protecting the information of sudoers from others. - Protecting various system relevant files and modules. -##### permission-hardening ##### +##### permission-hardener ##### `permission-hardener` removes SUID / SGID bits from non-essential binaries as these are often used in privilege escalation attacks. It runs at package installation and upgrade time. There is also an optional systemd unit which does the same at boot time that -can be enabled by running `systemctl enable permission-hardening.service` as +can be enabled by running `systemctl enable permission-hardener.service` as root. The hardening at boot time is not the default because this slows down the boot too much. See: -* `/usr/bin/permission-hardening` +* `/usr/bin/permission-hardener` * `debian/security-misc.postinst` -* `/lib/systemd/system/permission-hardening.service` -* `/etc/permission-hardening.d` +* `/lib/systemd/system/permission-hardener.service` +* `/etc/permission-hardener.d` * https://forums.whonix.org/t/disable-suid-binaries/7706 * https://www.kicksecure.com/wiki/SUID_Disabler_and_Permission_Hardener diff --git a/debian/security-misc.postinst b/debian/security-misc.postinst index 7cd54c2..da358e3 100644 --- a/debian/security-misc.postinst +++ b/debian/security-misc.postinst @@ -20,8 +20,8 @@ permission_hardening() { echo "Running SUID Disabler and Permission Hardener... See also:" echo "https://www.kicksecure.com/wiki/SUID_Disabler_and_Permission_Hardener" echo "" - echo "$0: INFO: running: permission-hardening" - if ! permission-hardening ; then + echo "$0: INFO: running: permission-hardener" + if ! permission-hardener ; then echo "$0: ERROR: Permission hardening failed." >&2 return 0 fi @@ -59,7 +59,7 @@ esac pam-auth-update --package /usr/libexec/security-misc/permission-lockdown -permission_hardening +permission_hardener ## https://phabricator.whonix.org/T377 ## Debian has no update-grub trigger yet: diff --git a/etc/permission-hardening.d/25_default_passwd.conf b/etc/permission-hardener.d/25_default_passwd.conf similarity index 80% rename from etc/permission-hardening.d/25_default_passwd.conf rename to etc/permission-hardener.d/25_default_passwd.conf index 32fd72e..dcd403f 100644 --- a/etc/permission-hardening.d/25_default_passwd.conf +++ b/etc/permission-hardener.d/25_default_passwd.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. # Keep the `passwd` utility executable to prevent issues with the diff --git a/etc/permission-hardening.d/25_default_sudo.conf b/etc/permission-hardener.d/25_default_sudo.conf similarity index 89% rename from etc/permission-hardening.d/25_default_sudo.conf rename to etc/permission-hardener.d/25_default_sudo.conf index 67be9ac..6a1cf21 100644 --- a/etc/permission-hardening.d/25_default_sudo.conf +++ b/etc/permission-hardener.d/25_default_sudo.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. ## https://forums.whonix.org/t/restrict-root-access/7658/116 diff --git a/etc/permission-hardening.d/25_default_whitelist_bubblewrap.conf b/etc/permission-hardener.d/25_default_whitelist_bubblewrap.conf similarity index 66% rename from etc/permission-hardening.d/25_default_whitelist_bubblewrap.conf rename to etc/permission-hardener.d/25_default_whitelist_bubblewrap.conf index 2ffc8c2..071e724 100644 --- a/etc/permission-hardening.d/25_default_whitelist_bubblewrap.conf +++ b/etc/permission-hardener.d/25_default_whitelist_bubblewrap.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. /usr/bin/bwrap exactwhitelist diff --git a/etc/permission-hardening.d/25_default_whitelist_chromium.conf b/etc/permission-hardener.d/25_default_whitelist_chromium.conf similarity index 63% rename from etc/permission-hardening.d/25_default_whitelist_chromium.conf rename to etc/permission-hardener.d/25_default_whitelist_chromium.conf index 5244b2c..db6f8ea 100644 --- a/etc/permission-hardening.d/25_default_whitelist_chromium.conf +++ b/etc/permission-hardener.d/25_default_whitelist_chromium.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. chrome-sandbox matchwhitelist diff --git a/etc/permission-hardening.d/25_default_whitelist_dbus.conf b/etc/permission-hardener.d/25_default_whitelist_dbus.conf similarity index 64% rename from etc/permission-hardening.d/25_default_whitelist_dbus.conf rename to etc/permission-hardener.d/25_default_whitelist_dbus.conf index e1325ff..2997915 100644 --- a/etc/permission-hardening.d/25_default_whitelist_dbus.conf +++ b/etc/permission-hardener.d/25_default_whitelist_dbus.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. dbus-daemon-launch-helper matchwhitelist diff --git a/etc/permission-hardening.d/25_default_whitelist_firejail.conf b/etc/permission-hardener.d/25_default_whitelist_firejail.conf similarity index 74% rename from etc/permission-hardening.d/25_default_whitelist_firejail.conf rename to etc/permission-hardener.d/25_default_whitelist_firejail.conf index 99608df..a56cb23 100644 --- a/etc/permission-hardening.d/25_default_whitelist_firejail.conf +++ b/etc/permission-hardener.d/25_default_whitelist_firejail.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. ## There is a controversy about firejail but those who choose to install it diff --git a/etc/permission-hardening.d/25_default_whitelist_fuse.conf b/etc/permission-hardener.d/25_default_whitelist_fuse.conf similarity index 72% rename from etc/permission-hardening.d/25_default_whitelist_fuse.conf rename to etc/permission-hardener.d/25_default_whitelist_fuse.conf index 1293214..4affc6a 100644 --- a/etc/permission-hardening.d/25_default_whitelist_fuse.conf +++ b/etc/permission-hardener.d/25_default_whitelist_fuse.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. ## required for AppImages such as electrum Bitcoin wallet diff --git a/etc/permission-hardening.d/25_default_whitelist_hardened_malloc.conf b/etc/permission-hardener.d/25_default_whitelist_hardened_malloc.conf similarity index 68% rename from etc/permission-hardening.d/25_default_whitelist_hardened_malloc.conf rename to etc/permission-hardener.d/25_default_whitelist_hardened_malloc.conf index 4934ff0..6cc01fe 100644 --- a/etc/permission-hardening.d/25_default_whitelist_hardened_malloc.conf +++ b/etc/permission-hardener.d/25_default_whitelist_hardened_malloc.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. libhardened_malloc.so matchwhitelist diff --git a/etc/permission-hardening.d/25_default_whitelist_mount.conf b/etc/permission-hardener.d/25_default_whitelist_mount.conf similarity index 81% rename from etc/permission-hardening.d/25_default_whitelist_mount.conf rename to etc/permission-hardener.d/25_default_whitelist_mount.conf index 1557318..ce7d014 100644 --- a/etc/permission-hardening.d/25_default_whitelist_mount.conf +++ b/etc/permission-hardener.d/25_default_whitelist_mount.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. ## https://forums.whonix.org/t/disable-suid-binaries/7706/61 diff --git a/etc/permission-hardening.d/25_default_whitelist_pam.conf b/etc/permission-hardener.d/25_default_whitelist_pam.conf similarity index 69% rename from etc/permission-hardening.d/25_default_whitelist_pam.conf rename to etc/permission-hardener.d/25_default_whitelist_pam.conf index bf518ff..7348e0c 100644 --- a/etc/permission-hardening.d/25_default_whitelist_pam.conf +++ b/etc/permission-hardener.d/25_default_whitelist_pam.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. ## Without this, Xfce fails to start with a dbus-launch error. diff --git a/etc/permission-hardening.d/25_default_whitelist_policykit.conf b/etc/permission-hardener.d/25_default_whitelist_policykit.conf similarity index 79% rename from etc/permission-hardening.d/25_default_whitelist_policykit.conf rename to etc/permission-hardener.d/25_default_whitelist_policykit.conf index fb4fa86..032c6b2 100644 --- a/etc/permission-hardening.d/25_default_whitelist_policykit.conf +++ b/etc/permission-hardener.d/25_default_whitelist_policykit.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. /usr/bin/pkexec exactwhitelist diff --git a/etc/permission-hardening.d/25_default_whitelist_qubes.conf b/etc/permission-hardener.d/25_default_whitelist_qubes.conf similarity index 81% rename from etc/permission-hardening.d/25_default_whitelist_qubes.conf rename to etc/permission-hardener.d/25_default_whitelist_qubes.conf index 7a5c968..ad8592a 100644 --- a/etc/permission-hardening.d/25_default_whitelist_qubes.conf +++ b/etc/permission-hardener.d/25_default_whitelist_qubes.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. ## TODO: research diff --git a/etc/permission-hardening.d/25_default_whitelist_selinux.conf b/etc/permission-hardener.d/25_default_whitelist_selinux.conf similarity index 64% rename from etc/permission-hardening.d/25_default_whitelist_selinux.conf rename to etc/permission-hardener.d/25_default_whitelist_selinux.conf index f0464b9..2a5686a 100644 --- a/etc/permission-hardening.d/25_default_whitelist_selinux.conf +++ b/etc/permission-hardener.d/25_default_whitelist_selinux.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. /utempter/utempter matchwhitelist diff --git a/etc/permission-hardening.d/25_default_whitelist_spice.conf b/etc/permission-hardener.d/25_default_whitelist_spice.conf similarity index 65% rename from etc/permission-hardening.d/25_default_whitelist_spice.conf rename to etc/permission-hardener.d/25_default_whitelist_spice.conf index 394b173..a8b7f7a 100644 --- a/etc/permission-hardening.d/25_default_whitelist_spice.conf +++ b/etc/permission-hardener.d/25_default_whitelist_spice.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. spice-client-glib-usb-acl-helper matchwhitelist diff --git a/etc/permission-hardening.d/25_default_whitelist_ssh.conf b/etc/permission-hardener.d/25_default_whitelist_ssh.conf similarity index 69% rename from etc/permission-hardening.d/25_default_whitelist_ssh.conf rename to etc/permission-hardener.d/25_default_whitelist_ssh.conf index 678b2f6..f7ef445 100644 --- a/etc/permission-hardening.d/25_default_whitelist_ssh.conf +++ b/etc/permission-hardener.d/25_default_whitelist_ssh.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2023 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. ## TODO: research diff --git a/etc/permission-hardening.d/25_default_whitelist_sudo.conf b/etc/permission-hardener.d/25_default_whitelist_sudo.conf similarity index 65% rename from etc/permission-hardening.d/25_default_whitelist_sudo.conf rename to etc/permission-hardener.d/25_default_whitelist_sudo.conf index 07051dd..a7b0fd2 100644 --- a/etc/permission-hardening.d/25_default_whitelist_sudo.conf +++ b/etc/permission-hardener.d/25_default_whitelist_sudo.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. /usr/bin/sudo exactwhitelist diff --git a/etc/permission-hardening.d/25_default_whitelist_unix_chkpwd.conf b/etc/permission-hardener.d/25_default_whitelist_unix_chkpwd.conf similarity index 74% rename from etc/permission-hardening.d/25_default_whitelist_unix_chkpwd.conf rename to etc/permission-hardener.d/25_default_whitelist_unix_chkpwd.conf index c086dab..dc1fb5a 100644 --- a/etc/permission-hardening.d/25_default_whitelist_unix_chkpwd.conf +++ b/etc/permission-hardener.d/25_default_whitelist_unix_chkpwd.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. ## required for performing password validation from unprivileged user diff --git a/etc/permission-hardening.d/25_default_whitelist_virtualbox.conf b/etc/permission-hardener.d/25_default_whitelist_virtualbox.conf similarity index 77% rename from etc/permission-hardening.d/25_default_whitelist_virtualbox.conf rename to etc/permission-hardener.d/25_default_whitelist_virtualbox.conf index dbd5737..17701d9 100644 --- a/etc/permission-hardening.d/25_default_whitelist_virtualbox.conf +++ b/etc/permission-hardener.d/25_default_whitelist_virtualbox.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. ## TODO: research diff --git a/etc/permission-hardening.d/30_default.conf b/etc/permission-hardener.d/30_default.conf similarity index 94% rename from etc/permission-hardening.d/30_default.conf rename to etc/permission-hardener.d/30_default.conf index b6e4aeb..2ba3dee 100644 --- a/etc/permission-hardening.d/30_default.conf +++ b/etc/permission-hardener.d/30_default.conf @@ -1,8 +1,8 @@ ## Copyright (C) 2012 - 2024 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. -## Please use "/etc/permission-hardening.d/20_user.conf" or -## "/usr/local/etc/permission-hardening.d/20_user.conf" for your custom +## Please use "/etc/permission-hardener.d/20_user.conf" or +## "/usr/local/etc/permission-hardener.d/20_user.conf" for your custom ## configuration. When security-misc is updated, this file may be overwritten. ## File permission hardening. @@ -60,8 +60,8 @@ /home/ 0755 root root /root/ 0700 root root /boot/ 0700 root root -/etc/permission-hardening.d 0600 root root -/usr/local/etc/permission-hardening.d 0600 root root +/etc/permission-hardener.d 0600 root root +/usr/local/etc/permission-hardener.d 0600 root root /lib/modules/ 0700 root root /usr/src 0700 root root /etc/cups/cupsd.conf 0400 root root diff --git a/lib/systemd/system-preset/50-security-misc.preset b/lib/systemd/system-preset/50-security-misc.preset index 201369d..a852419 100644 --- a/lib/systemd/system-preset/50-security-misc.preset +++ b/lib/systemd/system-preset/50-security-misc.preset @@ -5,7 +5,7 @@ disable hide-hardware-info.service ## Disable for now until development finished / tested. -disable permission-hardening.service +disable permission-hardener.service ## Disable for now until development finished / tested. ## https://github.com/Kicksecure/security-misc/pull/152 diff --git a/lib/systemd/system/permission-hardening.service b/lib/systemd/system/permission-hardener.service similarity index 93% rename from lib/systemd/system/permission-hardening.service rename to lib/systemd/system/permission-hardener.service index 9891b72..912e6c7 100644 --- a/lib/systemd/system/permission-hardening.service +++ b/lib/systemd/system/permission-hardener.service @@ -13,7 +13,7 @@ After=local-fs.target [Service] Type=oneshot RemainAfterExit=yes -ExecStart=permission-hardening +ExecStart=permission-hardener [Install] WantedBy=sysinit.target diff --git a/usr/bin/permission-hardening b/usr/bin/permission-hardener similarity index 99% rename from usr/bin/permission-hardening rename to usr/bin/permission-hardener index 7673dd7..d2a7ccc 100755 --- a/usr/bin/permission-hardening +++ b/usr/bin/permission-hardener @@ -6,13 +6,10 @@ ## https://forums.whonix.org/t/disable-suid-binaries/7706 ## https://forums.whonix.org/t/re-mount-home-and-other-with-noexec-and-nosuid-among-other-useful-mount-options-for-better-security/7707 -## To undo: -## sudo permission-hardening disable - set -o errexit -o nounset -o pipefail exit_code=0 -store_dir="/var/lib/permission-hardening" +store_dir="/var/lib/permission-hardener" dpkg_admindir_parameter_existing_mode="--admindir ${store_dir}/existing_mode" dpkg_admindir_parameter_new_mode="--admindir ${store_dir}/new_mode" @@ -507,6 +504,8 @@ parse_config_folder() { shopt -s nullglob for config_file in \ + /etc/permission-hardener.d/*.conf \ + /usr/local/etc/permission-hardener.d/*.conf \ /etc/permission-hardening.d/*.conf \ /usr/local/etc/permission-hardening.d/*.conf do @@ -620,7 +619,7 @@ spare() { To remove all: $0 disable all - This change might not be permanent (because of the permission-hardening.service systemd unit). For full instructions, see: + This change might not be permanent (because of the permission-hardener.service systemd unit). For full instructions, see: https://www.kicksecure.com/wiki/SUID_Disabler_and_Permission_Hardener To view list of changed by SUID Disabler and Permission Hardener: From bc02c72018d6458d4c1852dd441287b277421514 Mon Sep 17 00:00:00 2001 From: Ben Grande Date: Tue, 2 Jan 2024 17:08:45 +0100 Subject: [PATCH 3/3] Fix unbound variable - Run messages preceded by INFO; - Comment unknown unused variables; - Remove unnecessary variables; and - Deal with unbound variable due to subshell by writing to a file; --- usr/bin/permission-hardener | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/usr/bin/permission-hardener b/usr/bin/permission-hardener index d2a7ccc..2e3fcbc 100755 --- a/usr/bin/permission-hardener +++ b/usr/bin/permission-hardener @@ -14,17 +14,17 @@ dpkg_admindir_parameter_existing_mode="--admindir ${store_dir}/existing_mode" dpkg_admindir_parameter_new_mode="--admindir ${store_dir}/new_mode" echo_wrapper_ignore() { - echo "run: $*" + echo "INFO: run: $*" "$@" 2>/dev/null || true } echo_wrapper_silent_ignore() { - #echo "run: $@" + #echo "INFO: run: $@" "$@" 2>/dev/null || true } echo_wrapper_audit() { - echo "run: $*" + echo "INFO: run: $*" return_code=0 "$@" || { @@ -499,8 +499,8 @@ parse_config_folder() { group_file_contents_temp=$(getent group) echo "${group_file_contents_temp}" | tee "${store_dir}/private/group" >/dev/null - passwd_file_contents="$(cat "${store_dir}/private/passwd")" - group_file_contents="$(cat "${store_dir}/private/group")" + #passwd_file_contents="$(cat "${store_dir}/private/passwd")" + #group_file_contents="$(cat "${store_dir}/private/group")" shopt -s nullglob for config_file in \ @@ -555,32 +555,29 @@ spare() { true "owner: '${owner}' group: '${group}' mode: '${mode}' file_name: '${file_name}'" if test "${remove_file}" = "all"; then - proceed=true verbose="" remove_one=false else if test "${remove_file}" = "${file_name}"; then - proceed=true verbose="--verbose" remove_one=true + echo "${remove_one}" | tee "${store_dir}/remove_one" >/dev/null else - proceed=false - verbose="" + echo "false" | tee "${store_dir}/remove_one" >/dev/null + continue fi fi - if test "${proceed}" = "false"; then - continue - fi - if test "${remove_one}" = "true"; then set -o xtrace fi if test -e "${file_name}"; then + # shellcheck disable=SC2086 chown ${verbose} "${owner}:${group}" "${file_name}" || exit_code=202 ## chmod need to be run after chown since chown removes suid. ## https://unix.stackexchange.com/questions/53665/chown-removes-setuid-bit-bug-or-feature + # shellcheck disable=SC2086 chmod ${verbose} "${mode}" "${file_name}" || exit_code=203 else echo "INFO: file_name: '${file_name}' - does not exist. This is likely normal." @@ -600,10 +597,10 @@ spare() { done < "${store_dir}/existing_mode/statoverride" if test ! "${remove_file}" = "all"; then - if test ! "${remove_one}" = "true"; then - echo "INFO: no file removed. + if test "$(cat "${store_dir}/remove_one")" = "false"; then + echo "INFO: no file was removed. - File '${remove_file}' has not removed from SUID Disabler and Permission Hardener during this invocation of this program. + File '${remove_file}' has not been removed from SUID Disabler and Permission Hardener during this invocation of this program. Note: This is expected if already done earlier. @@ -657,7 +654,7 @@ case "${1:-}" in disable) shift case "${1:-}" in - "") usage;; + "") usage 1;; *) spare "${1}";; esac ;;