def cpu_nx_support(): suggest = Klanguage().to_ts(1185) try: data = file_op.cat("/proc/cpuinfo", "r") if data: flags, num = common.grep(data, r"flags\s*:\s(.*)") nx, num = common.grep(flags, r"nx") if nx == "nx": return Klanguage().to_ts(1120), LEVEL_SECURITY, suggest except Exception as e: pass return Klanguage().to_ts(1121), LEVEL_WARNING, suggest
def cpu_nx_support(self): suggest = Klanguage().to_ts(1185) try: data = file_op.cat("/proc/cpuinfo", "r") if data: flags, num = common.grep(data, r"flags\s*:\s(.*)") nx, num = common.grep(flags, r"nx") if nx == "nx": return Klanguage().to_ts( 1120), macro.BASELINE_LEVEL["SECURITY"], suggest except Exception as e: pass return Klanguage().to_ts(1121), macro.BASELINE_LEVEL["LOW"], suggest
def check_kdump_config(response): if common.is_linux(): kdump_cmdline = "/proc/cmdline" crashkernel = "" if os.path.exists(kdump_cmdline): data = file_op.cat(kdump_cmdline, "r") if data: crashkernel, num = common.grep(data, r"crashkernel=(\S+)") #enable if crashkernel: kdump_conf = "/etc/kdump.conf" if os.path.exists(kdump_conf): data = file_op.cat(kdump_conf, "r") if data: lines = data.split("\n") values = [["Key", "Value"], ["Reserved memory", crashkernel]] keys = [ "Store the dump to a remote machine using the NFS protocol,", "Local directory in which the core dump is to be saved", "Write dump to storage devices", "Write the dump directly to a device", "Core collector to compress the data", "Action to perform in case dumping fails", "Store the dump to a remote machine using the SSH protocol", "SSH Key" ] patterns = [ re.compile(r"nfs\s(\S+)"), re.compile(r"path\s(\S+)"), re.compile(r"ext4\s(\S+)"), re.compile(r"raw\s(\S+)"), re.compile(r"core_collector\s(\S+).*"), re.compile(r"default\s(\S+)"), re.compile(r"ssh\s(\S+)"), re.compile(r"sshkey\s(\S+)") ] for line in lines: for i in range(len(patterns)): match = patterns[i].match(line) if match and len(match.groups()): values.append([keys[i], match.groups()[0]]) response["kernel"].append({ "name": "Kernel Dump Configuration", "value": len(values) - 1, "values": values })
def get_cpuinfo(response): try: data = file_op.cat("/proc/cpuinfo", "r") if data: #vendor_id, num = lib.grep(data, r"vendor_id\s*:\s(.*)") model_name, num = common.grep(data, r"model name\s*:\s(.*)") response["hardware"].append( {Klanguage().to_ts(1011): ["{}".format(model_name)]}) except: pass
def default_io_scheduler(response): config_file = find_kernel_config() if config_file: data = file_op.cat(config_file, "r") if data: io_scheduler, num = common.grep(data, r"CONFIG_DEFAULT_IOSCHED=(\S*)") if num: response["kernel"].append({ "name": "IO Scheduler", "value": io_scheduler })
def find_useradd_users(): uid_min = 1000 uid_max = 60000 data = common.cat("/etc/login.defs") if data: lines = data.split("\n") for line in lines: if line: tmp, num = common.grep(line, r"^UID_MIN\s*(\d+)") if num: uid_min = tmp continue tmp, num = common.grep(line, r"^UID_MAX\s*(\d+)") if num: uid_max = tmp continue data = common.cat("/etc/passwd") usernames = [] if data: lines = data.split("\n") for line in lines: if line: username, password, uid, gid, comment, home, shell = line.split( ":") if uid_min != None and uid_max != None: if int(uid) >= int(uid_min) and int(uid) <= int(uid_max): usernames.append(username) return usernames
def login_defs_policy(self, target_risk_id): baseline = Kdatabase().get_obj('baseline') data = file_op.cat("/etc/login.defs", "r") if data: lines = data.split("\n") for line in lines: if line: # UMASK is the default umask value for pam_umask and is used by # useradd and newusers to set the mode of the new home directories. tmp, num = common.grep(line, r"^UMASK\s*(\S+)") if num: if tmp == "077" or tmp == "027" or tmp == "0077" or tmp == "0027": if target_risk_id == macro.BASELINE_ITEM[ "AU_UMASK"]: if macro.BASELINE_ITEM["AU_UMASK"] in baseline[ "risks"]: baseline["risks"][ macro.BASELINE_ITEM["AU_UMASK"]][ "handle_ts"] = time_op.now() baseline["risks"][ macro.BASELINE_ITEM["AU_UMASK"]][ "stage"] = macro.BASELINE_STAGE[ "VERIFIED"] else: if macro.BASELINE_ITEM["AU_UMASK"] in baseline[ "risks"]: baseline["risks"][macro.BASELINE_ITEM[ "AU_UMASK"]]["last_ts"] = time_op.now() baseline["risks"][ macro.BASELINE_ITEM["AU_UMASK"]][ "stage"] = macro.BASELINE_STAGE[ "UNRESOLVED"] else: baseline["risks"][ macro.BASELINE_ITEM["AU_UMASK"]] = { "name": Klanguage().to_ts(1178), "level": macro.BASELINE_LEVEL["MEDIUM"], "stage": macro.BASELINE_STAGE["UNRESOLVED"], "kind": macro.BASELINE_KIND["AUTHENTICATION"], "extra": tmp, "ts": time_op.now(), "last_ts": time_op.now(), "handle_ts": None, "solution": Klanguage().to_ts(1177) } continue # Algorithm will be used for encrypting password tmp, num = common.grep(line, r"^ENCRYPT_METHOD\s*(\S+)") if num: if tmp == "SHA512": if target_risk_id == macro.BASELINE_ITEM[ "AU_ENCRYPT_METHOD"]: if macro.BASELINE_ITEM[ "AU_ENCRYPT_METHOD"] in baseline[ "risks"]: baseline["risks"][macro.BASELINE_ITEM[ "AU_ENCRYPT_METHOD"]][ "handle_ts"] = time_op.now() baseline["risks"][macro.BASELINE_ITEM[ "AU_ENCRYPT_METHOD"]][ "stage"] = macro.BASELINE_STAGE[ "VERIFIED"] else: if macro.BASELINE_ITEM[ "AU_ENCRYPT_METHOD"] in baseline["risks"]: baseline["risks"][ macro.BASELINE_ITEM["AU_ENCRYPT_METHOD"]][ "last_ts"] = time_op.now() baseline["risks"][ macro.BASELINE_ITEM["AU_ENCRYPT_METHOD"]][ "stage"] = macro.BASELINE_STAGE[ "UNRESOLVED"] else: baseline["risks"][macro.BASELINE_ITEM[ "AU_ENCRYPT_METHOD"]] = { "name": Klanguage().to_ts(1175), "level": macro.BASELINE_LEVEL["LOW"], "stage": macro.BASELINE_STAGE["UNRESOLVED"], "kind": macro.BASELINE_KIND["AUTHENTICATION"], "extra": tmp, "ts": time_op.now(), "last_ts": time_op.now(), "handle_ts": None, "solution": Klanguage().to_ts(1174) } continue #Password aging controls #Maximum number of days a password may be used tmp, num = common.grep(line, r"^PASS_MAX_DAYS\s*(\d+)") if num: if tmp == "99999": if macro.BASELINE_ITEM[ "AU_PASS_MAX_DAYS"] in baseline["risks"]: baseline["risks"][ macro.BASELINE_ITEM["AU_PASS_MAX_DAYS"]][ "last_ts"] = time_op.now() baseline["risks"][ macro.BASELINE_ITEM["AU_PASS_MAX_DAYS"]][ "stage"] = macro.BASELINE_STAGE[ "UNRESOLVED"] else: baseline["risks"][macro.BASELINE_ITEM[ "AU_PASS_MAX_DAYS"]] = { "name": Klanguage().to_ts(1175), "level": macro.BASELINE_LEVEL["LOW"], "stage": macro.BASELINE_STAGE["UNRESOLVED"], "kind": macro.BASELINE_KIND["AUTHENTICATION"], "extra": tmp, "ts": time_op.now(), "last_ts": time_op.now(), "handle_ts": None, "solution": Klanguage().to_ts(1170) } else: if target_risk_id == macro.BASELINE_ITEM[ "AU_PASS_MAX_DAYS"]: if macro.BASELINE_ITEM[ "AU_PASS_MAX_DAYS"] in baseline[ "risks"]: baseline["risks"][macro.BASELINE_ITEM[ "AU_PASS_MAX_DAYS"]][ "handle_ts"] = time_op.now() baseline["risks"][macro.BASELINE_ITEM[ "AU_PASS_MAX_DAYS"]][ "stage"] = macro.BASELINE_STAGE[ "VERIFIED"] continue #Minimum number of days allowed between password changes. tmp, num = common.grep(line, r"^PASS_MIN_DAYS\s*(\d+)") if num: if tmp == "0": if macro.BASELINE_ITEM[ "AU_PASS_MIN_DAYS"] in baseline["risks"]: baseline["risks"][ macro.BASELINE_ITEM["AU_PASS_MIN_DAYS"]][ "last_ts"] = time_op.now() baseline["risks"][ macro.BASELINE_ITEM["AU_PASS_MIN_DAYS"]][ "stage"] = macro.BASELINE_STAGE[ "UNRESOLVED"] else: baseline["risks"][macro.BASELINE_ITEM[ "AU_PASS_MIN_DAYS"]] = { "name": Klanguage().to_ts(1175), "level": macro.BASELINE_LEVEL["LOW"], "stage": macro.BASELINE_STAGE["UNRESOLVED"], "kind": macro.BASELINE_KIND["AUTHENTICATION"], "extra": tmp, "ts": time_op.now(), "last_ts": time_op.now(), "handle_ts": None, "solution": Klanguage().to_ts(1167) } else: if target_risk_id == macro.BASELINE_ITEM[ "AU_PASS_MIN_DAYS"]: if macro.BASELINE_ITEM[ "AU_PASS_MIN_DAYS"] in baseline[ "risks"]: baseline["risks"][macro.BASELINE_ITEM[ "AU_PASS_MIN_DAYS"]][ "handle_ts"] = time_op.now() baseline["risks"][macro.BASELINE_ITEM[ "AU_PASS_MIN_DAYS"]][ "stage"] = macro.BASELINE_STAGE[ "VERIFIED"] continue #Min/max values for automatic uid selection in useradd tmp, num = common.grep(line, r"^UID_MIN\s*(\d+)") if num: self.uid_min = tmp continue #Min/max values for automatic uid selection in useradd tmp, num = common.grep(line, r"^UID_MAX\s*(\d+)") if num: self.uid_max = tmp continue
def login_defs_policy(response): global uid_min global uid_max values = [["ITEM", "VALUE"]] data = file_op.cat("/etc/login.defs", "r") if data: lines = data.split("\n") for line in lines: if line: # The default PATH settings, for superuser. tmp, num = common.grep(line, r"^ENV_SUPATH\s*(\S+)") if num: values.append(["Default PATH settings for superuser", tmp]) continue # The default PATH settings, for normal users. tmp, num = common.grep(line, r"^ENV_PATH\s*(\S+)") if num: values.append( ["Default PATH settings for normal users", tmp]) continue # UMASK is the default umask value for pam_umask and is used by # useradd and newusers to set the mode of the new home directories. tmp, num = common.grep(line, r"^UMASK\s*(\S+)") if num: values.append(["UMASK", tmp]) continue # If defined, login failures will be logged here in a utmp format # last, when invoked as lastb, will read /var/log/btmp, so... tmp, num = common.grep(line, r"^FTMP_FILE\s*(\S+)") if num: values.append(["Login failures will be logged in", tmp]) continue # Algorithm will be used for encrypting password tmp, num = common.grep(line, r"^ENCRYPT_METHOD\s*(\S+)") if num: values.append([ "Algorithm will be used for encrypting password", tmp ]) continue #Min/max values for automatic uid selection in useradd tmp, num = common.grep(line, r"^UID_MIN\s*(\d+)") if num: values.append([ "Min values for automatic uid selection in useradd", tmp ]) uid_min = tmp continue #Min/max values for automatic uid selection in useradd tmp, num = common.grep(line, r"^UID_MAX\s*(\d+)") if num: values.append([ "Max values for automatic uid selection in useradd", tmp ]) uid_max = tmp continue #Min/max values for automatic gid selection in groupadd tmp, num = common.grep(line, r"^GID_MIN\s*(\d+)") if num: values.append([ "Min values for automatic gid selection in groupadd", tmp ]) continue #Min/max values for automatic gid selection in groupadd tmp, num = common.grep(line, r"^GID_MAX\s*(\d+)") if num: values.append([ "Max values for automatic gid selection in groupadd", tmp ]) continue #Password aging controls #Maximum number of days a password may be used tmp, num = common.grep(line, r"^PASS_MAX_DAYS\s*(\d+)") if num: values.append( ["Maximum number of days a password may be used", tmp]) continue #Minimum number of days allowed between password changes. tmp, num = common.grep(line, r"^PASS_MIN_DAYS\s*(\d+)") if num: values.append([ "Minimum number of days allowed between password changes.", tmp ]) continue #Number of days warning given before a password expires. tmp, num = common.grep(line, r"^PASS_WARN_AGE\s*(\d+)") if num: values.append([ "Number of days warning given before a password expires.", tmp ]) continue response["authentication"].append({ "name": "Configuration control definitions for the login package", "value": len(values) - 1, "values": values })
def login_defs_policy(response): global uid_min global uid_max values = [[ Klanguage().to_ts(1148), Klanguage().to_ts(1149), Klanguage().to_ts(1119) ]] data = file_op.cat("/etc/login.defs", "r") if data: lines = data.split("\n") for line in lines: if line: # The default PATH settings, for superuser. tmp, num = common.grep(line, r"^ENV_SUPATH\s*(\S+)") if num: values.append( [Klanguage().to_ts(1180), tmp, LEVEL_INVALID, ""]) continue # The default PATH settings, for normal users. tmp, num = common.grep(line, r"^ENV_PATH\s*(\S+)") if num: values.append( [Klanguage().to_ts(1179), tmp, LEVEL_INVALID, ""]) continue # UMASK is the default umask value for pam_umask and is used by # useradd and newusers to set the mode of the new home directories. tmp, num = common.grep(line, r"^UMASK\s*(\S+)") if num: if tmp == "077" or tmp == "027" or tmp == "0077" or tmp == "0027": level = LEVEL_SECURITY else: level = LEVEL_WARNING response["statistic"]["warning"] += 1 values.append([ Klanguage().to_ts(1178), tmp, level, Klanguage().to_ts(1177) ]) continue # If defined, login failures will be logged here in a utmp format # last, when invoked as lastb, will read /var/log/btmp, so... tmp, num = common.grep(line, r"^FTMP_FILE\s*(\S+)") if num: values.append( [Klanguage().to_ts(1176), tmp, LEVEL_INVALID, ""]) continue # Algorithm will be used for encrypting password tmp, num = common.grep(line, r"^ENCRYPT_METHOD\s*(\S+)") if num: if tmp == "SHA512": level = LEVEL_SECURITY suggest = Klanguage().to_ts(1173) else: level = LEVEL_WARNING suggest = Klanguage().to_ts(1174) response["statistic"]["warning"] += 1 values.append( [Klanguage().to_ts(1175), tmp, level, suggest]) continue #Password aging controls #Maximum number of days a password may be used tmp, num = common.grep(line, r"^PASS_MAX_DAYS\s*(\d+)") if num: if tmp == "99999": level = LEVEL_WARNING suggest = Klanguage().to_ts(1170) response["statistic"]["warning"] += 1 else: level = LEVEL_SECURITY suggest = Klanguage().to_ts(1171) values.append( [Klanguage().to_ts(1172), tmp, level, suggest]) continue #Minimum number of days allowed between password changes. tmp, num = common.grep(line, r"^PASS_MIN_DAYS\s*(\d+)") if num: if tmp == "0": level = LEVEL_WARNING suggest = Klanguage().to_ts(1167) response["statistic"]["warning"] += 1 else: level = LEVEL_SECURITY suggest = Klanguage().to_ts(1168) values.append( [Klanguage().to_ts(1169), tmp, level, suggest]) continue #Number of days warning given before a password expires. tmp, num = common.grep(line, r"^PASS_WARN_AGE\s*(\d+)") if num: level = LEVEL_SECURITY suggest = Klanguage().to_ts(1165) values.append( [Klanguage().to_ts(1166), tmp, level, suggest]) continue #Min/max values for automatic uid selection in useradd tmp, num = common.grep(line, r"^UID_MIN\s*(\d+)") if num: uid_min = tmp continue #Min/max values for automatic uid selection in useradd tmp, num = common.grep(line, r"^UID_MAX\s*(\d+)") if num: uid_max = tmp continue response["authentication"].append({ "name": Klanguage().to_ts(1147), "values": values })
def find_runlevel(): global runlevel #runlevel #N 5 #who -r # run-level 5 2017-07-08 15:12 data, success, retcode = common.exec_command(['runlevel']) if success: runlevel_pattern = re.compile(r'^N\s(\d)') match = runlevel_pattern.match(data) if match: runlevel = match.groups()[0] return #/etc/systemd/system/default.target -> /lib/systemd/system/graphical.target default_target = "/etc/systemd/system/default.target" target = lib.readlink(default_target, 1) if target != "": for i in ["runlevel5.target", "graphical.target"]: tmp, num = common.grep(target, i) if num: runlevel = 5 return for i in ["runlevel3.target", "multi-user.target"]: tmp, num = common.grep(target, i) if num: runlevel = 3 return ## Default runlevel. The runlevels used are: # 0 - halt (Do NOT set initdefault to this) # 1 - Single user mode # 2 - Multiuser, without NFS (The same as 3, if you do not have networking) # 3 - Full multiuser mode # 4 - unused # 5 - X11 # 6 - reboot (Do NOT set initdefault to this) # #id:3:initdefault: data = file_op.cat("/etc/inittab", "r") if data: lines = data.split("\n") for line in lines: tmp, num = common.grep(line, r"^id:(\d)") if num: runlevel = tmp return # run-level 5 2017-09-17 13:35 data, success, retcode = common.exec_command(['who', '-r']) if success: tmp, num = common.grep(data, r"^\s*run-level\s(\d)") if num: runlevel = tmp return