def testParseCronData(self): test_data = br"""root user user2 user3 root hi hello user pparth""" file_obj = io.BytesIO(test_data) pathspec = rdf_paths.PathSpec(path="/etc/at.allow") stat = rdf_client_fs.StatEntry(pathspec=pathspec) parser = config_file.CronAtAllowDenyParser() results = list(parser.Parse(stat, file_obj, None)) result = [ d for d in results if isinstance(d, rdf_protodict.AttributedDict) ][0] filename = result.filename users = result.users self.assertEqual("/etc/at.allow", filename) self.assertEqual(sorted(["root", "user", "pparth"]), sorted(users)) anomalies = [a for a in results if isinstance(a, rdf_anomaly.Anomaly)] self.assertEqual(1, len(anomalies)) anom = anomalies[0] self.assertEqual("Dodgy entries in /etc/at.allow.", anom.symptom) self.assertEqual(sorted(["user2 user3", "hi hello"]), sorted(anom.finding)) self.assertEqual(pathspec, anom.reference_pathspec) self.assertEqual("PARSER_ANOMALY", anom.type)
def testCronAllowOnlyContainsRoot(self): """Ensure cron/at allow only contains "root".""" check_id = "CIS-CRON-AT-ALLOW-ONLY-CONTAINS-ROOT" artifact = "CronAtAllowDenyFiles" sym = ("Found: at.allow or cron.allow contains non-root users or does " "not contain root.") parser = config_file.CronAtAllowDenyParser() data = { "/etc/at.allow": u"root", "/etc/cron.allow": u"user1", "/etc/at.deny": u"blah\nblah blah" } found = ["/etc/cron.allow: user1"] results = self.GenResults([artifact], [data], [parser]) self.assertCheckDetectedAnom(check_id, results, sym, found) data = {"/etc/at.allow": u"", "/etc/cron.allow": u"root"} found = ["/etc/at.allow:"] results = self.GenResults([artifact], [data], [parser]) self.assertCheckDetectedAnom(check_id, results, sym, found) data = {"/etc/at.allow": u"", "/etc/cron.allow": u""} found = ["/etc/at.allow:", "/etc/cron.allow:"] results = self.GenResults([artifact], [data], [parser]) self.assertCheckDetectedAnom(check_id, results, sym, found) data = {"/etc/at.allow": u"root", "/etc/cron.allow": u"root"} results = self.GenResults([artifact], [data], [parser]) self.assertCheckUndetected(check_id, results)
def testFileArtifactParser(self): """Test parsing a fake file artifact with a file parser.""" processor = config_file.CronAtAllowDenyParser() source = rdf_artifact.ArtifactSource( type=rdf_artifact.ArtifactSource.SourceType.FILE, attributes={ "paths": ["VFSFixture/etc/passwd", "numbers.txt"], }) paths = [] for path in source.attributes["paths"]: paths.append(os.path.join(self.base_path, path)) stat_cache = utils.StatCache() expanded_paths = [] opts = globbing.PathOpts(follow_links=True) for path in paths: for expanded_path in globbing.ExpandPath(path, opts): expanded_paths.append(expanded_path) path_type = rdf_paths.PathSpec.PathType.OS results = [] for path in expanded_paths: stat = stat_cache.Get(path, follow_symlink=True) pathspec = rdf_paths.PathSpec( pathtype=path_type, path=client_utils.LocalPathToCanonicalPath(stat.GetPath()), path_options=rdf_paths.PathSpec.Options.CASE_LITERAL) response = rdf_client_fs.FindSpec(pathspec=pathspec) for res in artifact_collector.ParseSingleResponse( processor, response, {}, path_type): results.append(res) self.assertEqual(len(results), 3) self.assertTrue( results[0]["filename"].endswith("test_data/VFSFixture/etc/passwd")) self.assertIsInstance(results[0], rdf_protodict.AttributedDict) self.assertEqual(len(results[0]["users"]), 3) self.assertIsInstance(results[1], rdf_anomaly.Anomaly) self.assertEqual(len(results[2]["users"]), 1000)