Example #1
0
  def testFileFinderThrottlingByFlowCountWorks(self):
    self.InitRouterConfig(self.__class__.FILE_FINDER_THROTTLED_ROUTER_CONFIG %
                          self.token.username)

    args = []
    for p in ["tests.plist", "numbers.txt", "numbers.txt.ver2"]:
      args.append(
          rdf_file_finder.FileFinderArgs(
              action=rdf_file_finder.FileFinderAction(action_type="STAT"),
              paths=[p]).AsPrimitiveProto())

    client_ref = self.api.Client(client_id=self.client_id.Basename())

    flow_obj = client_ref.CreateFlow(
        name=file_finder.FileFinder.__name__, args=args[0])
    self.assertEqual(flow_obj.data.state, flow_obj.data.RUNNING)

    flow_obj = client_ref.CreateFlow(
        name=file_finder.FileFinder.__name__, args=args[1])
    self.assertEqual(flow_obj.data.state, flow_obj.data.RUNNING)

    with self.assertRaisesRegexp(RuntimeError, "2 flows run since"):
      client_ref.CreateFlow(name=file_finder.FileFinder.__name__, args=args[2])
Example #2
0
    def Start(self):
        """Determine the Firefox history directory."""
        self.state.hist_count = 0
        self.state.history_paths = []

        if self.args.history_path:
            self.state.history_paths.append(self.args.history_path)
        else:
            self.state.history_paths = self.GuessHistoryPaths(
                self.args.username)

            if not self.state.history_paths:
                raise flow.FlowError("Could not find valid History paths.")

        filename = "places.sqlite"
        for path in self.state.history_paths:
            self.CallFlow(file_finder.FileFinder.__name__,
                          paths=[os.path.join(path, "**2", filename)],
                          pathtype=self.args.pathtype,
                          action=rdf_file_finder.FileFinderAction(
                              action_type=rdf_file_finder.FileFinderAction.
                              Action.DOWNLOAD),
                          next_state="ParseFiles")
Example #3
0
    def testFileFinderDownloadMaxFileSizeCanBeOverriden(self):
        router = self._CreateRouter(
            file_finder_flow=rr.RobotRouterFileFinderFlowParams(
                enabled=True, max_file_size=42))

        da = rdf_file_finder.FileFinderDownloadActionOptions()
        da.max_size = 80
        da.oversized_file_policy = da.OversizedFilePolicy.DOWNLOAD_TRUNCATED

        path = "/foo/bar"
        handler = router.CreateFlow(api_flow.ApiCreateFlowArgs(
            flow=api_flow.ApiFlow(name=file_finder.FileFinder.__name__,
                                  args=rdf_file_finder.FileFinderArgs(
                                      paths=[path],
                                      action=rdf_file_finder.FileFinderAction(
                                          action_type="DOWNLOAD",
                                          download=da))),
            client_id=self.client_id),
                                    token=self.token)

        da = handler.override_flow_args.action.download
        self.assertEqual(da.oversized_file_policy, da.OversizedFilePolicy.SKIP)
        self.assertEqual(da.max_size, 42)
Example #4
0
class TestFileFinderOSLinuxProc(base.VFSPathContentExists):
    """Download a /proc/sys entry with FileFinder."""
    platforms = ["Linux"]
    flow = "FileFinder"
    test_output_path = "/fs/os/proc/sys/net/ipv4/ip_forward"
    client_min_version = 3007

    sizecondition = rdf_file_finder.FileFinderSizeCondition(
        max_file_size=1000000)
    filecondition = rdf_file_finder.FileFinderCondition(
        condition_type=rdf_file_finder.FileFinderCondition.Type.SIZE,
        size=sizecondition)

    download = rdf_file_finder.FileFinderDownloadActionOptions()
    action = rdf_file_finder.FileFinderAction(
        action_type=rdf_file_finder.FileFinderAction.Action.DOWNLOAD,
        download=download)

    args = {
        "paths": ["/proc/sys/net/ipv4/ip_forward"],
        "conditions": filecondition,
        "action": action
    }
