usnistgov / macos_security

macOS Security Compliance Project
Other
1.77k stars 200 forks source link

pwpolicy_account_lockout_enforce issues with Sonoma #311

Closed robertgendler closed 1 year ago

robertgendler commented 1 year ago

Discussed in https://github.com/usnistgov/macos_security/discussions/310

Originally posted by **danieldotweinert** September 28, 2023 Currently having this issue with the Sonoma compliance script...as you can see the output show it as 'yes' but includes a line break and extra yes which is causing the rule to fail and make the device non compliant. Any ideas? Thu Sep 28 19:58:14 UTC 2023 pwpolicy_account_lockout_enforce failed (Result: yes yes, Expected: {string: yes})
robertgendler commented 1 year ago

So I'm not able to reproduce this.

I created a baseline file with just the 1 rule. And it appears when I run with --check it spits it out correctly.

Are you setting an ODV value? Can you copy/paste your custom rule?

danieldotweinert commented 1 year ago

Config Profile settings: image

#####----- Rule: pwpolicy_account_lockout_enforce -----#####
## Addresses the following NIST 800-53 controls:
# * AC-7
rule_arch=""
if [[ "$arch" == "$rule_arch" ]] || [[ -z "$rule_arch" ]]; then
    #echo 'Running the command to check the settings for: pwpolicy_account_lockout_enforce ...' | tee -a "$audit_log"
    unset result_value
    result_value=$(/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 <= 10) {print "yes"} else {print "no"}}'
)
    # expected result {'string': 'yes'}

    # check to see if rule is exempt
    unset exempt
    unset exempt_reason

    exempt=$(/usr/bin/osascript -l JavaScript << EOS 2>/dev/null
ObjC.unwrap($.NSUserDefaults.alloc.initWithSuiteName('org.cis_lvl1-sonoma.audit.plist').objectForKey('pwpolicy_account_lockout_enforce'))["exempt"]
EOS
)
    exempt_reason=$(/usr/bin/osascript -l JavaScript << EOS 2>/dev/null
ObjC.unwrap($.NSUserDefaults.alloc.initWithSuiteName('org.cis_lvl1-sonoma.audit.plist').objectForKey('pwpolicy_account_lockout_enforce'))["exempt_reason"]
EOS
)

    if [[ $result_value == "yes" ]]; then
        echo "$(date -u) pwpolicy_account_lockout_enforce passed (Result: $result_value, Expected: "{'string': 'yes'}")" | /usr/bin/tee -a "$audit_log"
        /usr/bin/defaults write "$audit_plist" pwpolicy_account_lockout_enforce -dict-add finding -bool NO
        /usr/bin/logger "mSCP: cis_lvl1 - pwpolicy_account_lockout_enforce passed (Result: $result_value, Expected: "{'string': 'yes'}")"
    else
        if [[ ! $exempt == "1" ]] || [[ -z $exempt ]];then
            echo "$(date -u) pwpolicy_account_lockout_enforce failed (Result: $result_value, Expected: "{'string': 'yes'}")" | /usr/bin/tee -a "$audit_log"
            /usr/bin/defaults write "$audit_plist" pwpolicy_account_lockout_enforce -dict-add finding -bool YES
            /usr/bin/logger "mSCP: cis_lvl1 - pwpolicy_account_lockout_enforce failed (Result: $result_value, Expected: "{'string': 'yes'}")"
        else
            echo "$(date -u) pwpolicy_account_lockout_enforce failed (Result: $result_value, Expected: "{'string': 'yes'}") - Exemption Allowed (Reason: "$exempt_reason")" | /usr/bin/tee -a "$audit_log"
            /usr/bin/defaults write "$audit_plist" pwpolicy_account_lockout_enforce -dict-add finding -bool YES
            /usr/bin/logger "mSCP: cis_lvl1 - pwpolicy_account_lockout_enforce failed (Result: $result_value, Expected: "{'string': 'yes'}") - Exemption Allowed (Reason: "$exempt_reason")"
            /bin/sleep 1
        fi
    fi

else
    echo "$(date -u) pwpolicy_account_lockout_enforce does not apply to this architechture" | tee -a "$audit_log"
    /usr/bin/defaults write "$audit_plist" pwpolicy_account_lockout_enforce -dict-add finding -bool NO
