Пример #1
0
 def testDeleteSignedBinary(self):
   binary1_urn = rdfvalue.RDFURN("aff4:/config/executables/foo1")
   binary2_urn = rdfvalue.RDFURN("aff4:/config/executables/foo2")
   signed_binary_utils.WriteSignedBinaryBlobs(
       binary1_urn, [rdf_crypto.SignedBlob().Sign(b"\x00", self._private_key)])
   signed_binary_utils.WriteSignedBinaryBlobs(
       binary2_urn, [rdf_crypto.SignedBlob().Sign(b"\x11", self._private_key)])
   self.assertCountEqual(signed_binary_utils.FetchURNsForAllSignedBinaries(),
                         [binary1_urn, binary2_urn])
   signed_binary_utils.DeleteSignedBinary(binary1_urn)
   self.assertCountEqual(signed_binary_utils.FetchURNsForAllSignedBinaries(),
                         [binary2_urn])
Пример #2
0
 def testWriteSignedBinaryBlobs(self):
     test_urn = rdfvalue.RDFURN("aff4:/config/executables/foo")
     test_blobs = [
         rdf_crypto.SignedBlob().Sign(b"\x00\x11\x22", self._private_key),
         rdf_crypto.SignedBlob().Sign(b"\x33\x44\x55", self._private_key),
         rdf_crypto.SignedBlob().Sign(b"\x66\x77\x88", self._private_key),
         rdf_crypto.SignedBlob().Sign(b"\x99", self._private_key)
     ]
     signed_binary_utils.WriteSignedBinaryBlobs(test_urn, test_blobs)
     blobs_iter, timestamp = signed_binary_utils.FetchBlobsForSignedBinaryByURN(
         test_urn)
     self.assertGreater(timestamp.AsMicrosecondsSinceEpoch(), 0)
     self.assertCountEqual(list(blobs_iter), test_blobs)
Пример #3
0
  def testExecutePythonEnvironment(self):
    """Test the basic ExecutePython action."""

    python_code = """
import io
import uu

def decode(encoded):
  # Use the import (uu) inside a function. This will fail if the environment
  # for exec is not set up properly.
  i = io.BytesIO(s)
  o = io.BytesIO()
  uu.decode(i, o)
  return o.getvalue()

s = "626567696e20363636202d0a2c3226354c3b265c4035565d523b2630410a200a656e640a"
s = s.decode("hex")

magic_return_str = decode(s)
"""
    signed_blob = rdf_crypto.SignedBlob()
    signed_blob.Sign(python_code.encode("utf-8"), self.signing_key)
    request = rdf_client_action.ExecutePythonRequest(python_code=signed_blob)
    result = self.RunAction(standard.ExecutePython, request)[0]

    self.assertTrue(result.time_used > 0)
    self.assertEqual(result.return_val, "Hello World!")
Пример #4
0
    def testExecuteModifiedPython(self):
        """Test that rejects invalid ExecutePython action."""
        utils.TEST_VAL = "original"
        python_code = "utils.TEST_VAL = 'modified'"
        signed_blob = rdf_crypto.SignedBlob()
        signed_blob.Sign(python_code.encode("utf-8"), self.signing_key)

        # Modify the data so the signature does not match.
        signed_blob.data = b"utils.TEST_VAL = 'notmodified'"

        request = rdf_client_action.ExecutePythonRequest(
            python_code=signed_blob)

        # Should raise since the code has been modified.
        self.assertRaises(rdf_crypto.VerificationError, self.RunAction,
                          standard.ExecutePython, request)

        # Lets also adjust the hash.
        signed_blob.digest = hashlib.sha256(signed_blob.data).digest()
        request = rdf_client_action.ExecutePythonRequest(
            python_code=signed_blob)

        self.assertRaises(rdf_crypto.VerificationError, self.RunAction,
                          standard.ExecutePython, request)

        # Make sure the code never ran.
        self.assertEqual(utils.TEST_VAL, "original")