Example #5
0
  def setUp(self):
    super(ApiGetHuntFileHandlerTest, self).setUp()

    self.handler = hunt_plugin.ApiGetHuntFileHandler()

    self.file_path = os.path.join(self.base_path, "test.plist")
    self.hunt = hunts.GRRHunt.StartHunt(
        hunt_name="GenericHunt",
        flow_runner_args=rdf_flows.FlowRunnerArgs(
            flow_name=file_finder.FileFinder.__name__),
        flow_args=rdf_file_finder.FileFinderArgs(
            paths=[self.file_path],
            action=rdf_file_finder.FileFinderAction(action_type="DOWNLOAD"),),
        client_rate=0,
        token=self.token)
    self.hunt.Run()

    self.aff4_file_path = "fs/os/%s" % self.file_path

    self.client_id = self.SetupClients(1)[0]
    self.AssignTasksToClients(client_ids=[self.client_id])
    action_mock = action_mocks.FileFinderClientMock()
    test_lib.TestHuntHelper(action_mock, [self.client_id], token=self.token)
Example #6
0
    def testListHuntClients(self):
        hunt = implementation.GRRHunt.StartHunt(
            hunt_name=standard.GenericHunt.__name__,
            flow_runner_args=rdf_flows.FlowRunnerArgs(
                flow_name=file_finder.FileFinder.__name__),
            flow_args=rdf_file_finder.FileFinderArgs(
                paths=[os.path.join(self.base_path, "test.plist")],
                action=rdf_file_finder.FileFinderAction(
                    action_type="DOWNLOAD"),
            ),
            client_rate=0,
            token=self.token)
        hunt.Run()

        client_ids = self.SetupClients(5)
        self.AssignTasksToClients(client_ids=client_ids)
        action_mock = action_mocks.FileFinderClientMock()
        hunt_test_lib.TestHuntHelper(action_mock,
                                     client_ids,
                                     iteration_limit=10,
                                     token=self.token)

        result = self.handler.Handle(
            hunt_plugin.ApiListHuntClientsArgs(hunt_id=hunt.urn.Basename()),
            token=self.token)

        # TODO(user): This still uses data store internals and will fail on some
        # data stores.

        # This is not super deterministic, we start processing some
        # clients, run the hunt for a bit but there is no order to all
        # this. We should have some clients half finished though (i.e.,
        # with pending requests) and five clients in total.
        self.assertEqual(result.total_count, 5)
        clients = list(result.items)
        pending_requests = [client.pending_requests for client in clients]
        self.assertTrue(any(r.next_state) for r in pending_requests)
Example #7
0
    def testAttributesOfFileFoundInHashFileStoreAreSetCorrectly(self):
        client_ids = self.SetupClients(2)

        filename = os.path.join(self.base_path, "tcpip.sig")
        pathspec = rdf_paths.PathSpec(pathtype=rdf_paths.PathSpec.PathType.OS,
                                      path=filename)
        urn1 = pathspec.AFF4Path(client_ids[0])
        urn2 = pathspec.AFF4Path(client_ids[1])

        for client_id in client_ids:
            client_mock = action_mocks.FileFinderClientMock()
            for _ in flow_test_lib.TestFlowHelper(
                    file_finder.FileFinder.__name__,
                    client_mock,
                    token=self.token,
                    client_id=client_id,
                    paths=[filename],
                    action=rdf_file_finder.FileFinderAction(
                        action_type=rdf_file_finder.FileFinderAction.Action.
                        DOWNLOAD)):
                pass
            # Running worker to make sure FileStore.AddFileToStore event is processed
            # by the worker.
            worker = worker_test_lib.MockWorker(token=self.token)
            worker.Simulate()

        fd1 = aff4.FACTORY.Open(urn1, token=self.token)
        self.assertTrue(isinstance(fd1, aff4_grr.VFSBlobImage))

        fd2 = aff4.FACTORY.Open(urn2, token=self.token)
        self.assertTrue(isinstance(fd2, aff4_grr.VFSBlobImage))

        self.assertTrue(fd1.Get(fd1.Schema.STAT))
        self.assertTrue(fd2.Get(fd2.Schema.STAT))
        self.assertEqual(fd1.Get(fd1.Schema.SIZE), fd2.Get(fd2.Schema.SIZE))
        self.assertEqual(fd1.Get(fd1.Schema.CONTENT_LAST),
                         fd2.Get(fd2.Schema.CONTENT_LAST))
