import subprocess from CIStoPLIST import shared # 2.5 Energy Saver # This section contains recommendations related to the configurable items under the Energy Saver panel if __name__ == '__main__': # 2.5.1 Disable "Wake for network access" (Scored) energy_saver_plist = {} wake_status = subprocess.run(['pmset', '-g'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if "womp 0" in wake_status.stdout.decode('utf-8'): energy_saver_plist.update({'WakeForNetworkAccess': 0}) if "womp 1" in wake_status.stdout.decode('utf-8'): energy_saver_plist.update({'WakeForNetworkAccess': 1}) # 5.14 Ensure system is set to hibernate (Scored) hibernate = subprocess.Popen('pmset -g | egrep standbydelay', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) hibernate_out = hibernate.communicate() energy_saver_plist.update( {'HibernateDelay': hibernate_out[0].decode('utf-8').rstrip("\n")}) shared.plist_create(energy_saver_plist, "/tmp/EnergySaver.plist")
security_privacy_plist.update({'FilevaultStatus': 1}) if "FileVault is Off." in fv_status.stdout.decode('utf-8'): security_privacy_plist.update({'FilevaultStatus': 0}) # 2.6.7 Monitor Location Services Access (Not Scored) location_service_access = subprocess.run( ['sudo', 'defaults', 'read', '/var/db/locationd/clients.plist'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # this isn't great, apple's clients.plist looks more like a dictionary than a plist. # returns a string that is difficult to parse. security_privacy_plist.update({ 'LocationServiceAccess': location_service_access.stdout.decode('utf-8') }) # 5.15 Require an administrator password to access system-wide preferences (Scored) system_preferences = subprocess.Popen( 'security authorizationdb read system.preferences 2> /dev/null | ' 'grep -A1 shared | grep -E "(true|false)"', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) system_preferences_out = system_preferences.communicate() security_privacy_plist.update({ 'SecurityAuthorization': system_preferences_out[0].decode('utf-8').rstrip("\n")[2:6] }) shared.plist_create(security_privacy_plist, "/tmp/SecurityAndPrivacy.plist")
'NetworkLocations': network_locations.stdout.decode('utf-8').rstrip("\n") }) http_server_status = subprocess.Popen('ps -ef | grep -i [h]ttpd', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) http_server_status_out = http_server_status.communicate() network_configurations_plist.update( {'HTTPServerStatus': http_server_status_out[0].decode('utf-8')}) nfs_server_status = subprocess.Popen('ps -ef | grep -i [n]fsd', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) nfs_server_status_out = nfs_server_status.communicate() network_configurations_plist.update({ 'NFSServerStatus': nfs_server_status_out[0].decode('utf-8'.rstrip("\n")) }) nfs_server_export = subprocess.run(['cat', '/etc/exports'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) network_configurations_plist.update({ 'NFSServerExport': nfs_server_export.stdout.decode('utf-8').rstrip("\n") }) shared.plist_create(network_configurations_plist, '/tmp/NetworkCgti onfiguration.plist')
import subprocess from CIStoPLIST import shared # 2.10 Enable Secure Keyboard Entry in terminal.app (Scored) if __name__ == '__main__': secure_keyboard_plist = {} secure_keyboard_status = subprocess.run( ['defaults', 'read', '-app', 'Terminal', 'SecureKeyboardEntry'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) secure_keyboard_plist.update({ 'SecureKeyboard': secure_keyboard_status.stdout.decode('utf-8').rstrip("\n") }) shared.plist_create(secure_keyboard_plist, '/tmp/SecureKeyboard.plist')
from CIStoPLIST import shared import subprocess # 2.8 Time Machine if __name__ == '__main__': time_machine_plist = {} # time_machine_settings = main.plist_value('/Library/Preferences/com.apple.TimeMachine.plist', 'AutoBackup') auto_backup = subprocess.run([ 'sudo', 'defaults', 'read', '/Library/Preferences/com.apple.TimeMachine.plist', 'AutoBackup' ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) time_machine_plist.update( {'AutoBackup': int(auto_backup.stdout.decode('utf-8').rstrip("\n"))}) print(time_machine_plist) shared.plist_create(time_machine_plist, "/tmp/TimeMachine.plist")
from CIStoPLIST import shared import subprocess if __name__ == '__main__': # 5.7 Automatically lock the login keychain for inactivity (Scored) keychain_plist = {} keychain_timeout = subprocess.run(['security', 'show-keychain-info'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) keychain_plist.update({'KeychainTimeout': keychain_timeout.stdout.decode('utf-8').rstrip("\n")}) # 5.8 Ensure login keychain is locked when the computer sleeps (Scored) keychain_sleep_lock = subprocess.run(['security', 'show-keychain-info'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) keychain_plist.update({'KeychainSleepLock': keychain_sleep_lock.stdout.decode('utf-8').rstrip("\n")}) # 5.9 Enable OCSP and CRL certificate checking (Scored) certificate_check_CRL = subprocess.run(['defaults', 'read', 'com.apple.security.revocation', 'CRLStyle'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) keychain_plist.update({'TrustCRL': certificate_check_CRL.stdout.decode('utf-8').rstrip("\n")}) certificate_check_OCSP = subprocess.run(['defaults', 'read', 'com.apple.security.revocation', 'OCSPStyle'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) keychain_plist.update({'TrustOCSP': certificate_check_OCSP.stdout.decode('utf-8').rstrip("\n")}) shared.plist_create(keychain_plist, "/tmp/Keychain.plist")
audit_plist = {} audit_flags = subprocess.Popen( 'sudo grep ^flags /etc/security/audit_control', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) audit_flags_out = audit_flags.communicate() audit_plist.update( {'AuditFlags': audit_flags_out[0].decode('utf-8').rstrip("\n")[6:]}) audit_retention = subprocess.Popen( 'sudo cat /etc/security/audit_control | egrep expire-after', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) audit_retention_out = audit_retention.communicate() audit_plist.update( {'AuditRetention': audit_retention_out[0].decode('utf-8')}) install_log = subprocess.Popen('grep -i ttl /etc/asl/com.apple.install', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) install_log_out = install_log.communicate() if 'ttl=365' in install_log_out[0].decode('utf-8'): audit_plist.update({'InstallLogRetention': 1}) else: audit_plist.update({'InstallLogRetention': 0}) shared.plist_create(audit_plist, '/tmp/LoggingAuditing.plist')
# 2.9 Pair the remote control infrared receiver if enabled (Scored) if __name__ == '__main__': infrared_remote_plist = {} system_profiler_status = subprocess.run(['system_profiler'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if "IR Receiver" in system_profiler_status.stdout.decode('utf-8'): infrared_remote_plist.update({}) device_enabled = subprocess.run([ 'defaults', 'read', '/Library/Preferences/com.apple.driver.AppleIRController', 'DeviceEnabled' ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) uid_filter = subprocess.run([ 'defaults', 'read', '/Library/Preferences/com.apple.driver.AppleIRController', 'UIDFilter' ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) print(device_enabled.stdout.decode('utf-8')) print(uid_filter.stdout.decode('utf-8')) else: infrared_remote_plist.update({'IRReciever': 'Off'}) shared.plist_create(infrared_remote_plist, "/tmp/InfraredReceiver.plist")
password_policy_plist.update({'PasswordRequiresUpperAndLower': 0}) # 5.2.7 Password Age (Scored) pass_age = subprocess.Popen( 'pwpolicy -getaccountpolicies | egrep policyAttributeExpiresEveryNDays', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) pass_age_out = pass_age.communicate() if "policyAttributeExpiresEveryNDays" in pass_age_out[0].decode('utf-8'): password_age = re.findall(r'[0-9]+', pass_age_out[0].decode('utf-8')) password_policy_plist.update({'PasswordAge': pass_age}) else: password_policy_plist.update({'PasswordAge': 0}) # 5.2.8 Password History (Scored) differ_from_past = subprocess.Popen( 'pwpolicy -getaccountpolicies | egrep "differ from past"', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) differ_from_past_out = differ_from_past.communicate() if "Password must differ from past 15 passwords" in differ_from_past_out[ 0].decode('utf-8'): password_policy_plist.update({'DifferFromPast': 15}) else: password_policy_plist.update({'DifferFromPast': 0}) shared.plist_create(password_policy_plist, '/tmp/PasswordPolicy.plist')
import subprocess from CIStoPLIST import shared # 2.11 Java 6 is not the default Java runtime (Scored) if __name__ == '__main__': java_version_plist = {} java_version = subprocess.run(['java', '-version'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) java_version_plist.update( {'JavaVersion': java_version.stdout.decode('utf-8')}) shared.plist_create(java_version_plist, "/tmp/JavaVersion.plist")
from pathlib import Path # 2.7 iCloud # iCloud is Apple's service for synchronizing, storing and backing up data from Apple applications in both macOS and iOS # These settings are per user, so this should run as the user. if __name__ == '__main__': icloud_plist = {} # 2.7.1 iCloud configuration (Not Scored) # 2.7.2 iCloud keychain (Not Scored) # 2.7.3 iCloud Drive (Not Scored) # 2.7.4 iCloud Drive Document sync (Scored) # 2.7.5 iCloud Drive Desktop sync (Scored) icloud_settings = shared.plist_value(str(Path.home()) + '/Library/Preferences/MobileMeAccounts.plist', 'Accounts') for i in icloud_settings['Accounts'][0]['Services']: try: print(i['Name'], i['status']) icloud_plist.update({i['Name']: i['status']}) except KeyError: try: # print(i['Name'], i['Enabled']) icloud_plist.update({i['Name']: i['Enabled']}) except KeyError: print(i) shared.plist_create(icloud_plist, '/tmp/iCloud.plist')
import subprocess if __name__ == '__main__': # 2.1.1 Turn off Bluetooth, if no paired devices exist (Scored) bluetooth_plist = {} Bluetooth = "/Library/Preferences/com.apple.Bluetooth.plist", 'ControllerPowerState' bluetooth_plist.update(shared.plist_value(Bluetooth[0], Bluetooth[1])) if bluetooth_plist['ControllerPowerState'] == 1: bt_power_state = subprocess.run( ['system_profiler', 'SPBluetoothDataType'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if 'Bluetooth:' and "Connectable:" in bt_power_state.stdout.decode( 'utf-8'): bluetooth_plist.update( {'ControllerPowerState': "enabled and devices present"}) else: bluetooth_plist.update( {'ControllerPowerState': "disabled and no devices present"}) # 2.1.2 Bluetooth "Discoverable" is only available when Bluetooth preference pane is open (Not Scored) # 2.1.3 Show Bluetooth status in menu bar (Scored) bt_status = subprocess.run( ['defaults', 'read', 'com.apple.systemuiserver', 'menuExtras'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if "Bluetooth.menu" in bt_status.stdout.decode('utf-8'): bluetooth_plist.update({'BluetoothMenu': 1}) else: bluetooth_plist.update({'BluetoothMenu': 0}) shared.plist_create(bluetooth_plist, "/tmp/Bluetooth.plist")
import subprocess from CIStoPLIST import shared # 2.13 Ensure EFI version is valid and being regularly checked (Scored) if __name__ == '__main__': efi_plist = {} efi_status = subprocess.run(['/usr/libexec/firmwarecheckers/eficheck/eficheck', '--integrity-check'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if "No changes detected in primary hashes" in efi_status.stdout.decode('utf-8'): efi_plist.update({'IntegrityCheck': 'No changes detected in primary hashes'}) else: efi_plist.update({'IntegrityCheck': 'Check EFI integrity'}) shared.plist_create(efi_plist, '/tmp/EFI.plist')
import subprocess from CIStoPLIST import shared import os if __name__ == '__main__': # 2.2.1 Enable "Set time and date automatically" (Scored) # This one requires elevated privileges to run. This isn't my favorite thing... # visudo user ALL=(ALL) NOPASSWD: /full/path/to/command ARG1 ARG2, /full/path/to/command ARG1 ARG2 date_time_plist = {} ntp_status = subprocess.run(['sudo', 'systemsetup', '-getusingnetworktime'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if "On" in ntp_status.stdout.decode('utf-8'): date_time_plist.update({'NetworkTime': 1}) else: date_time_plist.update({'NetworkTime': 0}) # 2.2.2 Ensure time set is within appropriate limits (Scored) # 2.2.3 Added my own benchmark for NTP time server ntp_server = subprocess.run(['sudo', 'systemsetup', '-getnetworktimeserver'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) date_time_plist.update({'NTPServer': ntp_server.stdout.decode('utf-8')[21:].rstrip("\n")}) if os.path.isfile('/var/db/ntp-kod') is True: # if false, needs to be created ntp_offset = subprocess.run(['sudo', 'sntp', '-Ss', '-M', '128', str(date_time_plist['NTPServer'])], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) date_time_plist.update({'NTPOffset': ntp_offset.stdout.decode('utf-8')[97:-61]}) shared.plist_create(date_time_plist, "/tmp/DateTime.plist")
screen_saver_corners.update({ 'ScreenSaverBRCorner': int(screen_saver_br_corner.stdout.decode('utf-8')) }) screen_saver_tl_corner = subprocess.run( ['defaults', 'read', 'com.apple.dock', 'wvous-tl-corner'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) screen_saver_corners.update({ 'ScreenSaverTLCorner': int(screen_saver_tl_corner.stdout.decode('utf-8')) }) screen_saver_tr_corner = subprocess.run( ['defaults', 'read', 'com.apple.dock', 'wvous-tr-corner'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) screen_saver_corners.update({ 'ScreenSaverTRCorner': int(screen_saver_tr_corner.stdout.decode('utf-8')) }) print(screen_saver_plist) screen_saver_plist.update({'ScreenSaverCorners': screen_saver_corners}) print(screen_saver_plist) # 2.3.3 Familiarize users with screen lock tools or corner to Start Screen Saver (Not Scored) # This is user training only. shared.plist_create(screen_saver_plist, "/tmp/ScreenSaver.plist")
# this setting is protected behind system preferences > security and privacy > full disk access > terminal.app try: open_safe_downloads = subprocess.run( ['defaults', 'read', 'com.apple.Safari', 'AutoOpenSafeDownloads'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) accounts_and_environment_plist.update({ 'AutoOpenSafeDownloads': int(open_safe_downloads.stdout.decode('utf-8').rstrip("\n")) }) except TypeError: accounts_and_environment_plist.update( {'AutoOpenSafeDownloads': "Unable to get setting"}) plugin_first_visit = subprocess.Popen( 'defaults read ~/Library/Preferences/com.apple.safari.plist | ' 'grep -i "PlugInFirstVisitPolicy = *"', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) plugin_first_visit_out = plugin_first_visit.communicate() if "PlugInFirstVisitPolicy" in plugin_first_visit_out[0].decode('utf-8'): accounts_and_environment_plist.update( {'PlugInFirstVisitPolicy': "PlugInFirstVisitPolicy"}) else: accounts_and_environment_plist.update( {'PlugInFirstVisitPolicy': "Not Found"}) shared.plist_create(accounts_and_environment_plist, '/tmp/AccountsAndEnvironment.plist')
import subprocess from CIStoPLIST import shared if __name__ == '__main__': # 5.23 System Integrity Protection status (Scored) system_integrity_plist = {} system_integrity_status = subprocess.run(['/usr/bin/csrutil', 'status'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) system_integrity_plist.update({ 'SystemIntegrityStatus': system_integrity_status.stdout.decode('utf-8').rstrip("\n")[36:-1] }) shared.plist_create(system_integrity_plist, '/tmp/SystemIntegrity.plist')
users_accounts_plist.update( {'RootDisabled': root_disabled_out[0].decode('utf-8').rstrip("\n")}) # 5.16 Disable ability to login to another user's active and locked session (Scored) disable_login_other_user = subprocess.Popen( '/usr/bin/security authorizationdb read system.login.screensaver ' '2>/dev/null | /usr/bin/grep -A 1 "<array>" | /usr/bin/awk -F "<|>" ' '"END{ print $3 }"', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) disable_login_other_user_out = disable_login_other_user.communicate() users_accounts_plist.update({ 'DisableLoginUserActiveSession': disable_login_other_user_out[0].decode('utf-8')[10:-10] }) # 5.20 Disable Fast User Switching (Not Scored) fast_user_switching = subprocess.run([ 'defaults', 'read', '/Library/Preferences/.GlobalPreferences', 'MultipleSessionEnabled' ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) users_accounts_plist.update({ 'FastUserSwitching': bool(fast_user_switching.stdout.decode('utf-8')) }) shared.plist_create(users_accounts_plist, '/tmp/UserAccounts.plist')