Пример #5
0
    def testExecutePythonEnvironment(self):
        """Test the basic ExecutePython action."""

        python_code = """
import io
import uu
import binascii

def decode(encoded):
  # Use the import (uu) inside a function. This will fail if the environment
  # for exec is not set up properly.
  i = io.BytesIO(s)
  o = io.BytesIO()
  uu.decode(i, o)
  return o.getvalue()

s = "626567696e20363636202d0a2c3226354c3b265c4035565d523b2630410a200a656e640a"
s = binascii.unhexlify(s.encode("ascii"))

magic_return_str = decode(s)
"""
        signed_blob = rdf_crypto.SignedBlob()
        signed_blob.Sign(python_code.encode("utf-8"), self.signing_key)
        request = rdf_client_action.ExecutePythonRequest(
            python_code=signed_blob)
        result = self.RunAction(standard.ExecutePython, request)[0]

        if platform.system(
        ) != "Windows":  # Windows time resolution is too coarse.
            self.assertGreater(result.time_used, 0)
        self.assertEqual(result.return_val, "Hello World!")
Пример #6
0
def WriteSignedBinary(binary_urn: rdfvalue.RDFURN,
                      binary_content: bytes,
                      private_key: rdf_crypto.RSAPrivateKey,
                      public_key: Optional[rdf_crypto.RSAPublicKey],
                      chunk_size: int = 1024):
    """Signs a binary and saves it to the datastore.

  If a signed binary with the given URN already exists, its contents will get
  overwritten.

  Args:
    binary_urn: URN that should serve as a unique identifier for the binary.
    binary_content: Contents of the binary, as raw bytes.
    private_key: Key that should be used for signing the binary contents.
    public_key: Key that should be used to verify the signature generated using
      the private key.
    chunk_size: Size, in bytes, of the individual blobs that the binary contents
      will be split to before saving to the datastore.
  """
    blob_references = rdf_objects.BlobReferences()
    for chunk_offset in range(0, len(binary_content), chunk_size):
        chunk = binary_content[chunk_offset:chunk_offset + chunk_size]
        blob_rdf = rdf_crypto.SignedBlob()
        blob_rdf.Sign(chunk, private_key, verify_key=public_key)
        blob_id = data_store.BLOBS.WriteBlobWithUnknownHash(
            blob_rdf.SerializeToBytes())
        blob_references.items.Append(
            rdf_objects.BlobReference(offset=chunk_offset,
                                      size=len(chunk),
                                      blob_id=blob_id))
    data_store.REL_DB.WriteSignedBinaryReferences(
        SignedBinaryIDFromURN(binary_urn), blob_references)
Пример #7
0
  def testExecuteBrokenPython(self):
    """Test broken code raises back to the original flow."""
    python_code = "raise ValueError"
    signed_blob = rdf_crypto.SignedBlob()
    signed_blob.Sign(python_code.encode("utf-8"), self.signing_key)
    request = rdf_client_action.ExecutePythonRequest(python_code=signed_blob)

    self.assertRaises(ValueError, self.RunAction, standard.ExecutePython,
                      request)
Пример #8
0
 def testFetchSizeOfSignedBinary(self):
     binary1_urn = rdfvalue.RDFURN("aff4:/config/executables/foo1")
     binary2_urn = rdfvalue.RDFURN("aff4:/config/executables/foo2")
     binary1_data = b"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99"
     binary2_blobs = [
         rdf_crypto.SignedBlob().Sign(b"\x00\x11\x22", self._private_key),
         rdf_crypto.SignedBlob().Sign(b"\x33\x44", self._private_key)
     ]
     signed_binary_utils.WriteSignedBinary(binary1_urn,
                                           binary1_data,
                                           private_key=self._private_key,
                                           public_key=self._public_key,
                                           chunk_size=3)
     signed_binary_utils.WriteSignedBinaryBlobs(binary2_urn, binary2_blobs)
     binary1_size = signed_binary_utils.FetchSizeOfSignedBinary(binary1_urn)
     binary2_size = signed_binary_utils.FetchSizeOfSignedBinary(binary2_urn)
     self.assertEqual(binary1_size, 10)
     self.assertEqual(binary2_size, 5)
Пример #9
0
  def testReturnVals(self):
    """Test return values."""
    python_code = "magic_return_str = 'return string'"
    signed_blob = rdf_crypto.SignedBlob()
    signed_blob.Sign(python_code.encode("utf-8"), self.signing_key)
    request = rdf_client_action.ExecutePythonRequest(python_code=signed_blob)
    result = self.RunAction(standard.ExecutePython, request)[0]

    self.assertEqual(result.return_val, "return string")
