def configure_pam(): """5.3 Configure PAM""" try: Package('libpam-pwquality').install() PropertyFile('/etc/ssh/sshd_config', ' ').override({ 'password requisite': 'pam_pwquality.so retry=3' }).write() PropertyFile('/etc/security/pwquality.conf', '=').override({ 'minlen': '14', 'dcredit': '-1', 'ucredit': '-1', 'ocredit': '-1', 'lcredit': '-1', }).write() #"""5.3.2 Ensure lockout for failed password attempts is configured """ PropertyFile('/etc/ssh/sshd_config', ' ').override({ 'auth required': 'pam_tally2.so onerr=fail audit silent deny=5 unlock_time=900' }).write() #"""5.3.3 Ensure password reuse is limited""" PropertyFile('/etc/ssh/sshd_config', ' ').override({ 'password required': 'pam_pwhistory.so remember=5' }).write() #"""5.3.4 Ensure password hashing algorithm is SHA-512 """ PropertyFile('/etc/ssh/sshd_config', ' ').override({ 'password': '******' }).write() except Exception, e: logging.error('Error when attemp to execute 5.3.configure_pam()', exc_info=True)
def configure_rsyslog(): """4.2.1 Configure rsyslog""" try: Package('rsyslog').install() Service('rsyslog').enable() PropertyFile('/etc/rsyslog.conf', ' ').override({ '*.emerg': ':omusrmsg:*', 'mail.*': '-/var/log/mail', 'mail.info': '-/var/log/mail.info', 'mail.warning': '-/var/log/mail.warn', 'mail.err': '/var/log/mail.err', 'news.crit': '-/var/log/news/news.crit', 'news.err': '-/var/log/news/news.err', 'news.notice': '-/var/log/news/news.notice', '*.=warning;*.=err': '-/var/log/warn', '*.crit': '/var/log/warn', '*.*;mail.none;news.none': '-/var/log/messages', 'local0,local1.*': '-/var/log/localmessages', 'local2,local3.*': '-/var/log/localmessages', 'local4,local5.*': '-/var/log/localmessages', 'local6,local7.*': '-/var/log/localmessages ', '$FileCreateMode': '0640' }).write() exec_shell('pkill -HUP rsyslogd') ##reload rsyslogd #"""4.2.1.4 Ensure rsyslog is configured to send logs to a remote log host""" #"""4.2.1.5 Ensure remote rsyslog messages are only accepted on designated log hosts. """ PropertyFile('/etc/rsyslog.conf', ' ').override({ '$ModLoad': 'imtcp', '$InputTCPServerRun': '514' }).write() exec_shell('pkill -HUP rsyslogd') ##reload rsyslogd except Exception, e: logging.error('Error when attemp to execute 4.2.1.configure_rsyslog()', exc_info=True)
def mandatory_access_control(): """1.6.""" #1.6.1.1- """result = '' with open('/etc/default/grub') as f: if 'selinux=0'|'enforcing=0' in f.read: result = 'miss'""" #1.6.1.2 try: PropertyFile('/etc/selinux/config', '=').override({ 'SELINUX':'enforcing' }).write() #1.6.1.3 PropertyFile('/etc/selinux/config', '=').override({ 'SELINUXTYPE':'ubuntu' }).write() #1.6.1.4 #1.6.2.2 exec_shell([ 'aa-enforce /etc/apparmor.d/*' ]) #1.6.3 exec_shell([ 'apt-get install selinux', 'apt-get install apparmor' ]) except Exception, e: logging.error('Error when attemp to execute 1.6.mandatory_access_control()', exc_info=True)
def configure_sshd(): """5.2 SSH Server Configuration""" try: # 5.2.1 Ensure permissions on /etc/ssh/sshd_config are configured exec_shell([ 'chown root:root /etc/ssh/sshd_config', 'chmod og-rwx /etc/ssh/sshd_config' ]) # 5.2.2 - 5.2.15 PropertyFile('/etc/ssh/sshd_config', ' ').override({ 'Protocol': '2', 'LogLevel': 'INFO', 'X11Forwarding': 'no', 'MaxAuthTries': '4', 'IgnoreRhosts': 'yes', 'HostbasedAuthentication': 'no', 'PermitRootLogin': '******', 'PermitEmptyPasswords': 'no', 'PermitUserEnvironment': 'no', 'MACs': '[email protected],[email protected],[email protected],hmac-sha2-512,hmac-sha2-256,[email protected]', 'ClientAliveInterval': '300', 'ClientAliveCountMax': '0', 'LoginGraceTime': '60', #AllowUsers <userlist> #AllowGroups <grouplist> #DenyUsers <userlist> #DenyGroups <grouplist> 'Banner': '/etc/issue.net' }).write() except Exception, e: logging.error('Error when attemp to execute 5.2.configure_sshd()', exc_info=True)
def configure_ipv6_params(): """3.3 IPv6""" try: PropertyFile('/etc/sysctl.conf', ' = ').override({ 'net.ipv6.conf.all.accept_ra': '0', 'net.ipv6.conf.default.accept_ra': '0', 'net.ipv6.conf.all.accept_redirects': '0', 'net.ipv6.conf.default.accept_redirects': '0' }).write() # 3.3.3 Ensure IPv6 is disabled PropertyFile('etc/default/grub', '=').override({ 'GRUB_CMDLINE_LINUX': '"ipv6.disable=1"' }).write() except Exception, e: logging.error('Error when attemp to execute 3.3.configure_ipv6_params()', exc_info=True)
def configure_host_network_params(): """3.1 Network Parameters(Host Only)""" try: PropertyFile('/etc/sysctl.conf', ' = ').override({ 'net.ipv4.ip_forward': '0', 'net.ipv4.conf.all.send_redirects': '0', 'net.ipv4.conf.default.send_redirects': '0', }).write() except Exception, e: logging.error('Error when attemp to execute 3.1.configure_host_network_params()', exc_info=True)
def configure_mta(): """2.2.15 Ensure mail transfer agent is configured for local - only mode""" try: PropertyFile('/etc/postfix/main.cf', ' = ').override({ 'inet_interfaces': 'loopback-only' }).write() Service('postfix').restart() except Exception, e: logging.error('Error when attemp to execute 2.2.15.configure_mta()', exc_info=True)
def configure_ntp(upstream): """2.2.1 Time Synchronization""" try: # 2.2.1.1 Ensure time synchronization is in use Package('chrony').remove() Package('ntp').install() # 2.2.1.2 Ensure ntp is configured PropertyFile('/etc/ntp.conf', ' ').override({ 'restrict default': None, 'restrict -4 default': 'kod nomodify notrap nopeer noquery', 'restrict -6 default': 'kod nomodify notrap nopeer noquery', 'server': upstream }).write() PropertyFile('/etc/init.d/ntp', '=').override({ 'RUNASUSER': '******' }).write() except Exception, e: logging.error('Error when attemp to execute 2.2.1.configure_ntp()', exc_info=True)
def apply_process_hardenings(): """1.5""" # 1.5.1 try: PropertyFile('/etc/security/limits.conf', '').override({ '* hard core':'0' }).write() PropertyFile('/etc/sysctl.conf', '=').override({ 'fs.suid_dumpable':'0' }).write() # 1.5.3 Ensure ASLD is enable PropertyFile('/etc/sysctl.conf', ' = ').override({ 'kernel.randomize_va_space': '2' }).write() # 1.5.4 Ensure prelink is disable Package('prelink').remove() except Exception, e: logging.error('Error when attemp to execute 1.5.apply_process_hardenings()', exc_info=True)
def configure_chrony(upstream): """2.2.1 Time Synchronization""" try: # 2.2.1.1 Ensure time synchronization is in use Package('ntp').remove() Package('chrony').install() # 2.2.1.3 Ensure chrony is configured PropertyFile('/etc/chrony/chrony.conf', ' ').override({ 'server': upstream }).write() except Exception, e: logging.error('Error when attemp to execute 2.2.1.configure_chrony()', exc_info=True)
def configure_password_parmas(): """5.4 User Accounts and Environment""" try: PropertyFile('/etc/login.defs', '\t').override({ 'PASS_MAX_DAYS': '90', 'PASS_MIN_DAYS': '7', 'PASS_WARN_AGE': '7' }).write() exec_shell([ 'useradd -D -f 30' ]) #"""5.4.2 Ensure system accounts are non-login""" #"""5.4.3 Ensure default group for the root account is GID 0 """ exec_shell([ 'usermod -g 0 root' ]) except Exception, e: logging.error('Error when attemp to execute 5.4.configure_password_parmas()', exc_info=True)
def configure_network_params(): """3.2 Network Parameters(Host and Router)""" try: PropertyFile('/etc/sysctl.conf', ' = ').override({ 'net.ipv4.conf.all.accept_source_route': '0', 'net.ipv4.conf.default.accept_source_route': '0', 'net.ipv4.conf.all.accept_redirects': '0', 'net.ipv4.conf.default.accept_redirects': '0', 'net.ipv4.conf.all.secure_redirects': '0', 'net.ipv4.conf.default.secure_redirects': '0', 'net.ipv4.conf.all.log_martians': '1', 'net.ipv4.conf.default.log_martians': '1', 'net.ipv4.icmp_echo_ignore_broadcasts': '1', 'net.ipv4.icmp_ignore_bogus_error_responses': '1', 'net.ipv4.conf.all.rp_filter': '1', 'net.ipv4.conf.default.rp_filter': '1', 'net.ipv4.tcp_syncookies': '1' }).write() except Exception, e: logging.error('Error when attemp to execute 3.2.configure_host_network_params()', exc_info=True)
def configure_log(): """4.1.1.1 Ensure audit log storage size is configured""" try: max_log = 10 PropertyFile('/etc/audit/auditd.conf', ' = ').override({ 'max_log_file': max_log }).write() #"""4.1.1.2 Ensure system is disabled when audit logs are full""" PropertyFile('/etc/sysctl.conf', ' = ').override({ 'space_left_action': 'email', 'action_mail_acct': 'root', 'admin_space_left_action': 'halt', 'max_log_file_action': 'keep_logs' }).write() #"""4.1.2 Ensure auditd service is enabled""" Service('auditd').enable() #"""4.1.3 Ensure auditing for processes that start prior to auditd is enabled""" PropertyFile('/etc/default/grub', ' = ').override({ 'GRUB_CMDLINE_LINUX': '"audit=1"' }).write() exec_shell('update-grub') #"""4.1.4 Ensure events that modify date and time information are collected """ #for 64bit arch. If 32bit please remove line contant arch=b32 rules_time = [ '-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time-change', '-a always,exit -F arch=b32 -S adjtimex -S settimeofday -S stime -k time-change', '-a always,exit -F arch=b64 -S clock_settime -k time-change', '-a always,exit -F arch=b32 -S clock_settime -k time-change', '-w /etc/localtime -p wa -k time-change' ] File('/etc/audit/audit.rules').write('{}').format(rules_time) #"""4.1.5 Ensure events that modify user/group information are collected """ rules_user = [ '-w /etc/group -p wa -k identity', '-w /etc/passwd -p wa -k identity', '-w /etc/gshadow -p wa -k identity', '-w /etc/shadow -p wa -k identity', '-w /etc/security/opasswd -p wa -k identity' ] File('/etc/audit/audit.rules').write('{}').format(rules_user) #"""4.1.6 Ensure events that modify the system's network environment are collected""" #for 64bit arch. If 32bit please remove line contant arch=b32 rules_network = [ '-a always,exit -F arch=b64 -S sethostname -S setdomainname -k system-locale', '-a always,exit -F arch=b32 -S sethostname -S setdomainname -k system-locale', '-w /etc/issue -p wa -k system-locale', '-w /etc/issue.net -p wa -k system-locale', '-w /etc/hosts -p wa -k system-locale', '-w /etc/network -p wa -k system-locale' ] File('/etc/audit/audit.rules').write('{}').format(rules_network) #"""4.1.7 Ensure events that modify the system's Mandatory Access Controls are collected """ rules_sys_mandatory = [ '-w /etc/selinux/ -p wa -k MAC-policy', '-w /usr/share/selinux/ -p wa -k MAC-policy' ] File('/etc/audit/audit.rules').write('{}').format(rules_sys_mandatory) #"""4.1.8 Ensure login and logout events are collected (Scored)""" rules_login_logout = [ '-w /var/log/faillog -p wa -k logins', '-w /var/log/lastlog -p wa -k logins', '-w /var/log/tallylog -p wa -k logins' ] File('/etc/audit/audit.rules').write('{}').format(rules_login_logout) #"""4.1.9 Ensure session initiation information is collected """ rules_session = [ '-w /var/run/utmp-p wa -k session', '-w /var/log/wtmp -p wa -k logins', '-w /var/log/btmp -p wa -k logins' ] File('/etc/audit/audit.rules').write('{}').format(rules_session) #"""4.1.10 Ensure discretionary access control permission modification events are collected """ #for 64bit arch. If 32bit please remove line contant arch=b32 rules_permission_modify = [ '-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -F auid>=1000 -F auid!=4294967295 -k perm_mod', '-a always,exit -F arch=b32 -S chmod -S fchmod -S fchmodat -F auid>=1000 -F auid!=4294967295 -k perm_mod', '-a always,exit -F arch=b64 -S chown -S fchown -S fchownat -S lchown -F auid>=1000 -F auid!=4294967295 -k perm_mod', '-a always,exit -F arch=b32 -S chown -S fchown -S fchownat -S lchown -F auid>=1000 -F auid!=4294967295 -k perm_mod', '-a always,exit -F arch=b64 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>=1000 -F auid!=4294967295 -k perm_mod', '-a always,exit -F arch=b32 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>=1000 -F auid!=4294967295 -k perm_mod' ] File('/etc/audit/audit.rules').write('{}').format(rules_permission_modify) #"""4.1.11 Ensure unsuccessful unauthorized file access attempts are collected""" #for 64bit arch. If 32bit please remove line contant arch=b32 rules_auth_fail = [ '-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access', '-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access', '-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access', '-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access' ] File('/etc/audit/audit.rules').write('{}').format(rules_auth_fail) #"""4.1.12 Ensure use of privileged commands is collected""" #"""4.1.13 Ensure successful file system mounts are collected""" #for 64bit arch. If 32bit please remove line contant arch=b32 rules_mount= [ '-a always,exit -F arch=b64 -S mount -F auid>=1000 -F auid!=4294967295 -k mounts', '-a always,exit -F arch=b32 -S mount -F auid>=1000 -F auid!=4294967295 -k mounts' ] File('/etc/audit/audit.rules').write('{}').format(rules_mount) #"""4.1.14 Ensure file deletion events by users are collected """ #for 64bit arch. If 32bit please remove line contant arch=b32 rules_delete= [ '-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete', '-a always,exit -F arch=b32 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete' ] File('/etc/audit/audit.rules').write('{}').format(rules_delete) #"""4.1.15 Ensure changes to system administration scope (sudoers) is collected """ rules_sudoer = [ '-w /etc/sudoers -p wa -k scope', '-w /etc/sudoers.d/ -p wa -k scope' ] File('/etc/audit/audit.rules').write('{}').format(rules_sudoer) #"""4.1.16 Ensure system administrator actions (sudolog) are collected""" rules_sudolog = [ '-w /var/log/sudo.log -p wa -k actions' ] File('/etc/audit/audit.rules').write('{}').format(rules_sudolog) #"""4.1.17 Ensure kernel module loading and unloading is collected """ #for 64bit arch. If 32bit please replace arch=b64 by arch=b32 rules_kernel_module = [ '-w /sbin/insmod -p x -k modules', '-w /sbin/rmmod -p x -k modules', '-w /sbin/modprobe -p x -kmodules', '-a always,exit -F arch=b64 -S init_module -S delete_module -k modules' ] File('/etc/audit/audit.rules').write('{}').format(rules_kernel_module) #"""4.1.18 Ensure the audit configuration is immutable """ rules_audit_conf = [ '-e 2' ] File('/etc/audit/audit.rules').write('{}').format(rules_audit_conf) except Exception, e: logging.error('Error when attemp to execute 4.1.configure_log()', exc_info=True)