Email

Configure Secure Password Policy on Zimbra

Zimbra Collaboration Suite stores mailbox credentials in its internal LDAP directory. A weak password policy means accounts with short or simple passwords become easy targets for brute-force attacks and credential stuffing. Once an attacker owns a mailbox, they use it to relay spam, exfiltrate data, or pivot deeper into the network. Locking down the password policy is one of the first hardening steps on any production Zimbra deployment.

Original content from computingforgeeks.com - post 1950

This guide walks through every password-related attribute in Zimbra – minimum length, complexity rules, expiry, history, account lockout, per-COS overrides, forced resets, and auditing. All commands run as the zimbra user on the CLI using zmprov. The same settings are available in the Zimbra Administration Console under Class of Service, but CLI is faster and scriptable.

Prerequisites

  • A running Zimbra Collaboration Suite server (version 8.8.15 or 10.x)
  • Root or sudo access to the Zimbra server
  • SSH access to the server CLI
  • Basic familiarity with zmprov – the Zimbra provisioning command-line tool

All commands below should be run as the zimbra user. Switch to it first:

sudo su - zimbra

Step 1: Check the Current Password Policy

Before changing anything, dump the current password settings from the default Class of Service. This shows what Zimbra enforces out of the box.

zmprov gc default | grep -i password

The output lists every password-related attribute and its current value:

zimbraFeatureChangePasswordEnabled: TRUE
zimbraPasswordEnforceHistory: 0
zimbraPasswordLocked: FALSE
zimbraPasswordLockoutDuration: 1h
zimbraPasswordLockoutEnabled: FALSE
zimbraPasswordLockoutFailureLifetime: 1h
zimbraPasswordLockoutMaxFailures: 10
zimbraPasswordMaxAge: 0
zimbraPasswordMaxLength: 64
zimbraPasswordMinAge: 0
zimbraPasswordMinAlphaChars: 0
zimbraPasswordMinDigitsOrPuncs: 0
zimbraPasswordMinLength: 6
zimbraPasswordMinLowerCaseChars: 0
zimbraPasswordMinNumericChars: 0
zimbraPasswordMinPunctuationChars: 0
zimbraPasswordMinUpperCaseChars: 0

The defaults are weak – a 6-character password with no complexity requirements, no expiry, no lockout, and no history enforcement. Every one of these needs tightening on a production mail server.

Step 2: Set Minimum Password Length

Short passwords are the easiest to crack. Set the minimum length to at least 10 characters. This single change blocks most dictionary attacks.

zmprov mc default zimbraPasswordMinLength 10

Verify the change took effect:

zmprov gc default zimbraPasswordMinLength

The output confirms the new minimum length:

zimbraPasswordMinLength: 10

Users with existing passwords shorter than 10 characters will not be locked out, but they will be required to meet the new minimum when they change their password next time.

Step 3: Require Password Complexity

Length alone is not enough. Force passwords to include a mix of character types – uppercase, lowercase, numbers, and special characters. This prevents users from setting aaaaaaaaaa as a valid 10-character password.

zmprov mc default zimbraPasswordMinUpperCaseChars 1
zmprov mc default zimbraPasswordMinLowerCaseChars 1
zmprov mc default zimbraPasswordMinNumericChars 1
zmprov mc default zimbraPasswordMinPunctuationChars 1

You can also enforce a combined minimum of digits and punctuation characters with a single attribute:

zmprov mc default zimbraPasswordMinDigitsOrPuncs 2

Confirm all complexity settings are applied:

zmprov gc default | grep -i "zimbraPasswordMin"

The output should show all the updated values:

zimbraPasswordMinAge: 0
zimbraPasswordMinAlphaChars: 0
zimbraPasswordMinDigitsOrPuncs: 2
zimbraPasswordMinLength: 10
zimbraPasswordMinLowerCaseChars: 1
zimbraPasswordMinNumericChars: 1
zimbraPasswordMinPunctuationChars: 1
zimbraPasswordMinUpperCaseChars: 1

With these settings, a valid password must be at least 10 characters long and contain at least one uppercase letter, one lowercase letter, one number, and one special character.

Step 4: Set Password Expiry with zimbraPasswordMaxAge

Password expiry forces users to rotate their credentials regularly. The zimbraPasswordMaxAge attribute sets the maximum number of days a password remains valid. A value of 0 means passwords never expire, which is the default.

