Select any two versions of this STIG to compare the individual requirements
Select any old version/release of this STIG to view the previous requirements
Verify the macOS system is configured to prevent Apple Watch from terminating a session lock with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowAutoUnlock').js EOS If the result is not "false", this is a finding.
Configure the macOS system to prevent Apple Watch from terminating a session lock by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to prompt users to enter a password to unlock the screen saver with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.screensaver')\ .objectForKey('askForPassword').js EOS If the result is not "true", this is a finding.
Configure the macOS system to prompt users to enter a password to unlock the screen saver by installing the "com.apple.screensaver" configuration profile.
Verify the macOS system is configured to initiate a session lock within five seconds of the screen saver starting with the following command: /usr/bin/osascript -l JavaScript << EOS function run() { let delay = ObjC.unwrap($.NSUserDefaults.alloc.initWithSuiteName('com.apple.screensaver')\ .objectForKey('askForPasswordDelay')) if ( delay <= 5 ) { return("true") } else { return("false") } } EOS If the result is not "true", this is a finding.
Configure the macOS system to initiate a session lock within five seconds of the screen saver starting by installing the "com.apple.screensaver" configuration profile.
Verify the macOS system is configured to lock the user session when a smart token is removed with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.security.smartcard')\ .objectForKey('tokenRemovalAction').js EOS If the result is not "1", this is a finding.
Configure the macOS system to lock the user session when a smart token is removed by installing the "com.apple.security.smartcard" configuration profile. NOTE: To ensure continued access to the operating system, consult the supplemental guidance provided with the STIG before applying the configuration profile.
Verify the macOS system is configured to disable hot corners with the following command: /usr/bin/profiles -P -o stdout | /usr/bin/grep -Ec '"wvous-bl-corner" = 0|"wvous-br-corner" = 0|"wvous-tl-corner" = 0|"wvous-tr-corner" = 0' If the result is not "4", this is a finding.
Configure the macOS system to disable hot corners by installing the "com.apple.ManagedClient.preferences" configuration profile.
Verify the macOS system is configured to prevent AdminHostInfo from being available at LoginWindow with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.loginwindow')\ .objectIsForcedForKey('AdminHostInfo') EOS If the result is not "false", this is a finding.
Configure the macOS system to prevent AdminHostInfo from being available at LoginWindow by installing the "com.apple.loginwindow" configuration profile.
Verify that a password policy is enforced by a directory service by asking the system administrator (SA) or information system security officer (ISSO). If no policy is enforced by a directory service, a password policy can be set with the "pwpolicy" utility. The variable names may vary depending on how the policy was set. If no temporary or emergency accounts are defined on the system, this is not applicable. To check if the password policy is configured to disable a temporary or emergency account after 72 hours, run the following command to output the password policy to the screen, substituting the correct user name in place of username: /usr/bin/pwpolicy -u username getaccountpolicies | tail -n +2 If there is no output, and password policy is not controlled by a directory service, this is a finding. Otherwise, look for the line "<key>policyCategoryAuthentication</key>". In the array that follows, there should be a <dict> section that contains a check <string> that allows users to log in if "policyAttributeCurrentTime" is less than the result of adding "policyAttributeCreationTime" to 72 hours (259299 seconds). The check might use a variable defined in its "policyParameters" section. If the check does not exist or if the check adds too great an amount of time to "policyAttributeCreationTime", this is a finding.
This setting may be enforced using local policy or by a directory service. To set local policy to disable a temporary or emergency user, create a plain text file containing the following: <dict> <key>policyCategoryAuthentication</key> <array> <dict> <key>policyContent</key> <string>policyAttributeCurrentTime < policyAttributeCreationTime+259299</string> <key>policyIdentifier</key> <string>Disable Tmp Accounts </string> </dict> </array> </dict> After saving the file and exiting to the command prompt, run the following command to load the new policy file, substituting the correct user name in place of "username" and the path to the file in place of "/path/to/file". /usr/bin/pwpolicy -u username setaccountpolicies /path/to/file
Verify the macOS system is configured to enforce time synchronization with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.timed')\ .objectForKey('TMAutomaticTimeOnlyEnabled').js EOS If the result is not "true", this is a finding.
Configure the macOS system to enforce time synchronization by installing the "com.apple.timed" configuration profile.
Verify the macOS system is configured to limit consecutive failed login attempts to three with the following command: /usr/bin/pwpolicy -getaccountpolicies 2> /dev/null | /usr/bin/tail +2 | /usr/bin/xmllint --xpath '//dict/key[text()="policyAttributeMaximumFailedAuthentications"]/following-sibling::integer[1]/text()' - | /usr/bin/awk '{ if ($1 <= 3) {print "yes"} else {print "no"}}' If the result is not "yes", this is a finding.
Configure the macOS system to limit consecutive failed login attempts to three by installing the "com.apple.mobiledevice.passwordpolicy" configuration profile or by a directory service.
Verify the macOS system is configured to display the Standard Mandatory DOD Notice and Consent Banner before granting remote access to the operating system. Verify the operating system has the correct text listed in the "/etc/banner" file with the following command: /usr/bin/more /etc/banner The command must return the following text: "You are accessing a U.S. Government (USG) Information System (IS) that is provided for USG-authorized use only. By using this IS (which includes any device attached to this IS), you consent to the following conditions: -The USG routinely intercepts and monitors communications on this IS for purposes including, but not limited to, penetration testing, COMSEC monitoring, network operations and defense, personnel misconduct (PM), law enforcement (LE), and counterintelligence (CI) investigations. -At any time, the USG may inspect and seize data stored on this IS. -Communications using, or data stored on, this IS are not private, are subject to routine monitoring, interception, and search, and may be disclosed or used for any USG-authorized purpose. -This IS includes security measures (e.g., authentication and access controls) to protect USG interests--not for your personal benefit or privacy. -Notwithstanding the above, using this IS does not constitute consent to PM, LE or CI investigative searching or monitoring of the content of privileged communications, or work product, related to personal representation or services by attorneys, psychotherapists, or clergy, and their assistants. Such communications and work product are private and confidential. See User Agreement for details." If the operating system does not display a login banner before granting remote access or the banner does not match the Standard Mandatory DOD Notice and Consent Banner, this is a finding. If the text in the "/etc/banner" file does not match the Standard Mandatory DOD Notice and Consent Banner, this is a finding.
Configure the macOS system to display the Standard Mandatory DOD Notice and Consent Banner before granting remote access to the operating system by creating a text file containing the required DOD text. Name the file "banner" and place it in "/etc/".
Verify the macOS system is configured to display a policy banner with the following command: /bin/ls -ld /Library/Security/PolicyBanner.rtf* | /usr/bin/wc -l | /usr/bin/tr -d ' ' If the permissions for "PolicyBanner.rtfd" are not "644", this is a finding. The banner text of the document must read: "You are accessing a U.S. Government (USG) Information System (IS) that is provided for USG-authorized use only. By using this IS (which includes any device attached to this IS), you consent to the following conditions: -The USG routinely intercepts and monitors communications on this IS for purposes including, but not limited to, penetration testing, COMSEC monitoring, network operations and defense, personnel misconduct (PM), law enforcement (LE), and counterintelligence (CI) investigations. -At any time, the USG may inspect and seize data stored on this IS. -Communications using, or data stored on, this IS are not private, are subject to routine monitoring, interception, and search, and may be disclosed or used for any USG authorized purpose. -This IS includes security measures (e.g., authentication and access controls) to protect USG interests--not for your personal benefit or privacy. -Notwithstanding the above, using this IS does not constitute consent to PM, LE or CI investigative searching or monitoring of the content of privileged communications, or work product, related to personal representation or services by attorneys, psychotherapists, or clergy, and their assistants. Such communications and work product are private and confidential. See User Agreement for details." If the text is not worded exactly this way, this is a finding.
Configure the macOS system to display a policy banner by creating an RTF file containing the required text. Name the file "PolicyBanner.rtfd" and place it in "/Library/Security/". Update the permissions of the "/Library/Security/PolicyBanner.rtfd" file with the following command: /usr/bin/sudo /bin/chmod 644 /Library/Security/PolicyBanner.rtfd
Verify the macOS system is configured without ACLs applied to log files with the following command: /bin/ls -le $(/usr/bin/grep '^dir' /etc/security/audit_control | /usr/bin/awk -F: '{print $2}') | /usr/bin/awk '{print $1}' | /usr/bin/grep -c ":" If the result is not "0", this is a finding.
Configure the macOS system without ACLs applied to log files with the following command: /bin/chmod -RN /var/audit
Verify the macOS system is configured without ACLs applied to log folders with the following command: /bin/ls -lde /var/audit | /usr/bin/awk '{print $1}' | /usr/bin/grep -c ":" If the result is not "0", this is a finding.
Configure the macOS system without ACLs applied to log folders with the following command: /bin/chmod -N /var/audit
Verify the macOS system is configured to disable FileVault automatic login with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.loginwindow')\ .objectForKey('DisableFDEAutoLogin').js EOS If the result is not "true", this is a finding.
Configure the macOS system to disable FileVault automatic login by installing the "com.apple.loginwindow" configuration profile. NOTE: To ensure continued access to the operating system, consult the supplemental guidance provided with the STIG before applying the configuration profile.
Verify the macOS system is configured to set the SSHD ClientAliveInterval to 900 with the following command: /usr/sbin/sshd -G | /usr/bin/awk '/clientaliveinterval/{print $2}' If the result is not "900", this is a finding.
Configure the macOS system to set the SSHD ClientAliveInterval to 900 with the following command: include_dir=$(/usr/bin/awk '/^Include/ {print $2}' /etc/ssh/sshd_config | /usr/bin/tr -d '*') if [[ -z $include_dir ]]; then /usr/bin/sed -i.bk "1s/.*/Include \/etc\/ssh\/sshd_config.d\/\*/" /etc/ssh/sshd_config fi /usr/bin/grep -qxF 'clientaliveinterval 900' "${include_dir}01-mscp-sshd.conf" 2>/dev/null || echo "clientaliveinterval 900" >> "${include_dir}01-mscp-sshd.conf" for file in $(ls ${include_dir}); do if [[ "$file" == "100-macos.conf" ]]; then continue fi if [[ "$file" == "01-mscp-sshd.conf" ]]; then break fi /bin/mv ${include_dir}${file} ${include_dir}20-${file} done
Verify the macOS system is configured to set the SSHD ClientAliveCountMax to 1 with the following command: /usr/sbin/sshd -G | /usr/bin/awk '/clientalivecountmax/{print $2}' If the result is not "1", this is a finding.
Configure the macOS system to set the SSHD ClientAliveCountMax to 1 with the following command: include_dir=$(/usr/bin/awk '/^Include/ {print $2}' /etc/ssh/sshd_config | /usr/bin/tr -d '*') if [[ -z $include_dir ]]; then /usr/bin/sed -i.bk "1s/.*/Include \/etc\/ssh\/sshd_config.d\/\*/" /etc/ssh/sshd_config fi /usr/bin/grep -qxF 'clientalivecountmax 1' "${include_dir}01-mscp-sshd.conf" 2>/dev/null || echo "clientalivecountmax 1" >> "${include_dir}01-mscp-sshd.conf" for file in $(ls ${include_dir}); do if [[ "$file" == "100-macos.conf" ]]; then continue fi if [[ "$file" == "01-mscp-sshd.conf" ]]; then break fi /bin/mv ${include_dir}${file} ${include_dir}20-${file} done
Verify the macOS system is configured to set Login Grace Time to 30 with the following command: /usr/sbin/sshd -G | /usr/bin/awk '/logingracetime/{print $2}' If the result is not "30", this is a finding.
Configure the macOS system to set Login Grace Time to 30 with the following command: include_dir=$(/usr/bin/awk '/^Include/ {print $2}' /etc/ssh/sshd_config | /usr/bin/tr -d '*') if [[ -z $include_dir ]]; then /usr/bin/sed -i.bk "1s/.*/Include \/etc\/ssh\/sshd_config.d\/\*/" /etc/ssh/sshd_config fi /usr/bin/grep -qxF 'logingracetime 30' "${include_dir}01-mscp-sshd.conf" 2>/dev/null || echo "logingracetime 30" >> "${include_dir}01-mscp-sshd.conf" for file in $(ls ${include_dir}); do if [[ "$file" == "100-macos.conf" ]]; then continue fi if [[ "$file" == "01-mscp-sshd.conf" ]]; then break fi /bin/mv ${include_dir}${file} ${include_dir}20-${file} done
Verify the macOS system is configured to limit SSHD to FIPS-compliant connections with the following command: fips_sshd_config=("Ciphers aes128-gcm@openssh.com" "HostbasedAcceptedAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp256-cert-v01@openssh.com" "HostKeyAlgorithms ecdsa-sha2-nistp256-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp256,sk-ecdsa-sha2-nistp256@openssh.com" "KexAlgorithms ecdh-sha2-nistp256" "MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-256" "PubkeyAcceptedAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp256-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" "CASignatureAlgorithms ecdsa-sha2-nistp256,sk-ecdsa-sha2-nistp256@openssh.com") total=0 for config in $fips_sshd_config; do total=$(expr $(/usr/sbin/sshd -G | /usr/bin/grep -i -c "$config") + $total) done echo $total If the result is not "7", this is a finding.
Configure the macOS system to limit SSHD to FIPS-compliant connections with the following command: /bin/ln -fs /etc/ssh/crypto/fips.conf /etc/ssh/crypto.conf
Verify the macOS system is configured to limit SSH to FIPS-compliant connections with the following command: fips_ssh_config=("Ciphers aes128-gcm@openssh.com" "HostbasedAcceptedAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp256-cert-v01@openssh.com" "HostKeyAlgorithms ecdsa-sha2-nistp256-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp256,sk-ecdsa-sha2-nistp256@openssh.com" "KexAlgorithms ecdh-sha2-nistp256" "MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-256" "PubkeyAcceptedAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp256-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" "CASignatureAlgorithms ecdsa-sha2-nistp256,sk-ecdsa-sha2-nistp256@openssh.com") total=0 ret="pass" for config in $fips_ssh_config; do if [[ "$ret" == "fail" ]]; then break fi for u in $(/usr/bin/dscl . list /users shell | /usr/bin/egrep -v '(^_)|(root)|(/usr/bin/false)' | /usr/bin/awk '{print $1}'); do sshCheck=$(/usr/bin/sudo -u $u /usr/bin/ssh -G . | /usr/bin/grep -ci "$config") if [[ "$sshCheck" == "0" ]]; then ret="fail" break fi done done echo $ret If the result is not "pass", this is a finding.
Configure the macOS system to limit SSH to FIPS-compliant connections with the following command: if [ -f /etc/ssh/crypto.conf ] && /usr/bin/grep -q "Include /etc/ssh/crypto.conf" /etc/ssh/ssh_config.d/100-macos.conf 2>/dev/null; then /bin/ln -fs /etc/ssh/crypto/fips.conf /etc/ssh/crypto.conf fi include_dir=$(/usr/bin/awk '/^Include/ {print $2}' /etc/ssh/ssh_config | /usr/bin/tr -d '*') fips_ssh_config=("Ciphers aes128-gcm@openssh.com" "HostbasedAcceptedAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp256-cert-v01@openssh.com" "HostKeyAlgorithms ecdsa-sha2-nistp256-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp256,sk-ecdsa-sha2-nistp256@openssh.com" "KexAlgorithms ecdh-sha2-nistp256" "MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-256" "PubkeyAcceptedAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp256-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" "CASignatureAlgorithms ecdsa-sha2-nistp256,sk-ecdsa-sha2-nistp256@openssh.com") for ssh_config in $fips_ssh_config; do ssh_setting=$(echo $ssh_config | /usr/bin/cut -d " " -f1) /usr/bin/grep -qEi "^$ssh_setting" "${include_dir}01-mscp-ssh.conf" && /usr/bin/sed -i "" "s/^$ssh_setting.*/${ssh_config}/" "${include_dir}01-mscp-ssh.conf" || echo "$ssh_config" >> "${include_dir}01-mscp-ssh.conf" for u in $(/usr/bin/dscl . list /users shell | /usr/bin/egrep -v '(^_)|(root)|(/usr/bin/false)' | /usr/bin/awk '{print $1}'); do config=$(/usr/bin/sudo -u $u /usr/bin/ssh -Gv . 2>&1) configfiles=$(echo "$config" | /usr/bin/awk '/Reading configuration data/ {print $NF}'| /usr/bin/tr -d '\r') configarray=( ${(f)configfiles} ) if ! echo $config | /usr/bin/grep -q -i "$ssh_config" ; then for c in $configarray; do if [[ "$c" == "/etc/ssh/crypto.conf" ]]; then continue fi /usr/bin/sudo -u $u /usr/bin/grep -qEi "^$ssh_setting" "$c" && /usr/bin/sed -i "" "s/^$ssh_setting.*/${ssh_config}/I" "$c" if [[ "$c" =~ ".ssh/config" ]]; then if /usr/bin/grep -qEi "$ssh_setting" "$c" 2> /dev/null; then old_file=$(cat ~$u/.ssh/config) echo "$ssh_config" > ~$u/.ssh/config echo "$old_file" >> ~$u/.ssh/config fi fi done fi done done
Verify the macOS system is configured to set account lockout time to 15 minutes with the following command: /usr/bin/pwpolicy -getaccountpolicies 2> /dev/null | /usr/bin/tail +2 | /usr/bin/xmllint --xpath '//dict/key[text()="autoEnableInSeconds"]/following-sibling::integer[1]/text()' - | /usr/bin/awk '{ if ($1/60 >= 15 ) {print "yes"} else {print "no"}}' If the result is not "yes", this is a finding.
Configure the macOS system to set account lockout time to 15 minutes by installing the "com.apple.mobiledevice.passwordpolicy" configuration profile or by a directory service.
Verify the macOS system is configured to initiate the screen saver timeout after 15 minutes of inactivity with the following command: /usr/bin/osascript -l JavaScript << EOS function run() { let timeout = ObjC.unwrap($.NSUserDefaults.alloc.initWithSuiteName('com.apple.screensaver')\ .objectForKey('idleTime')) if ( timeout <= 900 ) { return("true") } else { return("false") } } EOS If the result is not "true", this is a finding.
Configure the macOS system to initiate the screen saver after 15 minutes of inactivity by installing the "com.apple.screensaver" configuration profile.
Verify the macOS system is configured to disable login to other users' active and locked sessions with the following command: /usr/bin/security authorizationdb read system.login.screensaver 2>&1 | /usr/bin/grep -c '<string>authenticate-session-owner</string>' If the result is not "1", this is a finding.
Configure the macOS system to disable login to other users' active and locked sessions with the following command: /usr/bin/security authorizationdb write system.login.screensaver "authenticate-session-owner"
Verify the macOS system is configured to disable root login with the following command: /usr/bin/dscl . -read /Users/root UserShell 2>&1 | /usr/bin/grep -c "/usr/bin/false" If the result is not "1", this is a finding.
Configure the macOS system to disable root login with the following command: /usr/bin/dscl . -create /Users/root UserShell /usr/bin/false
Verify the macOS system is configured to set the SSH ServerAliveInterval to 900 with the following command: ret="pass" for u in $(/usr/bin/dscl . -list /Users UniqueID | /usr/bin/awk '$2 > 500 {print $1}'); do sshCheck=$(/usr/bin/sudo -u $u /usr/bin/ssh -G . | /usr/bin/grep -c "^serveraliveinterval 900") if [[ "$sshCheck" == "0" ]]; then ret="fail" break fi done /bin/echo $ret If the result is not "pass", this is a finding.
Configure the macOS system to set the SSH ServerAliveInterval to 900 with the following command: include_dir=$(/usr/bin/awk '/^Include/ {print $2}' /etc/ssh/ssh_config | /usr/bin/tr -d '*') ssh_config_string=("ServerAliveInterval 900") for ssh_config in $ssh_config_string; do ssh_setting=$(echo $ssh_config | /usr/bin/cut -d " " -f1) /usr/bin/grep -qEi "^$ssh_setting" "${include_dir}01-mscp-ssh.conf" && /usr/bin/sed -i "" "s/^$ssh_setting.*/${ssh_config}/" "${include_dir}01-mscp-ssh.conf" || echo "$ssh_config" >> "${include_dir}01-mscp-ssh.conf" for u in $(/usr/bin/dscl . list /users shell | /usr/bin/egrep -v '(^_)|(root)|(/usr/bin/false)' | /usr/bin/awk '{print $1}'); do config=$(/usr/bin/sudo -u $u /usr/bin/ssh -Gv . 2>&1) configfiles=$(echo "$config" | /usr/bin/awk '/Reading configuration data/ {print $NF}'| /usr/bin/tr -d '\r') configarray=( ${(f)configfiles} ) if ! echo $config | /usr/bin/grep -q -i "$ssh_config" ; then for c in $configarray; do if [[ "$c" == "/etc/ssh/crypto.conf" ]]; then continue fi /usr/bin/sudo -u $u /usr/bin/grep -qEi "^$ssh_setting" "$c" && /usr/bin/sed -i "" "s/^$ssh_setting.*/${ssh_config}/I" "$c" if [[ "$c" =~ ".ssh/config" ]]; then if /usr/bin/grep -qEi "$ssh_setting" "$c" 2> /dev/null; then old_file=$(cat ~$u/.ssh/config) echo "$ssh_config" > ~$u/.ssh/config echo "$old_file" >> ~$u/.ssh/config fi fi done fi done done
Verify the macOS system is configured to set the SSHD Channel Timeout to 900 with the following command: /usr/sbin/sshd -G | /usr/bin/awk -F "=" '/channeltimeout session:*/{print $2}' If the result is not "900", this is a finding.
Configure the macOS system to set the SSHD ChannelTimeout to 900 with the following command: include_dir=$(/usr/bin/awk '/^Include/ {print $2}' /etc/ssh/sshd_config | /usr/bin/tr -d '*') if [[ -z $include_dir ]]; then /usr/bin/sed -i.bk "1s/.*/Include \/etc\/ssh\/sshd_config.d\/\*/" /etc/ssh/sshd_config fi /usr/bin/grep -qxF 'channeltimeout session:*=900' "${include_dir}01-mscp-sshd.conf" 2>/dev/null || echo "channeltimeout session:*=900" >> "${include_dir}01-mscp-sshd.conf" for file in $(ls ${include_dir}); do if [[ "$file" == "100-macos.conf" ]]; then continue fi if [[ "$file" == "01-mscp-sshd.conf" ]]; then break fi /bin/mv ${include_dir}${file} ${include_dir}20-${file} done
Verify the macOS system is configured to set the SSHD unused connection timeout to 900 with the following command: /usr/sbin/sshd -G | /usr/bin/awk '/unusedconnectiontimeout/{print $2}' If the result is not "900", this is a finding.
Configure the macOS system to set the SSHD unused connection timeout to 900 with the following command: include_dir=$(/usr/bin/awk '/^Include/ {print $2}' /etc/ssh/sshd_config | /usr/bin/tr -d '*') if [[ -z $include_dir ]]; then /usr/bin/sed -i.bk "1s/.*/Include \/etc\/ssh\/sshd_config.d\/\*/" /etc/ssh/sshd_config fi /usr/bin/grep -qxF 'unusedconnectiontimeout 900' "${include_dir}01-mscp-sshd.conf" 2>/dev/null || echo "unusedconnectiontimeout 900" >> "${include_dir}01-mscp-sshd.conf" for file in $(ls ${include_dir}); do if [[ "$file" == "100-macos.conf" ]]; then continue fi if [[ "$file" == "01-mscp-sshd.conf" ]]; then break fi /bin/mv ${include_dir}${file} ${include_dir}20-${file} done
Verify the macOS system is configured to set SSH Active Server Alive Maximum to 0 with the following command: ret="pass" for u in $(/usr/bin/dscl . -list /Users UniqueID | /usr/bin/awk '$2 > 500 {print $1}'); do sshCheck=$(/usr/bin/sudo -u $u /usr/bin/ssh -G . | /usr/bin/grep -c "^serveralivecountmax 0") if [[ "$sshCheck" == "0" ]]; then ret="fail" break fi done /bin/echo $ret If the result is not "pass", this is a finding.
Configure the macOS system to set SSH Active Server Alive Maximum to 0 with the following command: include_dir=$(/usr/bin/awk '/^Include/ {print $2}' /etc/ssh/ssh_config | /usr/bin/tr -d '*') ssh_config=("ServerAliveCountMax 0") ssh_setting=$(echo $ssh_config | /usr/bin/cut -d " " -f1) /usr/bin/grep -qEi "^$ssh_setting" "${include_dir}01-mscp-ssh.conf" && /usr/bin/sed -i "" "s/^$ssh_setting.*/${ssh_config}/" "${include_dir}01-mscp-ssh.conf" || echo "$ssh_config" >> "${include_dir}01-mscp-ssh.conf" for u in $(/usr/bin/dscl . list /users shell | /usr/bin/egrep -v '(^_)|(root)|(/usr/bin/false)' | /usr/bin/awk '{print $1}'); do config=$(/usr/bin/sudo -u $u /usr/bin/ssh -Gv . 2>&1) configfiles=$(echo "$config" | /usr/bin/awk '/Reading configuration data/ {print $NF}'| /usr/bin/tr -d '\r') configarray=( ${(f)configfiles} ) if ! echo $config | /usr/bin/grep -q -i "$ssh_config" ; then for c in $configarray; do if [[ "$c" == "/etc/ssh/crypto.conf" ]]; then continue fi /usr/bin/sudo -u $u /usr/bin/grep -qEi "^$ssh_setting" "$c" && /usr/bin/sed -i "" "s/^$ssh_setting.*/${ssh_config}/I" "$c" if [[ "$c" =~ ".ssh/config" ]]; then if /usr/bin/grep -qEi "$ssh_setting" "$c" 2> /dev/null; then old_file=$(cat ~$u/.ssh/config) echo "$ssh_config" > ~$u/.ssh/config echo "$old_file" >> ~$u/.ssh/config fi fi done fi done
Verify the macOS system is configured to enforce auto logout after 86400 seconds of inactivity with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('.GlobalPreferences')\ .objectForKey('com.apple.autologout.AutoLogOutDelay').js EOS If the result is not "86400", this is a finding.
Configure the macOS system to enforce auto logout after 86400 seconds of inactivity by installing the "com.apple.GlobalPreferences" configuration profile.
Verify the macOS system is configured to use an authorized time server with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.MCX')\ .objectForKey('timeServer').js EOS If the result is not an authoritative time server that is synchronized with redundant USNO time servers as designated for the appropriate DOD network, this is a finding.
Configure the macOS system to use an authorized time server by installing the "com.apple.MCX" configuration profile.
Verify the macOS system is configured to enable the time synchronization daemon with the following command: /bin/launchctl list | /usr/bin/grep -c com.apple.timed If the result is not "1", this is a finding.
Configure the macOS system to enable the time synchronization daemon with the following command: /bin/launchctl load -w /System/Library/LaunchDaemons/com.apple.timed.plist NOTE: The service "timed" cannot be unloaded or loaded while System Integrity Protection (SIP) is enabled.
Verify the macOS system is configured to log privilege escalation with the following command: /usr/bin/sudo /usr/bin/sudo -V | /usr/bin/grep -c "Log when a command is allowed by sudoers" If the result is not "1", this is a finding.
Configure the macOS system to log privilege escalation with the following command: /usr/bin/find /etc/sudoers* -type f -exec sed -i '' '/Defaults \!log_allowed/d' '{}' \; /bin/echo "Defaults log_allowed" >> /etc/sudoers.d/mscp
Verify the macOS system is configured to audit privileged access with the following command: /usr/bin/awk -F':' '/^flags/ { print $NF }' /etc/security/audit_control | /usr/bin/tr ',' '\n' | /usr/bin/grep -Ec 'ad' If "ad" is not listed in the output, this is a finding.
Configure the macOS system to audit privileged access with the following command: /usr/bin/grep -qE "^flags.*[^-]ad" /etc/security/audit_control || /usr/bin/sed -i.bak '/^flags/ s/$/,ad/' /etc/security/audit_control; /usr/sbin/audit -s A text editor may also be used to implement the required updates to the "/etc/security/audit_control" file.
Verify the macOS system is configured to audit all login and logout events with the following command: /usr/bin/awk -F':' '/^flags/ { print $NF }' /etc/security/audit_control | /usr/bin/tr ',' '\n' | /usr/bin/grep -Ec '^lo' If the result is not "1", this is a finding.
Configure the macOS system to audit all login and logout events with the following command: /usr/bin/grep -qE "^flags.*[^-]lo" /etc/security/audit_control || /usr/bin/sed -i.bak '/^flags/ s/$/,lo/' /etc/security/audit_control; /usr/sbin/audit -s A text editor may also be used to implement the required updates to the "/etc/security/audit_control" file.
Verify the macOS system is configured to enable the auditd service with the following command: LAUNCHD_RUNNING=$(/bin/launchctl list | /usr/bin/grep -c com.apple.auditd) AUDITD_RUNNING=$(/usr/sbin/audit -c | /usr/bin/grep -c "AUC_AUDITING") if [[ $LAUNCHD_RUNNING == 1 ]] && [[ -e /etc/security/audit_control ]] && [[ $AUDITD_RUNNING == 1 ]]; then echo "pass" else echo "fail" fi If the result is not "pass", this is a finding.
Configure the macOS system to enable the auditd service with the following command: if [[ ! -e /etc/security/audit_control ]] && [[ -e /etc/security/audit_control.example ]];then /bin/cp /etc/security/audit_control.example /etc/security/audit_control fi /bin/launchctl enable system/com.apple.auditd /bin/launchctl bootstrap system /System/Library/LaunchDaemons/com.apple.auditd.plist /usr/sbin/audit -i
Verify the macOS system is configured to shut down upon audit failure with the following command: /usr/bin/awk -F':' '/^policy/ {print $NF}' /etc/security/audit_control | /usr/bin/tr ',' '\n' | /usr/bin/grep -Ec 'ahlt' If the result is not "1", this is a finding.
Configure the macOS system to shut down upon audit failure with the following command: /usr/bin/sed -i.bak 's/^policy.*/policy: ahlt,argv/' /etc/security/audit_control; /usr/sbin/audit -s
Verify the macOS system is configured with audit log files owned by root with the following command: /bin/ls -n $(/usr/bin/grep '^dir' /etc/security/audit_control | /usr/bin/awk -F: '{print $2}') | /usr/bin/awk '{s+=$3} END {print s}' If the result is not "0", this is a finding.
Configure the macOS system with audit log files owned by root with the following command: /usr/sbin/chown -R root /var/audit/*
Verify the macOS system is configured with audit log folders owned by root with the following command: /bin/ls -dn $(/usr/bin/grep '^dir' /etc/security/audit_control | /usr/bin/awk -F: '{print $2}') | /usr/bin/awk '{print $3}' If the result is not "0", this is a finding.
Configure the macOS system with audit log folders owned by root with the following command: /usr/sbin/chown root /var/audit
Verify the macOS system is configured with audit log files group-owned by wheel with the following command: /bin/ls -n $(/usr/bin/grep '^dir' /etc/security/audit_control | /usr/bin/awk -F: '{print $2}') | /usr/bin/awk '{s+=$4} END {print s}' If the result is not "0", this is a finding.
Configure the macOS system with audit log files group-owned by wheel with the following command: /usr/bin/chgrp -R wheel /var/audit/*
Verify the macOS system is configured with audit log folders group-owned by wheel with the following command: /bin/ls -dn $(/usr/bin/grep '^dir' /etc/security/audit_control | /usr/bin/awk -F: '{print $2}') | /usr/bin/awk '{print $4}' If the result is not "0", this is a finding.
Configure the macOS system with audit log folders group-owned by wheel with the following command: /usr/bin/chgrp wheel /var/audit
Verify the macOS system is configured with audit log files set to mode 440 or less with the following command: /bin/ls -l $(/usr/bin/grep '^dir' /etc/security/audit_control | /usr/bin/awk -F: '{print $2}') | /usr/bin/awk '!/-r--r-----|current|total/{print $1}' | /usr/bin/wc -l | /usr/bin/tr -d ' ' If the result is not "0", this is a finding.
Configure the macOS system with audit log files set to mode 440 with the following command: /bin/chmod 440 /var/audit/*
Verify the macOS system is configured with audit log folders set to mode 700 or less permissive with the following command: /usr/bin/stat -f %A $(/usr/bin/grep '^dir' /etc/security/audit_control | /usr/bin/awk -F: '{print $2}') If the result is not a mode of 700 or less permissive, this is a finding.
Configure the macOS system with audit log folders set to mode 700 with the following command: /bin/chmod 700 /var/audit
Verify the macOS system is configured to audit all deletions of object attributes with the following command: /usr/bin/awk -F':' '/^flags/ { print $NF }' /etc/security/audit_control | /usr/bin/tr ',' '\n' | /usr/bin/grep -Ec '\-fd' If the result is not "1", this is a finding.
Configure the macOS system to audit all deletions of object attributes with the following command: /usr/bin/grep -qE "^flags.*-fd" /etc/security/audit_control || /usr/bin/sed -i.bak '/^flags/ s/$/,-fd/' /etc/security/audit_control;/usr/sbin/audit -s
Verify the macOS system is configured to audit all changes of object attributes with the following command: /usr/bin/awk -F':' '/^flags/ { print $NF }' /etc/security/audit_control | /usr/bin/tr ',' '\n' | /usr/bin/grep -Ec '^fm' If the result is not "1", this is a finding.
Configure the macOS system to audit all changes of object attributes with the following command: /usr/bin/grep -qE "^flags.*fm" /etc/security/audit_control || /usr/bin/sed -i.bak '/^flags/ s/$/,fm/' /etc/security/audit_control;/usr/sbin/audit -s
Verify the macOS system is configured to audit all failed read actions on the system with the following command: /usr/bin/awk -F':' '/^flags/ { print $NF }' /etc/security/audit_control | /usr/bin/tr ',' '\n' | /usr/bin/grep -Ec '\-fr' If the result is not "1", this is a finding.
Configure the macOS system to audit all failed read actions on the system with the following command: /usr/bin/grep -qE "^flags.*-fr" /etc/security/audit_control || /usr/bin/sed -i.bak '/^flags/ s/$/,-fr/' /etc/security/audit_control;/usr/sbin/audit -s
Verify the macOS system is configured to audit all failed write actions on the system with the following command: /usr/bin/awk -F':' '/^flags/ { print $NF }' /etc/security/audit_control | /usr/bin/tr ',' '\n' | /usr/bin/grep -Ec '\-fw' If the result is not "1", this is a finding.
Configure the macOS system to audit all failed write actions on the system with the following command: /usr/bin/grep -qE "^flags.*-fw" /etc/security/audit_control || /usr/bin/sed -i.bak '/^flags/ s/$/,-fw/' /etc/security/audit_control;/usr/sbin/audit -s
Verify the macOS system is configured to set audit retention to seven days with the following command: /usr/bin/awk -F: '/expire-after/{print $2}' /etc/security/audit_control If the result is not "7d", this is a finding.
Configure the macOS system to set audit retention to seven days with the following command: /usr/bin/sed -i.bak 's/^expire-after.*/expire-after:7d/' /etc/security/audit_control; /usr/sbin/audit -s
Verify the macOS system is configured to require a minimum of 25 percent free disk space for audit record storage with the following command: /usr/bin/awk -F: '/^minfree/{print $2}' /etc/security/audit_control If the result is not "25", this is a finding.
Configure the macOS system to require a minimum of 25 percent free disk space for audit record storage with the following command: /usr/bin/sed -i.bak 's/.*minfree.*/minfree:25/' /etc/security/audit_control; /usr/sbin/audit -s
Verify the macOS system is configured to produce audit failure notification with the following command: /usr/bin/grep -c "logger -s -p" /etc/security/audit_warn If the result is not "1", this is a finding.
Configure the macOS system to produce audit failure notification with the following command: /usr/bin/sed -i.bak 's/logger -p/logger -s -p/' /etc/security/audit_warn; /usr/sbin/audit -s
Verify the macOS system is configured to audit login events with the following command: /usr/bin/awk -F':' '/^flags/ { print $NF }' /etc/security/audit_control | /usr/bin/tr ',' '\n' | /usr/bin/grep -Ec 'aa' If the result is not "1", this is a finding.
Configure the macOS system to audit login events with the following command: /usr/bin/grep -qE "^flags.*[^-]aa" /etc/security/audit_control || /usr/bin/sed -i.bak '/^flags/ s/$/,aa/' /etc/security/audit_control; /usr/sbin/audit -s
Verify the macOS system is configured to check the revocation status of user certificates with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.security.smartcard')\ .objectForKey('checkCertificateTrust').js EOS If the result is not "2", this is a finding.
Configure the macOS system to check the revocation status of user certificates by installing the "com.apple.security.smartcard" configuration profile. NOTE: To ensure continued access to the operating system, consult the supplemental guidance provided with the STIG before applying the configuration profile.
Verify the macOS system is configured to disable root login for SSH with the following command: /usr/sbin/sshd -G | /usr/bin/awk '/permitrootlogin/{print $2}' If the result is not "no", this is a finding.
Configure the macOS system to disable root login for SSH with the following command: include_dir=$(/usr/bin/awk '/^Include/ {print $2}' /etc/ssh/sshd_config | /usr/bin/tr -d '*') if [[ -z $include_dir ]]; then /usr/bin/sed -i.bk "1s/.*/Include \/etc\/ssh\/sshd_config.d\/\*/" /etc/ssh/sshd_config fi /usr/bin/grep -qxF 'permitrootlogin no' "${include_dir}01-mscp-sshd.conf" 2>/dev/null || echo "permitrootlogin no" >> "${include_dir}01-mscp-sshd.conf" for file in $(ls ${include_dir}); do if [[ "$file" == "100-macos.conf" ]]; then continue fi if [[ "$file" == "01-mscp-sshd.conf" ]]; then break fi /bin/mv ${include_dir}${file} ${include_dir}20-${file} done
Verify the macOS system is configured with the audit_control group to wheel with the following command: /bin/ls -dn /etc/security/audit_control | /usr/bin/awk '{print $4}' If the result is not "0", this is a finding.
Configure the macOS system with the audit_control group to wheel with the following command: /usr/bin/chgrp wheel /etc/security/audit_control
Verify the macOS system is configured with the audit_control owner to root with the following command: /bin/ls -dn /etc/security/audit_control | /usr/bin/awk '{print $3}' If the result is not "0", this is a finding.
Configure the macOS system with the audit_control owner to root with the following command: /usr/sbin/chown root /etc/security/audit_control
Verify the macOS system is configured with the audit_control to mode 440 or less with the following command: /bin/ls -l /etc/security/audit_control | /usr/bin/awk '!/-r--[r-]-----|current|total/{print $1}' | /usr/bin/wc -l | /usr/bin/xargs If the result is not "0", this is a finding.
Configure the macOS system with the audit_control to mode 440 with the following command: /bin/chmod 440 /etc/security/audit_control
Verify the macOS system is configured to disable password authentication for SSH with the following command: /usr/sbin/sshd -G | /usr/bin/grep -Ec '^(passwordauthentication\s+no|kbdinteractiveauthentication\s+no)' If the result is not "2", this is a finding.
Configure the macOS system to disable password authentication for SSH with the following command: include_dir=$(/usr/bin/awk '/^Include/ {print $2}' /etc/ssh/sshd_config | /usr/bin/tr -d '*') if [[ -z $include_dir ]]; then /usr/bin/sed -i.bk "1s/.*/Include \/etc\/ssh\/sshd_config.d\/\*/" /etc/ssh/sshd_config fi echo "passwordauthentication no" >> "${include_dir}01-mscp-sshd.conf" echo "kbdinteractiveauthentication no" >> "${include_dir}01-mscp-sshd.conf" for file in $(ls ${include_dir}); do if [[ "$file" == "100-macos.conf" ]]; then continue fi if [[ "$file" == "01-mscp-sshd.conf" ]]; then break fi /bin/mv ${include_dir}${file} ${include_dir}20-${file} done
Verify the macOS system is configured to disable SMB sharing with the following command: /bin/launchctl print-disabled system | /usr/bin/grep -c '"com.apple.smbd" => disabled' If the result is not "1", this is a finding.
Configure the macOS system to disable SMB sharing with the following command: /bin/launchctl disable system/com.apple.smbd The system may need to be restarted for the update to take effect.
Verify the macOS system is configured to disable NFS service with the following command: /bin/launchctl print-disabled system | /usr/bin/grep -c '"com.apple.nfsd" => disabled' If the result is not "1", this is a finding.
Configure the macOS system to disable NFS service with the following command: /bin/launchctl disable system/com.apple.nfsd The system may need to be restarted for the update to take effect.
Verify the macOS system is configured to disable Location Services with the following command: /usr/bin/sudo -u _locationd /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.locationd')\ .objectForKey('LocationServicesEnabled').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable Location Services with the following command: /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool false; pid=$(/bin/launchctl list | /usr/bin/awk '/com.apple.locationd/ { print $1 }') kill -9 $pid
Verify the macOS system is configured to disable Bonjour multicast with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.mDNSResponder')\ .objectForKey('NoMulticastAdvertisements').js EOS If the result is not "true", this is a finding.
Configure the macOS system to disable Bonjour multicast by installing the "com.apple.mDNSResponder" configuration profile.
Verify the macOS system is configured to disable UUCP service with the following command: /bin/launchctl print-disabled system | /usr/bin/grep -c '"com.apple.uucp" => disabled' If the result is not "1", this is a finding.
Configure the macOS system to disable UUCP service with the following command: /bin/launchctl disable system/com.apple.uucp The system may need to be restarted for the update to take effect.
Verify the macOS system is configured to disable Internet Sharing with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.MCX')\ .objectForKey('forceInternetSharingOff').js EOS If the result is not "true", this is a finding.
Configure the macOS system to disable Internet Sharing by installing the "com.apple.MCX" configuration profile.
Verify the macOS system is configured to disable the built-in web server with the following command: /bin/launchctl print-disabled system | /usr/bin/grep -c '"org.apache.httpd" => disabled' If the result is not "1", this is a finding.
Configure the macOS system to disable the built-in web server with the following command: /bin/launchctl disable system/org.apache.httpd The system may need to be restarted for the update to take effect.
Verify the macOS system is configured to disable AirDrop with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowAirDrop').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable AirDrop by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable FaceTime.app with the following command: /usr/bin/osascript -l JavaScript << EOS function run() { let pref1 = ObjC.unwrap($.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess.new')\ .objectForKey('familyControlsEnabled')) let pathlist = $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess.new')\ .objectForKey('pathBlackList').js for ( let app in pathlist ) { if ( ObjC.unwrap(pathlist[app]) == "/Applications/FaceTime.app" && pref1 == true ){ return("true") } } return("false") } EOS If the result is not "true", this is a finding.
Configure the macOS system to disable FaceTime.app by installing the "com.apple.applicationaccess.new" configuration profile.
Verify the macOS system is configured to disable iCloud Calendar services with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowCloudCalendar').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable iCloud Calendar services by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable iCloud Reminders with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowCloudReminders').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable iCloud Reminders by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable iCloud Address Book with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowCloudAddressBook').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable iCloud Address Book by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable iCloud Mail with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowCloudMail').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable iCloud Mail by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable iCloud Notes with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowCloudNotes').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable iCloud Notes by installing the "com.apple.applicationaccess" configuration profile.
If the device or operating system does not have a camera installed, this requirement is not applicable. This requirement is not applicable to mobile devices (smartphones and tablets), where the use of the camera is a local authorizing official (AO) decision. This requirement is not applicable to dedicated video teleconference (VTC) suites in approved VTC locations that are centrally managed. For an external camera, if there is not a method for the operator to manually disconnect camera at the end of collaborative computing sessions, this is a finding. For a built-in camera, the camera must be protected by a camera cover (e.g., laptop camera cover slide) when not in use. If the built-in camera is not protected with a camera cover or is not physically disabled, this is a finding. If the camera is not disconnected, covered, or physically disabled, verify the macOS system is configured to disable the camera with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowCamera').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable the camera by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable Siri with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowAssistant').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable Siri by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable sending diagnostic and usage data to Apple with the following command: /usr/bin/osascript -l JavaScript << EOS function run() { let pref1 = $.NSUserDefaults.alloc.initWithSuiteName('com.apple.SubmitDiagInfo')\ .objectForKey('AutoSubmit').js let pref2 = $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowDiagnosticSubmission').js if ( pref1 == false && pref2 == false ){ return("true") } else { return("false") } } EOS If the result is not "true", this is a finding.
Configure the macOS system to disable sending diagnostic and usage data to Apple by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable Remote Apple Events with the following command: /bin/launchctl print-disabled system | /usr/bin/grep -c '"com.apple.AEServer" => disabled' If the result is not "1", this is a finding.
Configure the macOS system to disable Remote Apple Events with the following commands: /usr/sbin/systemsetup -setremoteappleevents off /bin/launchctl disable system/com.apple.AEServer NOTE: Systemsetup with -setremoteappleevents flag will fail unless Full Disk Access to systemsetup or its parent process is granted. This requires supervision.
Verify the macOS system is configured to disable Apple ID setup during Setup Assistant with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.SetupAssistant.managed')\ .objectForKey('SkipCloudSetup').js EOS If the result is not "true", this is a finding.
Configure the macOS system to disable Apple ID setup during Setup Assistant by installing the "com.apple.SetupAssistant.managed" configuration profile.
Verify the macOS system is configured to disable Privacy Setup services during Setup Assistant with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.SetupAssistant.managed')\ .objectForKey('SkipPrivacySetup').js EOS If the result is not "true", this is a finding.
Configure the macOS system to disable Privacy Setup services during Setup Assistant by installing the "com.apple.SetupAssistant.managed" configuration profile.
Verify the macOS system is configured to disable iCloud storage setup during Setup Assistant with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.SetupAssistant.managed')\ .objectForKey('SkipiCloudStorageSetup').js EOS If the result is not "true", this is a finding.
Configure the macOS system to disable iCloud storage setup during Setup Assistant by installing the "com.apple.SetupAssistant.managed" configuration profile.
Verify the macOS system is configured to disable TFTP service with the following command: /bin/launchctl print-disabled system | /usr/bin/grep -c '"com.apple.tftpd" => disabled' If the result is not "1", this is a finding.
Configure the macOS system to disable TFTP service with the following command: /bin/launchctl disable system/com.apple.tftpd The system may need to be restarted for the update to take effect.
Verify the macOS system is configured to disable Siri Setup during Setup Assistant with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.SetupAssistant.managed')\ .objectForKey('SkipSiriSetup').js EOS If the result is not "true", this is a finding.
Configure the macOS system to disable Siri Setup during Setup Assistant by installing the "com.apple.SetupAssistant.managed" configuration profile.
Verify the macOS system is configured to disable iCloud Keychain Sync with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowCloudKeychainSync').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable iCloud Keychain Sync by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable iCloud Document Sync with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowCloudDocumentSync').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable iCloud Document Sync by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable iCloud Bookmarks with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowCloudBookmarks').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable iCloud Bookmarks by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable the iCloud Photo Library with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowCloudPhotoLibrary').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable the iCloud Photo Library by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable Screen Sharing and Apple Remote Desktop with the following command: /bin/launchctl print-disabled system | /usr/bin/grep -c '"com.apple.screensharing" => disabled' If the result is not "1", this is a finding.
Configure the macOS system to disable Screen Sharing and Apple Remote Desktop with the following command: /bin/launchctl disable system/com.apple.screensharing The system may need to be restarted for the update to take effect. NOTE: This will apply to the whole system.
Verify the macOS system is configured to disable the System Settings pane for Wallet and Apple Pay with the following command: /usr/bin/profiles show -output stdout-xml | /usr/bin/xmllint --xpath '//key[text()="DisabledSystemSettings"]/following-sibling::*[1]' - | /usr/bin/grep -c "com.apple.WalletSettingsExtension" If the result is not "1", this is a finding.
Configure the macOS system to disable the System Settings pane for Wallet and Apple Pay by installing the "com.apple.systempreferences" configuration profile.
Verify the macOS system is configured to disable the system settings pane for Siri with the following command: /usr/bin/profiles show -output stdout-xml | /usr/bin/xmllint --xpath '//key[text()="DisabledSystemSettings"]/following-sibling::*[1]' - | /usr/bin/grep -c com.apple.Siri-Settings.extension If the result is not "1", this is a finding.
Configure the macOS system to disable the system settings pane for Siri by installing the "com.apple.systempreferences" configuration profile.
Verify the macOS system is configured to apply gatekeeper settings to block applications from unidentified developers with the following command: /usr/sbin/spctl --status --verbose | /usr/bin/grep -c "developer id enabled" If the result is not "1", this is a finding.
Configure the macOS system to apply gatekeeper settings to block applications from unidentified developers with the following command: /usr/sbin/spctl --global-enable; /usr/sbin/spctl --enable
Verify the macOS system is configured to disable Bluetooth with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.MCXBluetooth')\ .objectForKey('DisableBluetooth').js EOS If the result is not "true", this is a finding.
Configure the macOS system to disable Bluetooth by installing the "com.apple.MCXBluetooth" configuration profile.
Verify the macOS system is configured to disable the guest account with the following command: /usr/bin/osascript -l JavaScript << EOS function run() { let pref1 = ObjC.unwrap($.NSUserDefaults.alloc.initWithSuiteName('com.apple.MCX')\ .objectForKey('DisableGuestAccount')) let pref2 = ObjC.unwrap($.NSUserDefaults.alloc.initWithSuiteName('com.apple.MCX')\ .objectForKey('EnableGuestAccount')) if ( pref1 == true && pref2 == false ) { return("true") } else { return("false") } } EOS If the result is not "true", this is a finding.
Configure the macOS system to disable the guest account by installing the "com.apple.MCX" configuration profile.
Verify the macOS system is configured to enable gatekeeper with the following command: /usr/sbin/spctl --status | /usr/bin/grep -c "assessments enabled" If the result is not "1", this is a finding.
Configure the macOS system to enable gatekeeper with the following command: /usr/sbin/spctl --global-enable
Verify the macOS system is configured to disable unattended or automatic login to the system with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.loginwindow')\ .objectForKey('com.apple.login.mcx.DisableAutoLoginClient').js EOS If the result is not "true", this is a finding.
Configure the macOS system to disable unattended or automatic login to the system by installing the "com.apple.loginwindow" configuration profile.
Verify the macOS system is configured so that permissions are set correctly on user home directories with the following command: /usr/bin/find /System/Volumes/Data/Users -mindepth 1 -maxdepth 1 -type d ! \( -perm 700 -o -perm 711 \) | /usr/bin/grep -v "Shared" | /usr/bin/grep -v "Guest" | /usr/bin/wc -l | /usr/bin/xargs If the result is not "0", this is a finding.
Configure the macOS system to set the appropriate permissions for each user on the system with the following command: IFS=$'\n' for userDirs in $( /usr/bin/find /System/Volumes/Data/Users -mindepth 1 -maxdepth 1 -type d ! \( -perm 700 -o -perm 711 \) | /usr/bin/grep -v "Shared" | /usr/bin/grep -v "Guest" ); do /bin/chmod og-rwx "$userDirs" done unset IFS
Verify the macOS system is configured to require administrator privileges to modify systemwide settings with the following command: authDBs=("system.preferences" "system.preferences.energysaver" "system.preferences.network" "system.preferences.printing" "system.preferences.sharing" "system.preferences.softwareupdate" "system.preferences.startupdisk" "system.preferences.timemachine") result="1" for section in ${authDBs[@]}; do if [[ $(/usr/bin/security -q authorizationdb read "$section" | /usr/bin/xmllint -xpath 'name(//*[contains(text(), "shared")]/following-sibling::*[1])' -) != "false" ]]; then result="0" fi if [[ $(security -q authorizationdb read "$section" | /usr/bin/xmllint -xpath '//*[contains(text(), "group")]/following-sibling::*[1]/text()' - ) != "admin" ]]; then result="0" fi if [[ $(/usr/bin/security -q authorizationdb read "$section" | /usr/bin/xmllint -xpath 'name(//*[contains(text(), "authenticate-user")]/following-sibling::*[1])' -) != "true" ]]; then result="0" fi if [[ $(/usr/bin/security -q authorizationdb read "$section" | /usr/bin/xmllint -xpath 'name(//*[contains(text(), "session-owner")]/following-sibling::*[1])' -) != "false" ]]; then result="0" fi done echo $result If the result is not "1", this is a finding.
Configure the macOS system to require administrator privileges to modify systemwide settings with the following command: authDBs=("system.preferences" "system.preferences.energysaver" "system.preferences.network" "system.preferences.printing" "system.preferences.sharing" "system.preferences.softwareupdate" "system.preferences.startupdisk" "system.preferences.timemachine") for section in ${authDBs[@]}; do /usr/bin/security -q authorizationdb read "$section" > "/tmp/$section.plist" class_key_value=$(usr/libexec/PlistBuddy -c "Print :class" "/tmp/$section.plist" 2>&1) if [[ "$class_key_value" == *"Does Not Exist"* ]]; then /usr/libexec/PlistBuddy -c "Add :class string user" "/tmp/$section.plist" else /usr/libexec/PlistBuddy -c "Set :class user" "/tmp/$section.plist" fi key_value=$(/usr/libexec/PlistBuddy -c "Print :shared" "/tmp/$section.plist" 2>&1) if [[ "$key_value" == *"Does Not Exist"* ]]; then /usr/libexec/PlistBuddy -c "Add :shared bool false" "/tmp/$section.plist" else /usr/libexec/PlistBuddy -c "Set :shared false" "/tmp/$section.plist" fi auth_user_key=$(/usr/libexec/PlistBuddy -c "Print :authenticate-user" "/tmp/$section.plist" 2>&1) if [[ "$auth_user_key" == *"Does Not Exist"* ]]; then /usr/libexec/PlistBuddy -c "Add :authenticate-user bool true" "/tmp/$section.plist" else /usr/libexec/PlistBuddy -c "Set :authenticate-user true" "/tmp/$section.plist" fi session_owner_key=$(/usr/libexec/PlistBuddy -c "Print :session-owner" "/tmp/$section.plist" 2>&1) if [[ "$session_owner_key" == *"Does Not Exist"* ]]; then /usr/libexec/PlistBuddy -c "Add :session-owner bool false" "/tmp/$section.plist" else /usr/libexec/PlistBuddy -c "Set :session-owner false" "/tmp/$section.plist" fi group_key=$(usr/libexec/PlistBuddy -c "Print :group" "/tmp/$section.plist" 2>&1) if [[ "$group_key" == *"Does Not Exist"* ]]; then /usr/libexec/PlistBuddy -c "Add :group string admin" "/tmp/$section.plist" else /usr/libexec/PlistBuddy -c "Set :group admin" "/tmp/$section.plist" fi /usr/bin/security -q authorizationdb write "$section" < "/tmp/$section.plist" done
Verify the macOS system is configured to disable Airplay Receiver with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowAirPlayIncomingRequests').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable Airplay Receiver by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable TouchID for unlocking the device with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowFingerprintForUnlock').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable TouchID for unlocking the device by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable Media Sharing with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowMediaSharing').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable Media Sharing by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable Bluetooth sharing with the following command: /usr/bin/defaults -currentHost read com.apple.Bluetooth PrefKeyServicesEnabled If the result is not "0", this is a finding.
Configure the macOS system to disable Bluetooth sharing with the following command: /usr/bin/defaults -currentHost write com.apple.Bluetooth PrefKeyServicesEnabled -bool false
Verify the macOS system is configured to disable account modification with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowAccountModification').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable Account Modification by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable CD/DVD Sharing with the following command: /usr/bin/pgrep -q ODSAgent; /bin/echo $? If the result is not "1", this is a finding.
Configure the macOS system to disable CD/DVD Sharing with the following command: /bin/launchctl unload /System/Library/LaunchDaemons/com.apple.ODSAgent.plist
Verify the macOS system is configured to disable Content Caching service with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowContentCaching').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable Content Caching service by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable iCloud Desktop and Document folder synchronization with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowCloudDesktopAndDocuments').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable iCloud Desktop and Document folder synchronization by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable iCloud Game Center with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowGameCenter').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable iCloud Game Center by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable the iCloud Private Relay with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowCloudPrivateRelay').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable the iCloud Private Relay by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable Find My service with the following command: /usr/bin/osascript -l JavaScript << EOS function run() { let pref1 = ObjC.unwrap($.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowFindMyDevice')) let pref2 = ObjC.unwrap($.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowFindMyFriends')) let pref3 = ObjC.unwrap($.NSUserDefaults.alloc.initWithSuiteName('com.apple.icloud.managed')\ .objectForKey('DisableFMMiCloudSetting')) if ( pref1 == false && pref2 == false && pref3 == true ) { return("true") } else { return("false") } } EOS If the result is not "true", this is a finding.
Configure the macOS system to disable Find My service by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable Personalized Advertising with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowApplePersonalizedAdvertising').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable Personalized Advertising by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable sending Siri and Dictation information to Apple with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.assistant.support')\ .objectForKey('Siri Data Sharing Opt-In Status').js EOS If the result is not "2", this is a finding.
Configure the macOS system to disable sending Siri and Dictation information to Apple by installing the "com.apple.assistant.support" configuration profile.
For Intel-based systems, this is not applicable. Verify the macOS system is configured to enforce On Device Only Dictation with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('forceOnDeviceOnlyDictation').js EOS If the result is not "true", this is a finding.
Configure the macOS system to enforce On Device Only Dictation by installing the "com.apple.applicationaccess" configuration profile.
For Apple Silicon-based systems, this is not applicable. Verify the macOS system is configured to disable Dictation with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowDictation').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable Dictation by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable Printer Sharing with the following command: /usr/sbin/cupsctl | /usr/bin/grep -c "_share_printers=0" If the result is not "1", this is a finding.
Configure the macOS system to disable Printer Sharing with the following commands: /usr/sbin/cupsctl --no-share-printers /usr/bin/lpstat -p | awk '{print $2}'| /usr/bin/xargs -I{} lpadmin -p {} -o printer-is-shared=false
Verify the macOS system is configured to disable Remote Management with the following command: /usr/libexec/mdmclient QuerySecurityInfo | /usr/bin/grep -c "RemoteDesktopEnabled = 0" If the result is not "1", this is a finding.
Configure the macOS system to disable Remote Management with the following commands: /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -deactivate -stop
Verify the macOS system is configured to disable the Bluetooth System Settings pane with the following command: /usr/bin/profiles show -output stdout-xml | /usr/bin/xmllint --xpath '//key[text()="DisabledSystemSettings"]/following-sibling::*[1]' - | /usr/bin/grep -c com.apple.BluetoothSettings If the result is not "1", this is a finding.
Configure the macOS system to disable the Bluetooth System Settings pane by installing the "com.apple.systempreferences" configuration profiles.
Verify the macOS system is configured to disable iCloud Freeform services with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowCloudFreeform').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable iCloud Freeform services by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to issue or obtain public key certificates from an approved service provider with the following command: /usr/bin/security dump-keychain /Library/Keychains/System.keychain | /usr/bin/awk -F'"' '/labl/ {print $4}' If the result does not contain a list of approved certificate authorities, this is a finding.
Configure the macOS system to issue or obtain public key certificates from an approved service provider by obtaining the approved certificates from the appropriate authority and install them to the System Keychain.
Verify the macOS system is configured to require that passwords contain a minimum of one numeric character with the following command: /usr/bin/pwpolicy -getaccountpolicies 2> /dev/null | /usr/bin/tail +2 | /usr/bin/xmllint --xpath '//dict/key[text()="policyIdentifier"]/following-sibling::*[1]/text()' - | /usr/bin/grep "requireAlphanumeric" -c If the result is not "1", this is a finding.
Configure the macOS system to require that passwords contain a minimum of one numeric character by installing the "com.apple.mobiledevice.passwordpolicy" configuration profile.
Verify the macOS system is configured to restrict maximum password lifetime to 60 days with the following command: /usr/bin/pwpolicy -getaccountpolicies 2> /dev/null | /usr/bin/tail +2 | /usr/bin/xmllint --xpath '//dict/key[text()="policyAttributeExpiresEveryNDays"]/following-sibling::*[1]/text()' - If the result is not "60" or less, this is a finding.
Configure the macOS system to restrict maximum password lifetime to 60 days by installing the "com.apple.mobiledevice.passwordpolicy" configuration profile.
Verify the macOS system is configured to enforce a minimum 14-character password length with the following command: /usr/bin/pwpolicy -getaccountpolicies 2> /dev/null | /usr/bin/tail +2 | /usr/bin/xmllint --xpath 'boolean(//*[contains(text(),"policyAttributePassword matches '\''.{14,}'\''")])' - If the result is not "true", this is a finding.
Configure the macOS system to enforce a 14-character password length by installing the "com.apple.mobiledevice.passwordpolicy" configuration profile.
Verify the macOS system is configured to require passwords contain a minimum of one special character with the following command: /usr/bin/pwpolicy -getaccountpolicies 2> /dev/null | /usr/bin/tail +2 | /usr/bin/xmllint --xpath 'boolean(//*[contains(text(),"policyAttributePassword matches '\''(.*[^a-zA-Z0-9].*){1,}'\''")])' - If the result is not "true", this is a finding.
Configure the macOS system to require that passwords contain a minimum of one special character by installing the "com.apple.mobiledevice.passwordpolicy" configuration profile.
Verify the macOS system is configured to disable password hints with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.loginwindow')\ .objectForKey('RetriesUntilHint').js EOS If the result is not "0", this is a finding.
Configure the macOS system to disable password hints by installing the "com.apple.loginwindow" configuration profile.
For Apple Silicon systems, this is not applicable. Verify the macOS system is configured with a firmware password with the following command: /usr/sbin/firmwarepasswd -check | /usr/bin/grep -c "Password Enabled: Yes" If the result is not "1", this is a finding.
Configure the macOS system with a firmware password with the following command: /usr/sbin/firmwarepasswd -setpasswd NOTE: If firmware password or passcode is forgotten, the only way to reset the forgotten password is through a machine-specific binary generated and provided by Apple. Users must schedule a support call and provide proof of purchase before the firmware binary will be generated.
Verify the macOS system is configured to remove password hints from user accounts with the following command: HINT=$(/usr/bin/dscl . -list /Users hint | /usr/bin/awk '{ print $2 }') if [ -z "$HINT" ]; then echo "PASS" else echo "FAIL" fi If the result is not "PASS", this is a finding.
Configure the macOS system to remove password hints from user accounts with the following command: for u in $(/usr/bin/dscl . -list /Users UniqueID | /usr/bin/awk '$2 > 500 {print $1}'); do /usr/bin/dscl . -delete /Users/$u hint done
Verify the macOS system is configured to enforce multifactor authentication with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.security.smartcard')\ .objectForKey('enforceSmartCard').js EOS If the result is not "true", this is a finding.
Configure the macOS system to enforce multifactor authentication by installing the "com.apple.security.smartcard" configuration profile. NOTE: To ensure continued access to the operating system, consult the supplemental guidance provided with the STIG before applying the configuration profile.
Verify the macOS system is configured to allow smart card authentication with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.security.smartcard')\ .objectForKey('allowSmartCard').js EOS If the result is not "true", this is a finding.
Configure the macOS system to enforce multifactor authentication by installing the "com.apple.security.smartcard" configuration profile. NOTE: To ensure continued access to the operating system, consult the supplemental guidance provided with the STIG before applying the configuration profile.
Verify the macOS system is configured to enforce multifactor authentication for login with the following command: /usr/bin/grep -Ec '^(auth\s+sufficient\s+pam_smartcard.so|auth\s+required\s+pam_deny.so)' /etc/pam.d/login If the result is not "2", this is a finding.
Configure the macOS system to enforce multifactor authentication for login with the following commands: /bin/cat > /etc/pam.d/login << LOGIN_END # login: auth account password session auth sufficient pam_smartcard.so auth optional pam_krb5.so use_kcminit auth optional pam_ntlm.so try_first_pass auth optional pam_mount.so try_first_pass auth required pam_opendirectory.so try_first_pass auth required pam_deny.so account required pam_nologin.so account required pam_opendirectory.so password required pam_opendirectory.so session required pam_launchd.so session required pam_uwtmp.so session optional pam_mount.so LOGIN_END /bin/chmod 644 /etc/pam.d/login /usr/sbin/chown root:wheel /etc/pam.d/login
Verify the macOS system is configured to enforce multifactor authentication for the su command with the following command: /usr/bin/grep -Ec '^(auth\s+sufficient\s+pam_smartcard.so|auth\s+required\s+pam_rootok.so)' /etc/pam.d/su If the result is not "2", this is a finding.
Configure the macOS system to enforce multifactor authentication for the su command with the following commands: /bin/cat > /etc/pam.d/su << SU_END # su: auth account password session auth sufficient pam_smartcard.so auth required pam_rootok.so auth required pam_group.so no_warn group=admin,wheel ruser root_only fail_safe account required pam_permit.so account required pam_opendirectory.so no_check_shell password required pam_opendirectory.so session required pam_launchd.so SU_END # Fix new file ownership and permissions /bin/chmod 644 /etc/pam.d/su /usr/sbin/chown root:wheel /etc/pam.d/su
Verify the macOS system is configured to enforce multifactor authentication for privilege escalation through the sudo command with the following command: /usr/bin/grep -Ec '^(auth\s+sufficient\s+pam_smartcard.so|auth\s+required\s+pam_deny.so)' /etc/pam.d/sudo If the result is not "2", this is a finding.
Configure the macOS system to enforce multifactor authentication for privilege escalation through the sudo command with the following commands: /bin/cat > /etc/pam.d/sudo << SUDO_END # sudo: auth account password session auth sufficient pam_smartcard.so auth required pam_opendirectory.so auth required pam_deny.so account required pam_permit.so password required pam_deny.so session required pam_permit.so SUDO_END /bin/chmod 444 /etc/pam.d/sudo /usr/sbin/chown root:wheel /etc/pam.d/sudo
Verify the macOS system is configured to require that passwords contain a minimum of one lowercase character and one uppercase character with the following command: /usr/bin/pwpolicy -getaccountpolicies 2> /dev/null | /usr/bin/tail +2 | /usr/bin/xmllint --xpath 'boolean(//*[contains(text(),"policyAttributePassword matches '\''^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).*$'\''")])' - If the result is not "true", this is a finding.
Configure the macOS system to require at least one lowercase character and one uppercase character in password complexity by installing the "com.apple.mobiledevice.passwordpolicy" configuration profile.
Verify the macOS system is configured to set minimum password lifetime to 24 hours with the following command: /usr/bin/pwpolicy -getaccountpolicies 2> /dev/null | /usr/bin/tail +2 | /usr/bin/xmllint --xpath '//dict/key[text()="policyAttributeMinimumLifetimeHours"]/following-sibling::integer[1]/text()' - | /usr/bin/awk '{ if ($1 >= 24 ) {print "yes"} else {print "no"}}' If the result is not "yes", this is a finding.
Configure the macOS system to set minimum password lifetime to 24 hours. This setting may be enforced using local policy or by a directory service. To set local policy to require a minimum password lifetime, edit the current password policy to contain the following <dict> within the "policyCategoryPasswordContent": [source,xml] ---- <dict> <key>policyContent</key> <string>policyAttributeLastPasswordChangeTime < policyAttributeCurrentTime - (policyAttributeMinimumLifetimeHours * 60 * 60)</string> <key>policyIdentifier</key> <string>Minimum Password Lifetime</string> <key>policyParameters</key> <dict> <key>policyAttributeMinimumLifetimeHours</key> <integer>24</integer> </dict> </dict> ---- After saving the file and exiting to the command prompt, run the following command to load the new policy file, substituting the path to the file in place of "$pwpolicy_file". [source,bash] ---- /usr/bin/pwpolicy setaccountpolicies $pwpolicy_file ----
Verify the macOS system is configured to disable accounts after 35 days of inactivity with the following command: /usr/bin/pwpolicy -getaccountpolicies 2> /dev/null | /usr/bin/tail +2 | /usr/bin/xmllint --xpath '//dict/key[text()="policyAttributeInactiveDays"]/following-sibling::integer[1]/text()' - If the result is not "35", this is a finding.
Configure the macOS system to disable accounts after 35 days of inactivity with the following command: This setting may be enforced using local policy or by a directory service. To set local policy to disable an inactive user after 35 days, edit the current password policy to contain the following <dict> within the "policyCategoryAuthentication": [source,xml] ---- <dict> <key>policyContent</key> <string>policyAttributeLastAuthenticationTime > policyAttributeCurrentTime - (policyAttributeInactiveDays * 24 * 60 * 60)</string> <key>policyIdentifier</key> <string>Inactive Account</string> <key>policyParameters</key> <dict> <key>policyAttributeInactiveDays</key> <integer>35</integer> </dict> </dict> ---- After saving the file and exiting to the command prompt, run the following command to load the new policy file, substituting the path to the file in place of "$pwpolicy_file". [source,bash] ---- /usr/bin/pwpolicy setaccountpolicies $pwpolicy_file ----
Verify the macOS system is configured with ASL files owned by root and group to wheel with the following command: /usr/bin/stat -f '%Su:%Sg:%N' $(/usr/bin/grep -e '^>' /etc/asl.conf /etc/asl/* | /usr/bin/awk '{ print $2 }') 2> /dev/null | /usr/bin/awk '!/^root:wheel:/{print $1}' | /usr/bin/wc -l | /usr/bin/tr -d ' ' If the result is not "0", this is a finding.
Configure the macOS system with ASL files owned by root and group to wheel with the following command: /usr/sbin/chown root:wheel $(/usr/bin/stat -f '%Su:%Sg:%N' $(/usr/bin/grep -e '^>' /etc/asl.conf /etc/asl/* | /usr/bin/awk '{ print $2 }') 2> /dev/null | /usr/bin/awk '!/^root:wheel:/{print $1}' | /usr/bin/awk -F":" '!/^root:wheel:/{print $3}')
Verify the macOS system is configured with ASL files to mode 640 or less permissive with the following command: /usr/bin/stat -f '%A:%N' $(/usr/bin/grep -e '^>' /etc/asl.conf /etc/asl/* | /usr/bin/awk '{ print $2 }') 2> /dev/null | /usr/bin/awk '!/640/{print $1}' | /usr/bin/wc -l | /usr/bin/tr -d ' ' If the result is not "0", this is a finding.
Configure the macOS system with ASL files to mode 640 with the following command: /bin/chmod 640 $(/usr/bin/stat -f '%A:%N' $(/usr/bin/grep -e '^>' /etc/asl.conf /etc/asl/* | /usr/bin/awk '{ print $2 }') 2> /dev/null | /usr/bin/awk -F":" '!/640/{print $2}')
Verify the macOS system is configured with system log files owned by root and group to wheel with the following command: /usr/bin/stat -f '%Su:%Sg:%N' $(/usr/bin/grep -v '^#' /etc/newsyslog.conf | /usr/bin/awk '{ print $1 }') 2> /dev/null | /usr/bin/awk '!/^root:wheel:/{print $1}' | /usr/bin/wc -l | /usr/bin/tr -d ' ' If the result is not "0", this is a finding.
Configure the macOS system with system log files owned by root and group to wheel with the following command: /usr/sbin/chown root:wheel $(/usr/bin/stat -f '%Su:%Sg:%N' $(/usr/bin/grep -v '^#' /etc/newsyslog.conf | /usr/bin/awk '{ print $1 }') 2> /dev/null | /usr/bin/awk -F":" '!/^root:wheel:/{print $3}')
Verify the macOS system is configured with system log files set to mode 640 or less permissive with the following command: /usr/bin/stat -f '%A:%N' $(/usr/bin/grep -v '^#' /etc/newsyslog.conf | /usr/bin/awk '{ print $1 }') 2> /dev/null | /usr/bin/awk '!/640/{print $1}' | /usr/bin/wc -l | /usr/bin/tr -d ' ' If the result is not "0", this is a finding.
Configure the macOS system with system log files set to mode 640 or less permissive with the following command: /bin/chmod 640 $(/usr/bin/stat -f '%A:%N' $(/usr/bin/grep -v '^#' /etc/newsyslog.conf | /usr/bin/awk '{ print $1 }') 2> /dev/null | /usr/bin/awk '!/640/{print $1}' | awk -F":" '!/640/{print $2}')
Verify the macOS system is configured with install.log retention to 365 with the following command: /usr/sbin/aslmanager -dd 2>&1 | /usr/bin/awk '/\/var\/log\/install.log$/ {count++} /Processing module com.apple.install/,/Finished/ { for (i=1;i<=NR;i++) { if ($i == "TTL" && $(i+2) >= 365) { ttl="True" }; if ($i == "MAX") {max="True"}}} END{if (count > 1) { print "Multiple config files for /var/log/install, manually remove the extra files"} else if (max == "True") { print "all_max setting is configured, must be removed" } if (ttl != "True") { print "TTL not configured" } else { print "Yes" }}' If the result is not "yes", this is a finding.
Configure the macOS system with install.log retention to 365 with the following command: /usr/bin/sed -i '' "s/\* file \/var\/log\/install.log.*/\* file \/var\/log\/install.log format='\$\(\(Time\)\(JZ\)\) \$Host \$\(Sender\)\[\$\(PID\\)\]: \$Message' rotate=utc compress file_max=50M size_only ttl=365/g" /etc/asl/com.apple.install NOTE: If multiple configuration files in /etc/asl are set to process the file /var/log/install.log, these files must be manually removed.
Verify the macOS system is configured to enable System Integrity Protection with the following command: /usr/bin/csrutil status | /usr/bin/grep -c 'System Integrity Protection status: enabled.' If the result is not "1", this is a finding.
Configure the macOS system to enable System Integrity Protection by booting into "Recovery" mode, launching "Terminal" from the "Utilities" menu, and running the following command: /usr/bin/csrutil enable
Verify the macOS system is configured to enforce FileVault with the following command: dontAllowDisable=$(/usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.MCX')\ .objectForKey('dontAllowFDEDisable').js EOS ) fileVault=$(/usr/bin/fdesetup status | /usr/bin/grep -c "FileVault is On.") if [[ "$dontAllowDisable" == "true" ]] && [[ "$fileVault" == 1 ]]; then echo "1" else echo "0" fi If the result is not "1", this is a finding.
Refer to the FileVault supplemental to implement this rule.
Verify the macOS system is configured to enable the Application Firewall with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.security.firewall')\ .objectForKey('EnableFirewall').js EOS If the result is not "true", this is a finding.
Configure the macOS system to enable the Application Firewall by installing the "com.apple.security.firewall" configuration profile.
Verify the macOS system is configured to prompt for username and password at the login window with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.loginwindow')\ .objectForKey('SHOWFULLNAME').js EOS If the result is not "true", this is a finding.
Configure the macOS system to prompt for username and password at the login window by installing the "com.apple.loginwindow" configuration profile.
Verify the macOS system is configured to disable the TouchID prompt during Setup Assistant with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.SetupAssistant.managed')\ .objectForKey('SkipTouchIDSetup').js EOS If the result is not "true", this is a finding.
Configure the macOS system to disable the TouchID prompt during Setup Assistant by installing the "com.apple.SetupAssistant.managed" configuration profile.
Verify the macOS system is configured to disable the Screen Time prompt during Setup Assistant with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.SetupAssistant.managed')\ .objectForKey('SkipScreenTime').js EOS If the result is not "true", this is a finding.
Configure the macOS system to disable the Screen Time prompt during Setup Assistant by installing the "com.apple.SetupAssistant.managed" configuration profile.
Verify the macOS system is configured to disable Unlock with Apple Watch during Setup Assistant with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.SetupAssistant.managed')\ .objectForKey('SkipUnlockWithWatch').js EOS If the result is not "true", this is a finding.
Configure the macOS system to disable Unlock with Apple Watch during Setup Assistant by installing the "com.apple.SetupAssistant.managed" configuration profile.
Verify the macOS system is configured to disable Handoff with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowActivityContinuation').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable Handoff by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable proximity-based password sharing requests with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowPasswordProximityRequests').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable proximity-based password sharing requests by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable Erase Content and Settings with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowEraseContentAndSettings').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable Erase Content and Settings by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to enable authenticated root with the following command: /usr/libexec/mdmclient QuerySecurityInfo | /usr/bin/grep -c "AuthenticatedRootVolumeEnabled = 1;" If the result is not "1", this is a finding.
Configure the macOS system to enable authenticated root with the following command: /usr/bin/csrutil authenticated-root enable NOTE: To reenable "Authenticated Root", boot the affected system into "Recovery" mode, launch "Terminal" from the "Utilities" menu, and run the command.
Verify the macOS system is configured to prohibit user installation of software into /users/ with the following command: /usr/bin/osascript -l JavaScript << EOS function run() { let pref1 = ObjC.unwrap($.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess.new')\ .objectForKey('familyControlsEnabled')) let pathlist = $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess.new')\ .objectForKey('pathBlackList').js for ( let app in pathlist ) { if ( ObjC.unwrap(pathlist[app]) == "/Users/" && pref1 == true ){ return("true") } } return("false") } EOS If the result is not "true", this is a finding.
Configure the macOS system to prohibit user installation of software into /users/ by installing the "com.apple.applicationaccess.new" configuration profile.
Verify the macOS system is configured to authorize USB devices before allowing connection with the following command: /usr/bin/osascript -l JavaScript << EOS function run() { let pref1 = ObjC.unwrap($.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowUSBRestrictedMode')) if ( pref1 == false ) { return("false") } else { return("true") } } EOS If the result is not "true", this is a finding.
Configure the macOS system to authorize USB devices before allowing connection by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to ensure Secure Boot level is set to "full" using the following command: /usr/libexec/mdmclient QuerySecurityInfo | /usr/bin/grep -c "SecureBootLevel = full" If the result is not "1", this is a finding.
Configure the macOS system to ensure Secure Boot level is set to "full" by booting into Recovery Mode and enabling Full Secure Boot.
Verify the macOS system is configured to enforce enrollment in mobile device management with the following command: /usr/bin/profiles status -type enrollment | /usr/bin/awk -F: '/MDM enrollment/ {print $2}' | /usr/bin/grep -c "Yes (User Approved)" If the result is not "1", this is a finding.
Configure the macOS system by ensuring that the system is enrolled via UAMDM.
For non-Apple Silicon systems, this is not applicable. Verify the macOS system is configured with Recovery Lock with the following command: /usr/libexec/mdmclient QuerySecurityInfo | /usr/bin/grep -c "IsRecoveryLockEnabled = 1" If the result is not "1", this is a finding.
Configure the macOS system with Recovery Lock with the SetRecoveryLock command. This can be used to set a Recovery Lock password and must be from the MDM.
Verify the macOS system is configured to enforce installation of XProtect Remediator and Gatekeeper updates automatically with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.SoftwareUpdate')\ .objectForKey('ConfigDataInstall').js EOS If the result is not "true", this is a finding.
Configure the macOS system to enforce installation of XProtect Remediator and Gatekeeper updates automatically by installing the "com.apple.SoftwareUpdate" configuration profile.
Verify the macOS system is configured to disable Genmoji with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowGenmoji').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable Genmoji by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable Apple Intelligence Image Generation with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowImagePlayground').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable Apple Intelligence Image Generation by installing the "com.apple.applicationaccess" configuration profile.
Verify the macOS system is configured to disable Apple Intelligence Writing Tools with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.applicationaccess')\ .objectForKey('allowWritingTools').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable Apple Intelligence Writing Tools by installing the "com.apple.applicationaccess" configuration profile.
Verify the operating system version. Click the Apple icon on the menu at the top left corner of the screen and select the "About This Mac" option. The name of the macOS release installed appears on the Overview tab in the resulting window. The precise version number installed is displayed below that. If the installed version of macOS 15 is not supported, this is a finding.
Upgrade to a supported version of the operating system.
Verify the macOS system is configured to display the contents of "/etc/banner" before granting access to the system with the following command: /usr/sbin/sshd -G | /usr/bin/grep -c "^banner /etc/banner" If the command does not return "1", this is a finding.
Configure the macOS system to display the contents of "/etc/banner" before granting access to the system with the following command: include_dir=$(/usr/bin/awk '/^Include/ {print $2}' /etc/ssh/sshd_config | /usr/bin/tr -d '*') if [[ -z $include_dir ]]; then /usr/bin/sed -i.bk "1s/.*/Include \/etc\/ssh\/sshd_config.d\/\*/" /etc/ssh/sshd_config fi /usr/bin/grep -qxF 'banner /etc/banner' "${include_dir}01-mscp-sshd.conf" 2>/dev/null || echo "banner /etc/banner" >> "${include_dir}01-mscp-sshd.conf" for file in $(ls ${include_dir}); do if [[ "$file" == "100-macos.conf" ]]; then continue fi if [[ "$file" == "01-mscp-sshd.conf" ]]; then break fi /bin/mv ${include_dir}${file} ${include_dir}20-${file} done
Verify the macOS system is configured to audit all failed program execution on the system with the following command: /usr/bin/awk -F':' '/^flags/ { print $NF }' /etc/security/audit_control | /usr/bin/tr ',' '\n' | /usr/bin/grep -Ec '\-ex' If the result is not "1", this is a finding.
Configure the macOS system to audit all failed program execution on the system with the following command: /usr/bin/grep -qE "^flags.*-ex" /etc/security/audit_control || /usr/bin/sed -i.bak '/^flags/ s/$/,-ex/' /etc/security/audit_control; /usr/sbin/audit -s
Verify the macOS system is configured without ACLs applied to audit_control with the following command: /bin/ls -le /etc/security/audit_control | /usr/bin/awk '{print $1}' | /usr/bin/grep -c ":" If the result is not "0", this is a finding.
Configure the macOS system without ACLs applied to audit_control with the following command: /bin/chmod -N /etc/security/audit_control
Verify the macOS system is configured to disable sending audio recordings and transcripts with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.Accessibility')\ .objectForKey('AXSAudioDonationSiriImprovementEnabled').js EOS If the result is not "false", this is a finding.
Configure the macOS system to disable sending audio recordings and transcripts by installing the "com.apple.accessibility" configuration profile.
Verify the macOS system is configured to disable sending search data from Spotlight with the following command: /usr/bin/osascript -l JavaScript << EOS $.NSUserDefaults.alloc.initWithSuiteName('com.apple.assistant.support')\ .objectForKey('Search Queries Data Sharing Status').js EOS If the result is not "2", this is a finding.
Configure the macOS system to disable sending search data from Spotlight by installing the "com.apple.assistant.support" configuration profile.