Пример #10
0
 def testWriteSignedBinary(self):
     binary_data = b"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99"  # 10 bytes.
     test_urn = rdfvalue.RDFURN("aff4:/config/executables/foo")
     signed_binary_utils.WriteSignedBinary(test_urn,
                                           binary_data,
                                           private_key=self._private_key,
                                           public_key=self._public_key,
                                           chunk_size=3)
     blobs_iter, timestamp = signed_binary_utils.FetchBlobsForSignedBinaryByURN(
         test_urn)
     self.assertGreater(timestamp.AsMicrosecondsSinceEpoch(), 0)
     self.assertIsInstance(blobs_iter, collections.Iterator)
     # We expect blobs to have at most 3 contiguous bytes of data.
     expected_blobs = [
         rdf_crypto.SignedBlob().Sign(b"\x00\x11\x22", self._private_key),
         rdf_crypto.SignedBlob().Sign(b"\x33\x44\x55", self._private_key),
         rdf_crypto.SignedBlob().Sign(b"\x66\x77\x88", self._private_key),
         rdf_crypto.SignedBlob().Sign(b"\x99", self._private_key)
     ]
     self.assertCountEqual(list(blobs_iter), expected_blobs)
Пример #11
0
  def testWrongKey(self):
    """Test return values."""
    python_code = "print 'test'"

    # Generate a test valid RSA key that isn't the real one.
    signing_key = rdf_crypto.RSAPrivateKey.GenerateKey(2048, 65537)
    signed_blob = rdf_crypto.SignedBlob()
    signed_blob.Sign(python_code.encode("utf-8"), signing_key)
    request = rdf_client_action.ExecutePythonRequest(python_code=signed_blob)
    self.assertRaises(rdf_crypto.VerificationError, self.RunAction,
                      standard.ExecutePython, request)
Пример #12
0
  def testReadIndividualBlobsFromSignedBinary(self):
    test_urn = rdfvalue.RDFURN("aff4:/config/executables/foo")
    test_blobs = [
        rdf_crypto.SignedBlob().Sign(b"\x00\x11\x22", self._private_key),
        rdf_crypto.SignedBlob().Sign(b"\x33\x44\x55", self._private_key),
        rdf_crypto.SignedBlob().Sign(b"\x66\x77\x88", self._private_key),
        rdf_crypto.SignedBlob().Sign(b"\x99", self._private_key)
    ]
    signed_binary_utils.WriteSignedBinaryBlobs(test_urn, test_blobs)

    with self.assertRaises(ValueError):
      signed_binary_utils.FetchBlobForSignedBinaryByURN(test_urn, -1)

    for i, test_blob in enumerate(test_blobs):
      blob = signed_binary_utils.FetchBlobForSignedBinaryByURN(test_urn, i)
      self.assertEqual(blob.data, test_blob.data)

    with self.assertRaises(signed_binary_utils.BlobIndexOutOfBoundsError):
      signed_binary_utils.FetchBlobForSignedBinaryByURN(test_urn,
                                                        len(test_blobs))
Пример #13
0
  def testExecutePython(self):
    """Test the basic ExecutePython action."""
    utils.TEST_VAL = "original"
    python_code = "utils.TEST_VAL = 'modified'"
    signed_blob = rdf_crypto.SignedBlob()
    signed_blob.Sign(python_code.encode("utf-8"), self.signing_key)
    request = rdf_client_action.ExecutePythonRequest(python_code=signed_blob)
    result = self.RunAction(standard.ExecutePython, request)[0]

    self.assertTrue(result.time_used > 0)
    self.assertEqual(result.return_val, "")
    self.assertEqual(utils.TEST_VAL, "modified")
Пример #14
0
  def testExecuteBinary(self):
    """Test the basic ExecuteBinaryCommand action."""
    signed_blob = rdf_crypto.SignedBlob()
    signed_blob.Sign(open("/bin/ls", "rb").read(), self.signing_key)

    request = rdf_client_action.ExecuteBinaryRequest(
        executable=signed_blob, args=[__file__], write_path="ablob")

    result = self.RunAction(standard.ExecuteBinaryCommand, request)[0]

    self.assertTrue(result.time_used > 0)
    self.assertTrue(__file__ in result.stdout)
