Exemplo n.º 1
0
    def resolve(self):

        IDP = [
            "AWS::Iam::User", "AWS::Iam::Role", "AWS::Iam::Group",
            "AWS::Iam::Policy"
        ]

        RBP = {"AWS::S3::Bucket": "Policy", "AWS::Iam::Role": "Trusts"}

        (principals, actions, trusts) = (Elements(), Elements(), Elements())
        resources = self.get("Resource") + self.get("Generic")

        print("[*] Resolving actions and resources\n")

        # Resolve actions
        for resource in self.get("Resource"):

            self._print(f"[*] Processing {resource}")

            # Identity Based Policies (Inline and Managed)

            if resource.labels()[0] in IDP:

                count = len(actions)
                actions.extend(
                    IdentityBasedPolicy(resource, resources).resolve())

                diff = len(actions) - count
                if diff > 0:
                    self._print(f"[+] Identity based Policy ({resource}) "
                                "resolved to {diff} action(s)")

            if resource.labels()[0] in RBP.keys():

                # Bucket ACLs

                if resource.type("AWS::S3::Bucket"):

                    count = len(actions)
                    acl = BucketACL(resource, resources)

                    principals.extend(
                        [p for p in acl.principals() if p not in principals])
                    actions.extend(
                        [a for a in acl.resolve() if a not in actions])

                    diff = len(actions) - count
                    if diff > 0:
                        print(f"[+] Bucket ACL ({resource}) "
                              "resolved to {diff} action(s)")

                # Resource Based Policies

                rbp = ResourceBasedPolicy(resource,
                                          resources,
                                          keys=[RBP[resource.labels()[0]]])

                if len(rbp.principals()) > 0:

                    count = len(actions)
                    resolved = rbp.resolve()

                    principals.extend([
                        p for p in rbp.principals()
                        if p not in principals and str(p) != RESOURCES.
                        types["AWS::Account"].format(Account=self.account_id)
                    ])

                    # TODO: This code should be moved to 'ResourceBasedPolicy' and override resolve().

                    # For Roles, actions imply a TRUSTS relationship. Only those beginning
                    # with sts:Assume are considered valid.

                    for action in [
                            a for a in resolved
                            if "AWS::Iam::Role" not in resource.labels()
                            or str(a).startswith("sts:AssumeRole")
                    ]:

                        if action.source().type("AWS::Account") \
                                and action.source().properties()["Arn"].split(':')[4] == self.account_id:

                            if "AWS::Iam::Role" in resource.labels():

                                trusts.extend([
                                    Trusts(properties=action.properties(),
                                           source=action.target(),
                                           target=e) for e in self.entities
                                ])

                            # This case appears redundant for Buckets

                        else:
                            if not action.source().type("AWS::Domain"):
                                actions.append(action)

                            if "AWS::Iam::Role" in resource.labels():
                                trusts.append(
                                    Trusts(properties=action.properties(),
                                           source=action.target(),
                                           target=action.source()))

                    diff = len(actions) - count

                    if diff > 0:
                        print(f"[+] Resource based policy ({resource}) "
                              "resolved to {diff} action(s)")

        principals = [p for p in principals if p not in self]

        self.extend(principals)
        self.extend(actions)
        self.extend(trusts)

        sys.stdout.write("\033[F\033[K")
        print(
            f"[+] Produced {len(principals)} new principals and {len(actions)} actions\n"
        )
Exemplo n.º 2
0
    def load_actions(self):

        self.add(
            Node(labels=["CatchAll"],
                 properties={
                     "Name":
                     "CatchAll",
                     "Description":
                     "A sinkhole for actions affecting unknown resource types."
                 }))

        # Resource types Actions affect
        resources = Elements(e for e in self if any(
            [l in ["Resource", "Generic", "CatchAll"] for l in e.labels()]))

        # IAM entities
        entities = Elements(
            e for e in self.get("Resource")
            if e.label() in ['AWS::Iam::User', 'AWS::Iam::Role'])

        for resource in self.console.tasklist(
                "Resolving Policy information",
                iterables=self.get("Resource"),
                done="Added Action relationships"):

            # Identity-based policies (inline and managed)
            if resource.label() in [
                    "AWS::Iam::User", "AWS::Iam::Group", "AWS::Iam::Role",
                    "AWS::Iam::Policy"
            ]:

                self.update(IdentityBasedPolicy(resource, resources).actions())

            # Resource-based policies
            if resource.label() in [
                    "AWS::S3::Bucket",
                    "AWS::S3::Object",
            ]:
                resource_based_policy = ResourceBasedPolicy(
                    resource=resource, resources=resources, keys="Policy")

                self.update(resource_based_policy.principals())
                self.update(resource_based_policy.actions())

            # Assume role policy documents
            if resource.label() in ["AWS::Iam::Role"]:

                resource_based_policy = ResourceBasedPolicy(
                    resource=resource, resources=resources, keys="Trusts")

                # Skip AWS::Domain principals
                self.update(
                    Elements(
                        principal
                        for principal in resource_based_policy.principals()
                        if not principal.type("AWS::Domain")))

                # Only actions beginning with sts:AssumeRole are valid
                for action in [
                        action for action in resource_based_policy.actions()
                        if str(action).startswith("sts:AssumeRole")
                ]:

                    # This role trusts all IAM entities within this account
                    if (action.source().type("AWS::Account")
                            and len(action.source().id().split(':')) >= 5
                            and action.source().id().split(':')[4]
                            == self.account):
                        self.update(
                            Elements(
                                Trusts(properties=action.properties(),
                                       source=action.target(),
                                       target=entity) for entity in entities))

                    else:
                        # Skip AWS::Domain actions
                        if action.source().type("AWS::Domain"):
                            continue

                        self.add(action)
                        self.add(
                            Trusts(properties=action.properties(),
                                   source=action.target(),
                                   target=action.source()))

            # ACLs (bucket & objects)
            if resource.label() in ["AWS::S3::Bucket", "AWS::S3::Object"]:

                acl = BucketACL(resource, resources) \
                    if resource.label() == "AWS::S3::Bucket" \
                    else ObjectACL(resource, resources)

                self.update(acl.principals())
                self.update(acl.actions())