def test_listening_files(policy): if not utils.have_command("readelf") or not utils.have_command("nm"): return TestResult(Result.SKIP, notes="readelf needed for this test") if not policy: return TestResult(Result.SKIP, notes="Unable to find test config") predicate = lambda x: os.path.exists(x) and _is_elf(x) return _check_binaries(policy, utils.listening_executables(), predicate)
def firewall_whitelisting(): if not utils.have_command('iptables-save'): return TestResult(Result.SKIP, "iptables not available") rules = _list_rules() if rules is None: return TestResult(Result.SKIP, "Cannot retrieve iptables rules") targets = _get_default_policy(rules) if b'filter' not in targets: return TestResult(Result.SKIP, "Cannot find the filter table") failures = [] filter_table = targets[b'filter'] if b'INPUT' not in filter_table: return TestResult(Result.SKIP, "Filter table doesn't include INPUT") if b'FORWARD' not in filter_table: return TestResult(Result.SKIP, "Filter table doesn't include FORWARD") if filter_table[b'INPUT'] == b'ACCEPT': failures.append('INPUT') if filter_table[b'FORWARD'] == b'ACCEPT': failures.append('FORWARD') if failures: return TestResult(Result.FAIL, "The following chains accept packets by " "default: %s" % ', '.join(failures)) else: return TestResult(Result.PASS, "Filter chains whitelist by default")
def _check_binaries(policy, filelist, predicate): if not utils.have_command("readelf") or not utils.have_command("nm"): return TestResult(Result.SKIP, notes="readelf needed for this test") results = GroupTestResult() for path in filelist: if predicate(path): actual = { "relro": _check_relro(path), "pie": _check_pie(path), "stack_canary": _check_stack_canary(path), "nx": _check_nx(path), "fortify": _check_fortify(path), "runpath": _check_runpath(path) } _check_policy(path, policy, actual, results) return results
def test_list_sudoers(): if not utils.have_command('sudo'): return TestResult(Result.SKIP, "sudo not installed") # these can be moved to config if there is a good reason somebody would # ever want to change them, for now they stay here list_sudoer_command = ['sudo', '-U', '$USER', '-l'] not_sudo_string = b'not allowed to run sudo' sudo_string = b'may run the following commands' nopasswd_string = b'NOPASSWD' passwd_entries = pwd.getpwall() user_accounts = [] for entry in passwd_entries: if entry.pw_name != 'root': user_accounts.append(entry.pw_name) sudo_users = [] nopasswd_users = [] for user in user_accounts: # set the user in the sudo command template list_sudoer_command[2] = user proc = subprocess.Popen(list_sudoer_command, stdout=subprocess.PIPE) (output, _stderr) = proc.communicate() # if the output has the non-sudo user string in it, do nothing if not_sudo_string in output: pass # otherwise... elif sudo_string in output: # if NOPASSWD tag is found if nopasswd_string in output: nopasswd_users.append(user) # sudo user that requires a password else: sudo_users.append(user) # fail if there are NOPASSWD sudo users if len(nopasswd_users) > 0: result = Result.FAIL notes = "User(s) { " + str(nopasswd_users) + " } have password-less " notes += "sudo access!" # otherwise the test passes else: result = Result.PASS if len(sudo_users) > 0: notes = "User(s) { " + str(sudo_users) + " } have sudo access" else: notes = "No users have sudo access" return TestResult(result, notes)