Set passwords to expire every 90 days:

zmprov mc default zimbraPasswordMaxAge 90

You can also set a minimum age to prevent users from quickly cycling through passwords to reuse an old one:

zmprov mc default zimbraPasswordMinAge 1

This requires at least 1 day between password changes. Combined with password history (next step), it effectively blocks users from resetting back to a previous password within the same session.

Step 5: Enforce Password History

Password history prevents users from reusing recent passwords. When users rotate a password, they often just toggle between two favorites. The zimbraPasswordEnforceHistory attribute stores the number of previous passwords to remember.

Set history to remember the last 10 passwords:

zmprov mc default zimbraPasswordEnforceHistory 10

Verify the setting:

zmprov gc default zimbraPasswordEnforceHistory

Expected output showing history is enabled:

zimbraPasswordEnforceHistory: 10

Now if a user tries to set a password they have used within the last 10 changes, Zimbra will reject it.

Step 6: Configure Account Lockout Policy

Account lockout protects against brute-force login attempts. By default, Zimbra has lockout disabled. You need to enable it and set thresholds for failed attempts, lockout duration, and the failure counting window.

Enable lockout and set it to lock accounts after 5 failed attempts:

zmprov mc default zimbraPasswordLockoutEnabled TRUE
zmprov mc default zimbraPasswordLockoutMaxFailures 5
zmprov mc default zimbraPasswordLockoutDuration 30m
zmprov mc default zimbraPasswordLockoutFailureLifetime 1h

Here is what each attribute does:

  • zimbraPasswordLockoutEnabled – activates the lockout mechanism
  • zimbraPasswordLockoutMaxFailures – number of failed attempts before lockout (set to 5)
  • zimbraPasswordLockoutDuration – how long the account stays locked (30 minutes). Set to 0 to lock permanently until an admin unlocks it
  • zimbraPasswordLockoutFailureLifetime – the time window for counting failures. If a user fails 3 times, waits 2 hours (beyond the 1h window), and fails again, the counter resets

Verify the lockout configuration:

zmprov gc default | grep -i "zimbraPasswordLockout"

All lockout attributes should reflect the new values:

zimbraPasswordLockoutDuration: 30m
zimbraPasswordLockoutEnabled: TRUE
zimbraPasswordLockoutFailureLifetime: 1h
zimbraPasswordLockoutMaxFailures: 5

If an account gets locked out, an administrator can manually unlock it from the CLI. To check if a specific account is currently locked:

zmprov ga [email protected] zimbraAccountStatus zimbraPasswordLockoutLockedTime

To unlock a locked account:

zmprov ma [email protected] zimbraAccountStatus active zimbraPasswordLockoutLockedTime ""

Step 7: Set Per-COS Password Policies

Zimbra uses Class of Service (COS) to group accounts with shared settings. The default COS applies to all accounts unless overridden. In production, you might need different password policies for different groups – stricter rules for administrators, relaxed rules for service accounts or distribution list owners.

First, list all Classes of Service on the server:

zmprov gac

Typical output shows the available COS names:

default
defaultExternal

Create a new COS for administrators with stricter password requirements:

zmprov cc admin_cos zimbraPasswordMinLength 14 zimbraPasswordMinUpperCaseChars 2 zimbraPasswordMinNumericChars 2 zimbraPasswordMinPunctuationChars 2 zimbraPasswordMaxAge 60 zimbraPasswordEnforceHistory 15 zimbraPasswordLockoutEnabled TRUE zimbraPasswordLockoutMaxFailures 3

Assign an account to this stricter COS:

zmprov ma [email protected] zimbraCOSId $(zmprov gc admin_cos zimbraId | awk '{print $2}')

Verify the account is now using the new COS:

zmprov ga [email protected] zimbraCOSId

To modify the defaultExternal COS for external or partner accounts with a different policy:

zmprov mc defaultExternal zimbraPasswordMinLength 12 zimbraPasswordMaxAge 60 zimbraPasswordLockoutEnabled TRUE zimbraPasswordLockoutMaxFailures 5

Step 8: Force Password Change at Next Login

When onboarding new users or after a security incident, you may need to force specific accounts to change their password on next login. Zimbra provides the zimbraPasswordMustChange attribute for this.

Force a single user to change their password at next login:

