Auditd ACLs
Enhance Zimbra Security with AuditD and ACLs
Auditd (Linux Audit Daemon) can be used to capture detailed information about file accesses, system calls, and user actions. Auditd provides administrators the ability to track changes and identify suspicious activities and potentially get an early warning on system compromise by hackers.
Adding Auditd to your system will give you more detailed logs, but it also increases the overall log volume, therefore it is recommended to enable this along with centralized logging with Elastic Stack. For details see the link in the further reading section.
Linux File System ACLs (Access Control Lists) provide a more flexible way of managing file permissions compared to the traditional chmod
and chown
commands. When creating new files and folders, Access Control Lists (ACLs) offer several benefits over traditional chmod and chown:
- Default Permissions for New Files and Directories: ACLs allow you to set default permissions for a directory, which means that any new file or subdirectory created within will automatically inherit those permissions. This is particularly useful when you want consistent access settings without manually modifying each new item.
- Fine-Grained Access Control: ACLs let you define permissions for specific users or groups beyond the file’s owner, group, and others. When new files or folders are created, the inherited ACL settings can grant access to multiple users directly, avoiding the limitations of the traditional
chmod
mechanism that can only specify one owner and one group.
Setting up ACLs on Zimbra (beta)
Zimbra engineering is currently investigating the use of ACLs and these will hopefully be added to an upcoming patch soon. That said you can already try out ACLs to enhance security on Zimbra.
Create a new empty file /usr/local/sbin/zmacl_beta
with the following contents:
#!/bin/bash # Function to check if the script is run as root check_if_root() { if [ "$EUID" -ne 0 ]; then echo "Error: This script must be run as root." exit 1 fi } # Function to check if setfacl is installed check_setfacl_installed() { if ! command -v setfacl &> /dev/null; then echo "Error: 'setfacl' command not found." if [ -f /etc/debian_version ]; then echo "To install 'setfacl' on Ubuntu/Debian, run: sudo apt install acl" elif [ -f /etc/redhat-release ]; then echo "To install 'setfacl' on RedHat/CentOS/Fedora, run: sudo yum install acl" else echo "Please install 'acl' package using your distribution's package manager." fi exit 1 fi } # Check if acl argument is passed if [ "$#" -ne 1 ]; then echo "Usage: $0 [enable|disable]" exit 1 fi ACL_ACTION="$1" # Directories to apply ACLs to DIRS=( "/opt/zimbra/jetty/webapps/zimbraAdmin/public/" "/opt/zimbra/jetty/webapps/zimbra/public/" ) # Function to enable ACLs (deny write access) enable_acls() { for DIR in "${DIRS[@]}"; do echo "Setting ownership and base permissions" chown zimbra:zimbra -R "$DIR" chmod ugo-w -R "$DIR" echo "Applying write deny ACLs to $DIR" # Deny write access for everyone except root and zimbra setfacl -R -m u::r-x "$DIR" # Owner has read/execute setfacl -R -m u:zimbra:r-x "$DIR" # zimbra user has read/execute setfacl -R -m g::r-x "$DIR" # Group has read/execute setfacl -R -m o::r-x "$DIR" # Others have read/execute # Ensure these ACLs are the default for new files and directories setfacl -dR -m u::r-x "$DIR" setfacl -dR -m u:zimbra:r-x "$DIR" setfacl -dR -m g::r-x "$DIR" setfacl -dR -m o::r-x "$DIR" echo "ACLs applied successfully to $DIR" done } # Function to disable ACLs (remove all setfacl entries) disable_acls() { for DIR in "${DIRS[@]}"; do echo "Setting ownership and base permissions" chown zimbra:zimbra -R "$DIR" chmod go-w -R "$DIR" chmod u+w -R "$DIR" echo "Removing ACLs from $DIR" # Remove ACLs recursively setfacl -R -b "$DIR" setfacl -dR -b "$DIR" # Remove default ACLs echo "ACLs removed successfully from $DIR" done } # Main script logic check_if_root # Check if the script is run as root check_setfacl_installed # Check if setfacl is installed case "$ACL_ACTION" in enable) enable_acls ;; disable) disable_acls ;; *) echo "Invalid argument. Use 'enable' or 'disable'." exit 1 ;; esac
Next allow the script to be executed, as the user root
execute:
chmod +x /usr/local/sbin/zmacl_beta
Then you can enable ACLs on by running the script as root
:
/usr/local/sbin/zmacl_beta enable
The ACLs will prevent writes by the user zimbra
to the public folders in Jetty. This provides a significant security enhancement, however it will also prevent functionality such as the Client Uploader to work from the Admin Console UI, but it is already recommended to remove this Zimlet as follows:
As the user root
run:
rm -Rf /opt/zimbra/lib/ext/com_zimbra_clientuploader
As the user zimbra
run:
zmzimletctl undeploy com_zimbra_clientuploader zmmailboxdctl restart
Enhance Zimbra server logging with AuditD
Now that we have enabled ACLs we can use Auditd to monitor failed write attempts to the Jetty public folders.
Create a script /root/install-auditd
with the following contents:
#!/bin/bash WHO=`whoami` if [ $WHO != "root" ] then echo echo "Execute this script as root (\"su\")" echo exit 1 fi # Function to check if the kernel is tainted check_kernel_taint() { echo "Checking if the kernel is tainted..." taint=$(cat /proc/sys/kernel/tainted) if [ "$taint" != "0" ]; then echo "WARNING: The kernel is tainted. This can indicate hardware issues or non-standard kernel modules." echo "Do you wish to continue? (yes/no)" read response if [[ "$response" != "yes" ]]; then echo "Installation aborted." exit 1 fi else echo "Kernel is not tainted. Proceeding with installation." fi } # Function to remove existing audit rules remove_existing_audit_rules() { echo "Removing existing audit rules..." auditctl -D } # Function to install auditd based on the OS type install_auditd() { if [ -f /etc/redhat-release ]; then # RedHat-based systems echo "Detected RedHat-based system." yum install -y audit elif [ -f /etc/lsb-release ]; then # Ubuntu-based systems echo "Detected Ubuntu-based system." apt update apt install -y auditd else echo "Unsupported OS. Exiting." exit 1 fi } # Function to add audit rules add_audit_rules() { echo "Adding audit rules..." rm -f /etc/audit/rules.d/audit.rules cat >> /etc/audit/rules.d/audit.rules << EOF # This file contains the auditctl rules that are loaded # whenever the audit daemon is started via the initscripts. # The rules are simply the parameters that would be passed # to auditctl. # First rule - delete all -D # Increase the buffers to survive stress events. # Make this bigger for busy systems -b 8192 # Feel free to add below this line. See auditctl man page -w /bin/sh -p x -k rce -w /bin/bash -p x -k rce -w /usr/bin/wget -p x -k rce -w /usr/bin/curl -p x -k rce -w /usr/bin/python -p x -k rce -w /bin/dash -p x -k rce # New rule to monitor write attempts in Zimbra webapps directory -w /opt/zimbra/jetty/webapps -p wa -k webapps_write_attempts EOF } # Function to add the execve syscall auditing rule add_execve_rule() { echo "Adding execve syscall audit rule..." auditctl -a always,exit -F arch=b64 -S execve -k rce } # Run the functions check_kernel_taint remove_existing_audit_rules install_auditd add_audit_rules add_execve_rule # Reload auditd to apply the new rules echo "Reloading auditd to apply the rules..." systemctl restart auditd echo "Auditd setup complete." echo "You can track events using:" echo "ausearch -k rce" echo "tail -f /var/log/audit/audit.log | grep rce"
Install Auditd using the script by running as root:
chmod +x /root/install-auditd /root/install-auditd
Auditd logs into /var/log/audit/audit.log
. Again consider setting up RSyslog remote logging. Here is an example log line of what a failed write attempt would look like in the Jetty public folder:
type=SYSCALL msg=audit(1727443142.767:1275): arch=c000003e syscall=257 success=no exit=-13 a0=ffffff9c a1=7ffe14bea566 a2=941 a3=1b6 items=1 ppid=25529 pid=30908 auid=0 uid=998 gid=998 euid=998 suid=998 fsuid=998 egid=998 sgid=998 fsgid=998 tty=pts1 ses=21 comm="touch" exe="/usr/bin/touch" subj=unconfined key="webapps_write_attempts"ARCH=x86_64 SYSCALL=openat AUID="root" UID="zimbra" GID="zimbra" EUID="zimbra" SUID="zimbra" FSUID="zimbra" EGID="zimbra" SGID="zimbra" FSGID="zimbra" type=CWD msg=audit(1727443142.767:1275): cwd="/opt/zimbra/jetty_base/webapps/zimbra/public" type=PATH msg=audit(1727443142.767:1275): item=0 name="/opt/zimbra/jetty_base/webapps/zimbra/public" inode=547990 dev=fc:02 mode=040555 ouid=998 ogid=998 rdev=00:00 nametype=PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="zimbra" OGID="zimbra" type=PROCTITLE msg=audit(1727443142.767:1275): proctitle=746F7563680075726674
Auditd is safe to install on Zimbra, the ACLs are currently being investigated by Zimbra engineering. For now ACLs do not seem to cause issues on a running Zimbra set-up. Rebooting etc. works normally. But patch updates and upgrades still need to be investigated.
You can disable ACLs if needed by running:
/usr/local/sbin/zmacl_beta disable