Example #8
0
  def Grep(self, source, pathtype):
    """Grep files in paths for any matches to content_regex_list.

    Args:
      source: artifact source
      pathtype: pathspec path type

    When multiple regexes are supplied, combine them into a single regex as an
    OR match so that we check all regexes at once.
    """
    path_list = self.InterpolateList(source.attributes.get("paths", []))
    content_regex_list = self.InterpolateList(
        source.attributes.get("content_regex_list", []))

    regex_condition = rdf_file_finder.FileFinderContentsRegexMatchCondition(
        regex=self._CombineRegex(content_regex_list),
        bytes_before=0,
        bytes_after=0,
        mode="ALL_HITS")

    file_finder_condition = rdf_file_finder.FileFinderCondition(
        condition_type=(
            rdf_file_finder.FileFinderCondition.Type.CONTENTS_REGEX_MATCH),
        contents_regex_match=regex_condition)

    self.CallFlow(
        file_finder.FileFinder.__name__,
        paths=path_list,
        conditions=[file_finder_condition],
        action=rdf_file_finder.FileFinderAction(),
        pathtype=pathtype,
        request_data={
            "artifact_name": self.current_artifact_name,
            "source": source.ToPrimitiveDict()
        },
        next_state="ProcessCollected")
Example #9
0
class TestFileFinderOSWindows(base.VFSPathContentIsPE):
  """Download a file with FileFinder.

  Exercise globbing, interpolation and filtering.
  """
  platforms = ["Windows"]
  flow = file_finder.FileFinder.__name__
  test_output_path = "/fs/os/C:/Windows/System32/notepad.exe"

  sizecondition = rdf_file_finder.FileFinderSizeCondition(max_file_size=1000000)
  filecondition = rdf_file_finder.FileFinderCondition(
      condition_type=rdf_file_finder.FileFinderCondition.Type.SIZE,
      size=sizecondition)

  download = rdf_file_finder.FileFinderDownloadActionOptions()
  action = rdf_file_finder.FileFinderAction(
      action_type=rdf_file_finder.FileFinderAction.Action.DOWNLOAD,
      download=download)

  args = {
      "paths": ["%%environ_systemroot%%\\System32\\notepad.*"],
      "conditions": filecondition,
      "action": action
  }
Example #10
0
    def Handle(self, args, token=None):
        client_urn = self.GetClientTarget(args, token=token)

        size_condition = rdf_file_finder.FileFinderCondition(
            condition_type=rdf_file_finder.FileFinderCondition.Type.SIZE,
            size=rdf_file_finder.FileFinderSizeCondition(
                max_file_size=args.max_file_size))

        file_finder_args = rdf_file_finder.FileFinderArgs(
            paths=args.paths,
            action=rdf_file_finder.FileFinderAction(action_type=args.action),
            conditions=[size_condition])

        # Check our flow throttling limits, will raise if there are problems.
        throttler = throttle.FlowThrottler(
            daily_req_limit=config_lib.CONFIG.Get("API.DailyFlowRequestLimit"),
            dup_interval=config_lib.CONFIG.Get("API.FlowDuplicateInterval"))
        throttler.EnforceLimits(client_urn,
                                token.username,
                                file_finder.FileFinder.__name__,
                                file_finder_args,
                                token=token)

        # Limit the whole flow to 200MB so if a glob matches lots of small files we
        # still don't have too much impact.
        runner_args = rdf_flows.FlowRunnerArgs(
            client_id=client_urn,
            flow_name=file_finder.FileFinder.__name__,
            network_bytes_limit=200 * 1000 * 1000)

        flow_id = flow.GRRFlow.StartFlow(runner_args=runner_args,
                                         token=token,
                                         args=file_finder_args)

        return ApiStartRobotGetFilesOperationResult(
            operation_id=utils.SmartUnicode(flow_id))
Example #11
0
    def testLinkStat(self):
        """Tests resolving symlinks when getting stat entries."""
        test_dir = os.path.join(self.temp_dir, "lnk_stat_test")
        lnk = os.path.join(test_dir, "lnk")
        lnk_target = os.path.join(test_dir, "lnk_target")

        os.mkdir(test_dir)
        with open(lnk_target, "wb") as fd:
            fd.write("sometext")
        os.symlink(lnk_target, lnk)

        paths = [lnk]
        link_size = os.lstat(lnk).st_size
        target_size = os.stat(lnk).st_size
        for expected_size, resolve_links in [(link_size, False),
                                             (target_size, True)]:
            stat_action = rdf_file_finder.FileFinderAction(
                action_type=rdf_file_finder.FileFinderAction.Action.STAT,
                stat=rdf_file_finder.FileFinderStatActionOptions(
                    resolve_links=resolve_links))
            results = self._RunFileFinder(paths, stat_action)
            self.assertEqual(len(results), 1)
            res = results[0]
            self.assertEqual(res.stat_entry.st_size, expected_size)