Пример #15
0
  def testExecutePython(self):
    """Test the basic ExecutePython action."""
    utils.TEST_VAL = "original"
    python_code = "utils.TEST_VAL = 'modified'"
    signed_blob = rdf_crypto.SignedBlob()
    signed_blob.Sign(python_code.encode("utf-8"), self.signing_key)
    request = rdf_client_action.ExecutePythonRequest(python_code=signed_blob)
    result = self.RunAction(standard.ExecutePython, request)[0]

    if platform.system() != "Windows":  # Windows time resolution is too coarse.
      self.assertGreater(result.time_used, 0)
    self.assertEqual(result.return_val, "")
    self.assertEqual(utils.TEST_VAL, "modified")
Пример #16
0
  def testExecuteBinary(self):
    """Test the basic ExecuteBinaryCommand action."""
    signed_blob = rdf_crypto.SignedBlob()
    signed_blob.Sign(open("/bin/ls", "rb").read(), self.signing_key)

    filepath = __file__.encode(sys.getfilesystemencoding())

    request = rdf_client_action.ExecuteBinaryRequest(
        executable=signed_blob, args=[filepath], write_path="ablob")

    result = self.RunAction(standard.ExecuteBinaryCommand, request)[0]

    self.assertGreater(result.time_used, 0)
    self.assertIn(filepath, result.stdout)
Пример #17
0
    def testArgs(self):
        """Test passing arguments."""
        utils.TEST_VAL = "original"
        python_code = """
magic_return_str = py_args['test']
utils.TEST_VAL = py_args[43]
"""
        signed_blob = rdf_crypto.SignedBlob()
        signed_blob.Sign(python_code.encode("utf-8"), self.signing_key)
        pdict = rdf_protodict.Dict({"test": "dict_arg", 43: "dict_arg2"})
        request = rdf_client_action.ExecutePythonRequest(
            python_code=signed_blob, py_args=pdict)
        result = self.RunAction(standard.ExecutePython, request)[0]
        self.assertEqual(result.return_val, "dict_arg")
        self.assertEqual(utils.TEST_VAL, "dict_arg2")
Пример #18
0
  def testStdoutHooking(self):
    python_code = """

def f(n):
    print("F called: %s" % n)

print("Calling f.")
f(1)
print("Done.")
"""
    signed_blob = rdf_crypto.SignedBlob()
    signed_blob.Sign(python_code.encode("utf-8"), self.signing_key)
    request = rdf_client_action.ExecutePythonRequest(python_code=signed_blob)
    result = self.RunAction(standard.ExecutePython, request)[0]

    self.assertTrue(result.time_used > 0)
    self.assertEqual(result.return_val, "Calling f.\nF called: 1\nDone.\n")
Пример #19
0
  def testProgress(self):
    python_code = """

def f():
    # This should also work inside a function.
    Progress()

f()
Progress()
print("Done.")
"""
    signed_blob = rdf_crypto.SignedBlob()
    signed_blob.Sign(python_code.encode("utf-8"), self.signing_key)
    request = rdf_client_action.ExecutePythonRequest(python_code=signed_blob)
    result = self.RunAction(standard.ExecutePython, request)[0]

    self.assertTrue(result.time_used > 0)
    self.assertEqual(result.return_val, "Done.\n")
Пример #20
0
  def testStdoutHooking(self):
    python_code = """

def f(n):
    print("F called: %s" % n)

print("Calling f.")
f(1)
print("Done.")
"""
    signed_blob = rdf_crypto.SignedBlob()
    signed_blob.Sign(python_code.encode("utf-8"), self.signing_key)
    request = rdf_client_action.ExecutePythonRequest(python_code=signed_blob)
    result = self.RunAction(standard.ExecutePython, request)[0]

    if platform.system() != "Windows":  # Windows time resolution is too coarse.
      self.assertGreater(result.time_used, 0)
    self.assertEqual(result.return_val, "Calling f.\nF called: 1\nDone.\n")
