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_cron(): """5.1 Configure cron""" try: # 5.1.1 Ensure cron daemon is enabled Service('crond').enable() # 5.1.2 - 5.1.8 exec_shell([ 'chown root:root /etc/crontab', 'chmod og-rwx /etc/crontab', 'chown root:root /etc/cron.hourly', 'chmod og-rwx /etc/cron.hourly', 'chown root:root /etc/cron.daily', 'chmod og-rwx /etc/cron.daily', 'chown root:root /etc/cron.weekly', 'chmod og-rwx /etc/cron.weekly', 'chown root:root /etc/cron.monthly', 'chmod og-rwx /etc/cron.monthly', 'chown root:root /etc/cron.d', 'chmod og-rwx /etc/cron.d', 'rm /etc/cron.deny', 'rm /etc/at.deny', 'touch /etc/cron.allow', 'touch /etc/at.allow', 'chmod og-rwx /etc/cron.allow', 'chmod og-rwx /etc/at.allow', 'chown root:root /etc/cron.allow', 'chown root:root /etc/at.allow' ]) except Exception, e: logging.error('Error when attemp to execute 5.1.configure_cron()', 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_su(): """5.6 Ensure access to the su command is restricted """ try: File('/etc/pam.d/su').write('auth required pam_wheel.so') exec_shell('usermod -aG wheel root') except Exception, e: logging.error('Error when attemp to execute 5.6.configure_su()', 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 disable_wireless_interface(wireless_interface): """3.7 Ensure wireless interfaces are disabled """ try: exec_shell([ 'ip link set {} down'.format(wireless_interface) ]) except Exception, e: logging.error('Error when attemp to execute 3.7.disable_wireless_interface()', exc_info=True)
def secure_boot_setting(): """1.4 Secure Boot Settings""" try: if os.path.isfile('/boot/grub/grub.cfg'): exec_shell([ 'chown root:root /boot/grub/grub.cfg', 'chmod og-rwx /boot/grub/grub.cfg' ]) except Exception, e: logging.error('Error when attemp to execute 1.4.secure_boot_setting()', exc_info=True)
def configure_tcp_wrappers(hosts): """3.4 TCP Wrappers""" try: # 3.4.1 Ensure TCP Wrappers is installed Package('tcpd').install() if hosts: # 3.4.2 Ensure /etc/hosts.allow is configured #Type host : <net>/<mask>. Ex: 192.168.1.0/255.255.255.0 allowed_hosts = ','.join(hosts) exec_shell('echo "ALL: {}" > /etc/hosts.allow'.format(allowed_hosts)) # 3.4.3 Ensure /etc/hosts.deny is configured exec_shell('echo "ALL: ALL" > /etc/hosts.deny') # 3.4.4 Ensure permissions on /etc/hosts.allow are configured exec_shell([ 'chown root:root /etc/hosts.allow', 'chmod 644 /etc/hosts.allow' ]) # 3.4.5 Ensure permissions on /etc/hosts.deny are configured exec_shell([ 'chown root:root /etc/hosts.deny', 'chmod 644 /etc/hosts.deny' ]) except Exception, e: logging.error('Error when attemp to execute 3.4.configure_tcp_wrappers()', exc_info=True)
def configure_syslog_ng(): try: #"""4.2.2 Configure syslog-ng""" Package('syslog-ng').install() exec_shell('update-rc.d syslog-ng enable') #"""4.2.2.3-4.2.2.5 Ensure syslog-ng default file permissions configured """ tmp= [ 'options { chain_hostnames(off); flush_lines(0); perm(0640); stats_freq(3600); threaded(yes); };', 'destination logserver { tcp("logfile.example.com" port(514)); };log { source(src); destination(logserver); };', 'source net{ tcp(); };destination remote { file("/var/log/remote/${FULLHOST}-log"); };log { source(net); destination(remote); };' ] File('/etc/syslog-ng/syslog-ng.conf').write('{}').format(tmp) except Exception, e: logging.error('Error when attemp to execute 4.2.2-5.configure_syslog_ng()', 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_permit_sensitive_file(): """6. System Maintenance""" try: #"""6.1.2 - 6.1.9""" exec_shell([ 'chown root:root /etc/passwd', 'chmod 644 /etc/passwd', 'chown root:shadow /etc/shadow', 'chmod o-rwx,g-wx /etc/shadow', 'chown root:root /etc/group', 'chmod 644 /etc/group', 'chown root:shadow /etc/gshadow', 'chmod o-rwx,g-rw /etc/gshadow', 'chown root:root /etc/passwd-', 'chmod u-x,go-wx /etc/passwd-', 'chown root:shadow /etc/shadow-', 'chmod o-rwx,g-rw /etc/shadow-', 'chown root:root /etc/group-', 'chmod u-x,go-wx /etc/group-', 'chown root:shadow /etc/gshadow-', 'chmod o-rwx,g-rw /etc/gshadow-', ]) except Exception, e: logging.error('Error when attemp to execute 6.configure_permit_sensitive_file()', exc_info=True)
def configure_iptables(): """3.6 Firewall Configuration""" try: Package('iptables').install() exec_shell([ 'iptables -F', 'iptables -P INPUT DROP', 'iptables -P OUTPUT DROP', 'iptables -P FORWARD DROP', 'iptables -A INPUT -i lo -j ACCEPT', 'iptables -A OUTPUT -o lo -j ACCEPT', 'iptables -A INPUT -s 127.0.0.0/8 -j DROP', 'iptables -A OUTPUT -p tcp -m state --state NEW,ESTABLISHED -j ACCEPT', 'iptables -A OUTPUT -p udp -m state --state NEW,ESTABLISHED -j ACCEPT', 'iptables -A OUTPUT -p icmp -m state --state NEW,ESTABLISHED -j ACCEPT', 'iptables -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT', 'iptables -A INPUT -p udp -m state --state ESTABLISHED -j ACCEPT', 'iptables -A INPUT -p icmp -m state --state ESTABLISHED -j ACCEPT', 'iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT', 'iptables-save' ]) except Exception, e: logging.error('Error when attemp to execute 3.6.configure_iptables()', exc_info=True)
def enable_aide(): """1.3 Filesystem Integrity Checking""" try: cron_job = '0 5 * * * /usr/bin/aide.wrapper --config /etc/aide/aide.conf --check' try: Package('aide').install() except Exception, e: logging.error('Package "aide" has no installation candidate') try: Package('aide-common').install() except Exception, e: logging.error('Package "aide-common" has no installation candidate') return exec_shell([ 'aide --init', 'mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz', '(crontab -u root -l 2>/dev/null | grep -v /usr/bin/aide; echo "{}") | crontab -'.format(cron_job) ]) except Exception, e: logging.error('Error when attemp to execute enable_aide()') def secure_boot_setting(): """1.4 Secure Boot Settings""" try: if os.path.isfile('/boot/grub/grub.cfg'): exec_shell([ 'chown root:root /boot/grub/grub.cfg', 'chmod og-rwx /boot/grub/grub.cfg' ]) except Exception, e: logging.error('Error when attemp to execute 1.4.secure_boot_setting()', exc_info=True)
def configure_warning_bannners(): """1.7 Warning Bannners""" #1.7.1 Command Line Warning Banners #1.7.1.1 try: m = exec_shell('cat /etc/motd').find('\m') r = exec_shell('cat /etc/motd').find('\r') s = exec_shell('cat /etc/motd').find('\s') v = exec_shell('cat /etc/motd').find('\v') if (( m or r or s or v) == 0): print "Check failed, please config the file: /etc/motd" #1.7.1.2 m = exec_shell('cat /etc/issue').find('\m') r = exec_shell('cat /etc/issue').find('\r') s = exec_shell('cat /etc/issue').find('\s') v = exec_shell('cat /etc/issue').find('\v') if ((m or r or s or v) == 0): print 'Check failed, please config the file: /etc/issue' #1.7.1.3 m = exec_shell('cat /etc/issue.net').find('\m') r = exec_shell('cat /etc/issue.net').find('\r') s = exec_shell('cat /etc/issue.net').find('\s') v = exec_shell('cat /etc/issue.net').find('\v') if ((m or r or s or v) == 0): print "Check failed, please config the file: /etc/issue.net" #1.7.1.4-6 exec_shell([ 'update-motd --disable', 'chown root:root /etc/motd', 'chmod 644 /etc/motd' ]) File('/etc/motd').write(get_string_asset('/etc/motd')) exec_shell(['chown root:root /etc/issue', 'chmod 644 /etc/issue']) File('/etc/issue').write('Authorized uses only. All activity may be monitored and reported.\n') exec_shell(['chown root:root /etc/issue.net', 'chmod 644 /etc/issue.net']) File('/etc/issue.net').write('Authorized uses only. All activity may be monitored and reported.\n') #1.7.2 Ensure GDM login banner is configured (Scored) check_GDM = exec_shell('apt -qq list gdm') if check_GDM.find('gdm') == 0: conf_GDM = "[org/gnome/login-screen]\n banner-message-enable=true\n banner-message-text='Authorized uses only. All activity may be monitored and reported.'\n" with open(path_final,'a') as f: f.write(conf_GDM) except Exception, e: logging.error('Error when attemp to execute 1.7.configure_warning_bannners()', exc_info=True)
def ensure_updated(): """1.8 Ensure updates, patches, and additional security software are installed""" exec_shell(['apt-get -s upgrade']) print "All software are updated"
def configure_log_file_permission(): """4.2.4 Ensure permissions on all logfiles are configured """ try: exec_shell('chmod -R g-wx,o-rwx /var/log/*') except Exception, e: logging.error('Error when attemp to execute 4.2.4.configure_log_file_permission()', 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)