Example #12
0
  def testClientFileFinderUploadSkip(self):
    paths = [os.path.join(self.base_path, "**/*.plist")]
    action_type = rdf_file_finder.FileFinderAction.Action.DOWNLOAD
    download_action = rdf_file_finder.FileFinderDownloadActionOptions(
        oversized_file_policy="SKIP", max_size=300)
    action = rdf_file_finder.FileFinderAction(
        action_type=action_type, download=download_action)

    session_id = self._RunClientFileFinder(paths, action)
    collection = aff4.FACTORY.Open(session_id.Add("Results"), token=self.token)
    results = list(collection)
    # Only two instead of the usual four results.
    self.assertEqual(len(results), 2)
    relpaths = [
        os.path.relpath(p.stat_entry.pathspec.path, self.base_path)
        for p in results
    ]
    self.assertItemsEqual(relpaths, ["History.plist", "test.plist"])

    for r in results:
      aff4_obj = aff4.FACTORY.Open(
          r.stat_entry.pathspec.AFF4Path(self.client_id), token=self.token)
      self.assertEqual(
          aff4_obj.Read(100), open(r.stat_entry.pathspec.path, "rb").read(100))
Example #13
0
  def RunFlowAndCheckResults(
      self,
      conditions=None,
      action=rdf_file_finder.FileFinderAction.Action.STAT,
      expected_files=None,
      non_expected_files=None,
      paths=None):
    if not isinstance(action, rdf_file_finder.FileFinderAction):
      action = rdf_file_finder.FileFinderAction(action_type=action)
    action_type = action.action_type

    conditions = conditions or []
    expected_files = expected_files or []
    non_expected_files = non_expected_files or []

    for fname in expected_files + non_expected_files:
      aff4.FACTORY.Delete(self.FileNameToURN(fname), token=self.token)

    results = self.RunFlow(paths=paths, conditions=conditions, action=action)
    self.CheckReplies(results, action_type, expected_files)

    self.CheckFilesInCollection(expected_files)

    if action_type == rdf_file_finder.FileFinderAction.Action.STAT:
      self.CheckFilesNotDownloaded(expected_files + non_expected_files)
      self.CheckFilesNotHashed(expected_files + non_expected_files)
    elif action_type == rdf_file_finder.FileFinderAction.Action.DOWNLOAD:
      self.CheckFilesHashed(expected_files)
      self.CheckFilesNotHashed(non_expected_files)
      self.CheckFilesDownloaded(expected_files)
      self.CheckFilesNotDownloaded(non_expected_files)
      # Downloaded files are hashed to allow for deduping.
    elif action_type == rdf_file_finder.FileFinderAction.Action.HASH:
      self.CheckFilesNotDownloaded(expected_files + non_expected_files)
      self.CheckFilesHashed(expected_files)
      self.CheckFilesNotHashed(non_expected_files)
Example #14
0
  def testFileFinderWorkflowWorks(self):
    self.InitRouterConfig(
        self.__class__.FILE_FINDER_ROUTER_CONFIG % self.token.username)

    client_ref = self.api.Client(client_id=self.client_id.Basename())

    args = rdf_file_finder.FileFinderArgs(
        paths=[
            os.path.join(self.base_path, "test.plist"),
            os.path.join(self.base_path, "numbers.txt"),
            os.path.join(self.base_path, "numbers.txt.ver2")
        ],
        action=rdf_file_finder.FileFinderAction(
            action_type=rdf_file_finder.FileFinderAction.Action.DOWNLOAD)
    ).AsPrimitiveProto()
    flow_obj = client_ref.CreateFlow(
        name=file_finder.FileFinder.__name__, args=args)
    self.assertEqual(flow_obj.data.state, flow_obj.data.RUNNING)

    # Now run the flow we just started.
    client_id = rdf_client.ClientURN(flow_obj.client_id)
    flow_urn = client_id.Add("flows").Add(flow_obj.flow_id)
    for _ in flow_test_lib.TestFlowHelper(
        flow_urn,
        client_id=client_id,
        client_mock=action_mocks.FileFinderClientMock(),
        token=self.token):
      pass

    # Refresh flow.
    flow_obj = client_ref.Flow(flow_obj.flow_id).Get()
    self.assertEqual(flow_obj.data.state, flow_obj.data.TERMINATED)

    # Check that we got 3 results (we downloaded 3 files).
    results = list(flow_obj.ListResults())
    self.assertEqual(len(results), 3)
    # We expect results to be FileFinderResult.
    self.assertItemsEqual(
        [os.path.basename(r.payload.stat_entry.pathspec.path)
         for r in results], ["test.plist", "numbers.txt", "numbers.txt.ver2"])

    # Now downloads the files archive.
    zip_stream = StringIO.StringIO()
    flow_obj.GetFilesArchive().WriteToStream(zip_stream)
    zip_fd = zipfile.ZipFile(zip_stream)

    # Now check that the archive has only "test.plist" file, as it's the
    # only file that matches the whitelist (see FILE_FINDER_ROUTER_CONFIG).
    # There should be 3 items in the archive: the hash of the "test.plist"
    # file, the symlink to this hash and the MANIFEST file.
    namelist = zip_fd.namelist()
    self.assertEqual(len(namelist), 3)

    # First component of every path in the archive is the containing folder,
    # we should strip it.
    namelist = [os.path.join(*n.split(os.sep)[1:]) for n in namelist]
    with open(os.path.join(self.base_path, "test.plist")) as test_plist_fd:
      test_plist_hash = hashlib.sha256(test_plist_fd.read()).hexdigest()
    self.assertEqual(
        sorted([
            # pyformat: disable
            os.path.join(self.client_id.Basename(), "fs", "os",
                         self.base_path.strip("/"), "test.plist"),
            os.path.join("hashes", test_plist_hash),
            "MANIFEST"
            # pyformat: enable
        ]),
        sorted(namelist))