zmprov ma [email protected] zimbraPasswordMustChange TRUE

To force all accounts in a domain to reset their passwords, loop through the account list:

for user in $(zmprov -l gaa example.com); do
  zmprov ma "$user" zimbraPasswordMustChange TRUE
done

Verify the flag is set on a specific account:

zmprov ga [email protected] zimbraPasswordMustChange

The output shows the current state of the attribute:

zimbraPasswordMustChange: TRUE

Once the user logs in and changes their password, Zimbra automatically sets this attribute back to FALSE.

Step 9: Audit Weak Passwords on Zimbra

After tightening the policy, existing accounts still have their old weak passwords until they rotate. You cannot decrypt stored passwords (they are hashed), but you can identify accounts that have not changed their password since the policy update.

Check the last password change date for all accounts in a domain:

for user in $(zmprov -l gaa example.com); do
  echo -n "$user: "
  zmprov ga "$user" zimbraPasswordModifiedTime | grep zimbraPasswordModifiedTime
done

The output shows each account and when their password was last changed:

[email protected]: zimbraPasswordModifiedTime: 20260115103022Z
[email protected]: zimbraPasswordModifiedTime: 20250801142315Z
[email protected]: zimbraPasswordModifiedTime: 20240312091205Z

Accounts with old zimbraPasswordModifiedTime values have not rotated their password under the new policy. You can force those accounts to change their password using the method from Step 8.

To list accounts where the password is currently locked (due to too many failed attempts):

for user in $(zmprov -l gaa example.com); do
  locktime=$(zmprov ga "$user" zimbraPasswordLockoutLockedTime | grep zimbraPasswordLockoutLockedTime | awk '{print $2}')
  if [ -n "$locktime" ]; then
    echo "LOCKED: $user (since $locktime)"
  fi
done

This helps you spot accounts that are under active brute-force attack or users who have simply forgotten their credentials.

Zimbra Password Attributes Reference

The table below lists all password-related attributes in Zimbra, their purpose, and recommended production values.

AttributeDescriptionRecommended Value
zimbraPasswordMinLengthMinimum number of characters required10
zimbraPasswordMaxLengthMaximum password length allowed64 (default)
zimbraPasswordMinUpperCaseCharsMinimum uppercase letters required1
zimbraPasswordMinLowerCaseCharsMinimum lowercase letters required1
zimbraPasswordMinNumericCharsMinimum numeric digits required1
zimbraPasswordMinPunctuationCharsMinimum special characters required1
zimbraPasswordMinDigitsOrPuncsCombined minimum of digits and special characters2
zimbraPasswordMinAlphaCharsMinimum alphabetic characters required0 (default)
zimbraPasswordMaxAgeDays before password expires (0 = never)90
zimbraPasswordMinAgeMinimum days before password can be changed again1
zimbraPasswordEnforceHistoryNumber of previous passwords remembered10
zimbraPasswordLockoutEnabledEnable account lockout on failed attemptsTRUE
zimbraPasswordLockoutMaxFailuresFailed attempts before lockout5
zimbraPasswordLockoutDurationHow long the account stays locked30m
zimbraPasswordLockoutFailureLifetimeTime window for counting failed attempts1h
zimbraPasswordLockedPrevents user from changing their own passwordFALSE (default)
zimbraPasswordMustChangeForce password change at next loginPer-account basis
zimbraFeatureChangePasswordEnabledAllow users to change their own passwordTRUE (default)

Conclusion

You have configured a complete password policy on Zimbra covering minimum length, complexity requirements, expiry, history, account lockout, per-COS overrides, forced resets, and auditing. These settings apply to all new password changes – existing weak passwords remain until users rotate them, so consider forcing a domain-wide reset after deploying the policy.

For additional hardening, enable TLS certificates on your Zimbra server, configure proper firewall rules for Zimbra services, and set up Amavis spam filtering whitelist and blacklist rules to protect your mail infrastructure from both external threats and compromised accounts.

Related Articles

Networking Installing pfSense Firewall on Proxmox Hetzner root server AlmaLinux Configure Master BIND DNS on Rocky Linux 9 / AlmaLinux 9 Containers Run Teleport in Docker Container using Docker Compose Security How to Use a VPN for Windows in 2024 for Secure Connection

Leave a Comment

Press ESC to close