Пример #21
0
  def testExecuteBinary(self):
    """Test the basic ExecuteBinaryCommand action."""
    if platform.system() == "Windows":
      cmd, args = r"C:\Windows\System32\cmd.exe", ["/C", "echo", "foobar"]
    else:
      cmd, args = "/bin/echo", ["foobar"]

    signed_blob = rdf_crypto.SignedBlob()
    signed_blob.Sign(open(cmd, "rb").read(), self.signing_key)

    request = rdf_client_action.ExecuteBinaryRequest(
        executable=signed_blob, args=args, write_path="ablob")

    result = self.RunAction(standard.ExecuteBinaryCommand, request)[0]

    if platform.system() != "Windows":  # Windows time resolution is too coarse.
      self.assertGreater(result.time_used, 0)
    self.assertEqual("foobar{}".format(os.linesep).encode("utf-8"),
                     result.stdout)
Пример #22
0
def WriteSignedBinary(binary_urn,
                      binary_content,
                      private_key,
                      public_key,
                      chunk_size=1024,
                      token=None):
    """Signs a binary and saves it to the datastore.

  If a signed binary with the given URN already exists, its contents will get
  overwritten.

  Args:
    binary_urn: URN that should serve as a unique identifier for the binary.
    binary_content: Contents of the binary, as raw bytes.
    private_key: Key that should be used for signing the binary contents.
    public_key: Key that should be used to verify the signature generated using
      the private key.
    chunk_size: Size, in bytes, of the individual blobs that the binary contents
      will be split to before saving to the datastore.
    token: ACL token to use with the legacy (non-relational) datastore.
  """
    if _ShouldUseLegacyDatastore():
        collects.GRRSignedBlob.NewFromContent(binary_content,
                                              binary_urn,
                                              chunk_size=chunk_size,
                                              token=token,
                                              private_key=private_key,
                                              public_key=public_key)

    if data_store.RelationalDBWriteEnabled():
        blob_references = rdf_objects.BlobReferences()
        for chunk_offset in range(0, len(binary_content), chunk_size):
            chunk = binary_content[chunk_offset:chunk_offset + chunk_size]
            blob_rdf = rdf_crypto.SignedBlob()
            blob_rdf.Sign(chunk, private_key, verify_key=public_key)
            blob_id = data_store.BLOBS.WriteBlobWithUnknownHash(
                blob_rdf.SerializeToString())
            blob_references.items.Append(
                rdf_objects.BlobReference(offset=chunk_offset,
                                          size=len(chunk),
                                          blob_id=blob_id))
        data_store.REL_DB.WriteSignedBinaryReferences(
            _SignedBinaryIDFromURN(binary_urn), blob_references)
Пример #23
0
  def testProgress(self):
    python_code = """

def f():
    # This should also work inside a function.
    Progress()

f()
Progress()
print("Done.")
"""
    signed_blob = rdf_crypto.SignedBlob()
    signed_blob.Sign(python_code.encode("utf-8"), self.signing_key)
    request = rdf_client_action.ExecutePythonRequest(python_code=signed_blob)
    result = self.RunAction(standard.ExecutePython, request)[0]

    if platform.system() != "Windows":  # Windows time resolution is too coarse.
      self.assertGreater(result.time_used, 0)
    self.assertEqual(result.return_val, "Done.\n")
Пример #24
0
    def NewFromContent(cls,
                       content,
                       urn,
                       chunk_size=1024,
                       token=None,
                       private_key=None,
                       public_key=None):
        """Alternate constructor for GRRSignedBlob.

    Creates a GRRSignedBlob from a content string by chunking it and signing
    each chunk.

    Args:
      content: The data to stored in the GRRSignedBlob.
      urn: The AFF4 URN to create.

      chunk_size: Data will be chunked into this size (each chunk is
        individually signed.
      token: The ACL Token.
      private_key: An rdf_crypto.RSAPrivateKey() instance.
      public_key: An rdf_crypto.RSAPublicKey() instance.

    Returns:
      the URN of the new object written.
    """
        aff4.FACTORY.Delete(urn, token=token)
        with data_store.DB.GetMutationPool() as pool:
            with aff4.FACTORY.Create(urn,
                                     cls,
                                     mode="w",
                                     mutation_pool=pool,
                                     token=token) as fd:
                for start_of_chunk in range(0, len(content), chunk_size):
                    chunk = content[start_of_chunk:start_of_chunk + chunk_size]
                    blob_rdf = rdf_crypto.SignedBlob()
                    blob_rdf.Sign(chunk, private_key, public_key)
                    fd.Add(blob_rdf, mutation_pool=pool)

        return urn