Example #15
0
    def testFlowDuplicateLimit(self):
        # Disable the request limit checking by setting it to 0.
        throttler = throttle.FlowThrottler(
            daily_req_limit=0, dup_interval=rdfvalue.Duration("1200s"))

        # Running the same flow immediately should fail
        with test_lib.FakeTime(self.BASE_TIME):
            throttler.EnforceLimits(self.client_id,
                                    self.token.username,
                                    "DummyLogFlow",
                                    None,
                                    token=self.token)

            flow.GRRFlow.StartFlow(client_id=self.client_id,
                                   flow_name="DummyLogFlow",
                                   token=self.token)

            with self.assertRaises(throttle.ErrorFlowDuplicate):
                throttler.EnforceLimits(self.client_id,
                                        self.token.username,
                                        "DummyLogFlow",
                                        None,
                                        token=self.token)

        # Doing the same outside the window should work
        with test_lib.FakeTime(self.BASE_TIME + 1200 + 1):
            throttler.EnforceLimits(self.client_id,
                                    self.token.username,
                                    "DummyLogFlow",
                                    None,
                                    token=self.token)

            flow.GRRFlow.StartFlow(client_id=self.client_id,
                                   flow_name="DummyLogFlow",
                                   token=self.token)

            with self.assertRaises(throttle.ErrorFlowDuplicate):
                throttler.EnforceLimits(self.client_id,
                                        self.token.username,
                                        "DummyLogFlow",
                                        None,
                                        token=self.token)

        # Now try a flow with more complicated args
        args = rdf_file_finder.FileFinderArgs(
            paths=["/tmp/1", "/tmp/2"],
            action=rdf_file_finder.FileFinderAction(action_type="STAT"))

        with test_lib.FakeTime(self.BASE_TIME):
            throttler.EnforceLimits(self.client_id,
                                    self.token.username,
                                    file_finder.FileFinder.__name__,
                                    args,
                                    token=self.token)

            flow.GRRFlow.StartFlow(
                client_id=self.client_id,
                flow_name=file_finder.FileFinder.__name__,
                token=self.token,
                paths=["/tmp/1", "/tmp/2"],
                action=rdf_file_finder.FileFinderAction(action_type="STAT"))

            with self.assertRaises(throttle.ErrorFlowDuplicate):
                throttler.EnforceLimits(self.client_id,
                                        self.token.username,
                                        file_finder.FileFinder.__name__,
                                        args,
                                        token=self.token)

            # Different args should succeed.
            args = rdf_file_finder.FileFinderArgs(
                paths=["/tmp/1", "/tmp/3"],
                action=rdf_file_finder.FileFinderAction(action_type="STAT"))

            throttler.EnforceLimits(self.client_id,
                                    self.token.username,
                                    file_finder.FileFinder.__name__,
                                    args,
                                    token=self.token)
Example #16
0
 def setUp(self):
     super(FileFinderTest, self).setUp()
     self.stat_action = rdf_file_finder.FileFinderAction(
         action_type=rdf_file_finder.FileFinderAction.Action.STAT)
Example #17
0
 def _StatAction(**kwargs):
     action_type = rdf_file_finder.FileFinderAction.Action.STAT
     opts = rdf_file_finder.FileFinderStatActionOptions(**kwargs)
     return rdf_file_finder.FileFinderAction(action_type=action_type,
                                             stat=opts)