fi
danieldotweinert commented 1 year ago

Output from jamf logs:

image

brodjieski commented 1 year ago

Can you provide the output of sudo /usr/bin/pwpolicy -getaccountpolicies

danieldotweinert commented 1 year ago
Last login: Thu Sep 28 15:11:59 on ttys001
daniel.weinert@MAC-923G2F3 ~ % sudo /usr/bin/pwpolicy -getaccountpolicies
Password:
Getting global account policies
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>policyCategoryAuthentication</key>
    <array>
        <dict>
            <key>policyContent</key>
            <string>policyAttributeFailedAuthentications &lt; policyAttributeMaximumFailedAuthentications</string>
            <key>policyIdentifier</key>
            <string>ProfilePayload:2e42cfb6-c259-45c5-8660-39da3a427b55:maxFailedAttempts</string>
            <key>policyParameters</key>
            <dict>
                <key>policyAttributeMaximumFailedAuthentications</key>
                <integer>10</integer>
            </dict>
        </dict>
        <dict>
            <key>policyContent</key>
            <string>(policyAttributeFailedAuthentications &lt; policyAttributeMaximumFailedAuthentications) OR (policyAttributeCurrentTime &gt; (policyAttributeLastFailedAuthenticationTime + autoEnableInSeconds))</string>
            <key>policyIdentifier</key>
            <string>ProfilePayload:2e42cfb6-c259-45c5-8660-39da3a427b55:minutesUntilFailedLoginReset</string>
            <key>policyParameters</key>
            <dict>
                <key>autoEnableInSeconds</key>
                <integer>900</integer>
                <key>policyAttributeMaximumFailedAuthentications</key>
                <integer>10</integer>
            </dict>
        </dict>
    </array>
    <key>policyCategoryPasswordChange</key>
    <array>
        <dict>
            <key>policyContent</key>
            <string>policyAttributeCurrentTime &gt; policyAttributeLastPasswordChangeTime + (policyAttributeExpiresEveryNDays * 24 * 60 * 60)</string>
            <key>policyIdentifier</key>
            <string>ProfilePayload:2e42cfb6-c259-45c5-8660-39da3a427b55:maxPINAgeInDays</string>
            <key>policyParameters</key>
            <dict>
                <key>policyAttributeExpiresEveryNDays</key>
                <integer>365</integer>
            </dict>
        </dict>
    </array>
    <key>policyCategoryPasswordContent</key>
    <array>
        <dict>
            <key>policyContent</key>
            <string>none policyAttributePasswordHashes in policyAttributePasswordHistory</string>
            <key>policyContentDescription</key>
            <dict>
                <key>policyDefaultContentDescription</key>
                <string>Not be the same as the previous 15 passwords.</string>
            </dict>
            <key>policyIdentifier</key>
            <string>ProfilePayload:2e42cfb6-c259-45c5-8660-39da3a427b55:pinHistory</string>
            <key>policyParameters</key>
            <dict>
                <key>policyAttributePasswordHistoryDepth</key>
                <integer>15</integer>
            </dict>
        </dict>
        <dict>
            <key>policyContent</key>
            <string>policyAttributePassword matches '.{4,}+'</string>
            <key>policyContentDescription</key>
            <dict>
                <key>ar</key>
                <string>أدخل كلمة سر لا تقل عن أربعة أحرف أو رموز.</string>
                <key>ca</key>
                <string>Introdueix una contrasenya que tingui quatre caràcters o més.</string>
                <key>cs</key>
                <string>Zadejte heslo o minimální délce čtyři znaky.</string>
                <key>da</key>
                <string>Skriv en adgangskode på mindst fire tegn.</string>
                <key>de</key>
                <string>Gib ein Passwort ein, das aus mindestens vier Zeichen besteht.</string>
                <key>el</key>
                <string>Εισαγάγετε ένα συνθηματικό που περιέχει τέσσερις ή περισσότερους χαρακτήρες.</string>
                <key>en</key>
                <string>Enter a password that is four characters or more.</string>
                <key>en_AU</key>
                <string>Enter a password that is four characters or more.</string>
                <key>en_GB</key>
                <string>Enter a password that is four characters or more.</string>
                <key>es</key>
                <string>Introduce una contraseña que tenga como mínimo cuatro caracteres.</string>
                <key>es_419</key>
                <string>Ingresa una contraseña de cuatro caracteres o más.</string>
                <key>fi</key>
                <string>Kirjoita salasana, jossa on vähintään neljä merkkiä.</string>
                <key>fr</key>
                <string>Saisissez un mot de passe comportant au moins quatre caractères.</string>
                <key>fr_CA</key>
                <string>Saisissez un mot de passe comportant au moins quatre caractères.</string>
                <key>he</key>
                <string>יש להזין סיסמה בת ארבעה תווים או יותר.</string>
                <key>hi</key>
                <string>चार वर्णों वाला या उससे बड़ा पासवर्ड दर्ज करें।</string>
                <key>hr</key>
                <string>Unesite lozinku od četiri ili više znakova.</string>
                <key>hu</key>
                <string>Adjon meg egy legalább négy karakterből álló jelszót.</string>
                <key>id</key>
                <string>Masukkan kata sandi yang terdiri dari empat karakter atau lebih.</string>
                <key>it</key>
                <string>Inserisci una password di quattro o più caratteri.</string>
                <key>ja</key>
                <string>4文字以上のパスワードを入力してください。</string>
                <key>ko</key>
                <string>4자 이상의 암호를 입력하십시오.</string>
                <key>ms</key>
                <string>Masukkan kata laluan yang mengandungi empat atau lebih aksara.</string>
                <key>nl</key>
                <string>Voer een wachtwoord van vier of meer tekens in.</string>
                <key>no</key>
                <string>Angi et passord på minst fire tegn.</string>
                <key>pl</key>
                <string>Podaj hasło składające się z co najmniej czterech znaków.</string>
                <key>pt_BR</key>
                <string>Digite uma senha com quatro ou mais caracteres.</string>
                <key>pt_PT</key>
                <string>Digite uma palavra‑passe com pelo menos quatro caracteres.</string>
                <key>ro</key>
                <string>Introduceți o parolă de minimum patru caractere.</string>
                <key>ru</key>
                <string>Введите пароль, состоящий из четырех или более символов.</string>
                <key>sk</key>
                <string>Zadajte heslo obsahujúce najmenej štyri znaky.</string>
                <key>sv</key>
                <string>Ange ett lösenord som är minst fyra tecken långt.</string>
                <key>th</key>
                <string>ป้อนรหัสผ่านที่มีอักขระอย่างน้อยสี่ตัว</string>
                <key>tr</key>
                <string>En az dört karakter uzunluğunda bir parola girin.</string>
                <key>uk</key>
                <string>Введіть пароль зі щонайменше чотирьох символів.</string>
                <key>vi</key>
                <string>Nhập mật khẩu dài 4 ký tự trở lên.</string>
                <key>zh_CN</key>
                <string>输入不少于4个字符的密码。</string>
                <key>zh_HK</key>
                <string>輸入一個四位或更多字元的密碼。</string>
                <key>zh_TW</key>
                <string>輸入4個字元或更長的密碼。</string>
            </dict>
            <key>policyIdentifier</key>
            <string>com.apple.defaultpasswordpolicy.fde</string>
        </dict>
        <dict>
            <key>policyContent</key>
            <string>policyAttributePassword matches '.{8,}'</string>
            <key>policyContentDescription</key>
            <dict>
                <key>policyDefaultContentDescription</key>
                <string>Contain at least 8 characters.</string>
            </dict>
            <key>policyIdentifier</key>
            <string>ProfilePayload:2e42cfb6-c259-45c5-8660-39da3a427b55:minLength</string>
        </dict>
    </array>
</dict>
</plist>
brodjieski commented 1 year ago

Your password policy has policyAttributeMaximumFailedAuthentications defined twice. This is what is causing the issue. Try clearing your password policy and re-applying.

You can clear them by sudo pwpolicy -clearaccountpolicies.

danieldotweinert commented 1 year ago

Thanks @brodjieski and @robertgendler! That resolved my issue. Any idea why it populated twice?

brodjieski commented 1 year ago

When password policies are applied with a profile, they get written to pwpolicy, however when you remove a profile, it doesn't clean itself up. So depending on how you applied or removed profiles, old policies may still be in the mix.

robertgendler commented 1 year ago

Closing, since it's resolved.