Detection rules › Panther

AWS KMS Key Restricts Usage

Severity
high
Compliance
PCI 3.5.2
Tags
AWS, PCI, Credential Access:Unsecured Credentials
Reference
https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html
Source
github.com/panther-labs/panther-analysis

This policy validates that KMS Keys restrict what entities can use them and how. This is to ensure that encryption keys are limited in who can use them in order to prevent unapproved decryption.

MITRE ATT&CK coverage

TacticTechniques
Credential AccessT1552 Unsecured Credentials

Rule body yaml

AnalysisType: policy
Filename: aws_kms_key_policy_restricts_usage.py
PolicyID: "AWS.KMS.RestrictsUsage"
DisplayName: "AWS KMS Key Restricts Usage"
Enabled: true
ResourceTypes:
  - AWS.KMS.Key
Tags:
  - AWS
  - PCI
  - Credential Access:Unsecured Credentials
Reports:
  PCI:
    - 3.5.2
  MITRE ATT&CK:
    - TA0006:T1552
Severity: High
Description: >
  This policy validates that KMS Keys restrict what entities can use them and how. This is to ensure that encryption keys are limited in who can use them in order to prevent unapproved decryption.
Runbook: Add appropriate limitations to the KMS Key's policy.
Reference: https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html
Tests:
  - Name: Key Usage Not Restricted
    ExpectedResult: false
    Resource:
      {
        "KeyRotationEnabled": true,
        "AWSAccountId": "1122334455",
        "Arn": "arn:aws:kms:us-west-2:11223344:key/1122233-asdf-adsf-111222333",
        "CloudHsmClusterId": null,
        "CreationDate": "2019-01-01T00:00:00Z",
        "CustomKeyStoreId": null,
        "DeletionDate": null,
        "Description": "Default master key that protects my Secrets Manager data when no other key is defined",
        "Enabled": false,
        "ExpirationModel": null,
        "KeyId": "1122233-asdf-adsf-111222333",
        "KeyManager": "AWS",
        "KeyState": "Enabled",
        "KeyUsage": "ENCRYPT_DECRYPT",
        "Origin": "AWS_KMS",
        "ValidTo": null,
        "Policy": "{\n  \"Version\" : \"2012-10-17\",\n  \"Id\" : \"use-key\",\n  \"Statement\" : [ {\n    \"Sid\" : \"Allow access\",\n    \"Effect\" : \"Allow\",\n    \"Principal\" : {\n      \"AWS\" : \"*\"\n    },\n    \"Action\" : [ \"kms:*\", \"kms:Decrypt\", \"kms:ReEncrypt*\", \"kms:GenerateDataKey*\", \"kms:CreateGrant\", \"kms:DescribeKey\" ],\n    \"Resource\" : \"*\"} ]\n}",
      }
  - Name: Key Restricts Usage With Condition
    ExpectedResult: true
    Resource:
      {
        "KeyRotationEnabled": true,
        "AWSAccountId": "1122334455",
        "Arn": "arn:aws:kms:us-west-2:11223344:key/1122233-asdf-adsf-111222333",
        "CloudHsmClusterId": null,
        "CreationDate": "2019-01-01T00:00:00Z",
        "CustomKeyStoreId": null,
        "DeletionDate": null,
        "Description": "Example key",
        "Enabled": false,
        "ExpirationModel": null,
        "KeyId": "1122233-asdf-adsf-111222333",
        "KeyManager": "AWS",
        "KeyState": "Enabled",
        "KeyUsage": "ENCRYPT_DECRYPT",
        "Origin": "AWS_KMS",
        "ValidTo": null,
        "Policy": "{\n  \"Version\" : \"2012-10-17\",\n  \"Id\" : \"use key\",\n  \"Statement\" : [ {\n    \"Sid\" : \"Allow access\",\n    \"Effect\" : \"Allow\",\n    \"Principal\" : {\n      \"AWS\" : \"*\"\n    },\n    \"Action\" : [ \"kms:Encrypt\", \"kms:Decrypt\"],\n    \"Resource\" : \"*\",\n    \"Condition\" : {\n      \"StringEquals\" : {\n        \"kms:CallerAccount\" : \"123456789012\",\n        \"kms:ViaService\" : \"lambda.us-east-1.amazonaws.com\"\n      }\n    }\n  } ]\n}",
      }

Detection logic

Condition

Policy not is_null

This rule also runs imperative logic the parser cannot express as a filter; the conditions above are the structured part it could extract.

Exclusions

Top-level NOT(...) conjuncts: predicates this rule actively suppresses.

FieldKindExcluded values
Policyis_null(no value, null check)