Detection rules › Panther

IAM Inline Policy Network Admin

Severity
medium
Compliance
PCI 1.1.5, 2.2.4, 7.1.2
Tags
AWS, PCI, Persistence:Valid Accounts
Reference
https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html
Source
github.com/panther-labs/panther-analysis

This policy validates that IAM entities (Groups, Roles, and Users) do not have inline policies attached that grant network admin privileges. Inline policies are more difficult to track and audit than managed policies, and can lead to persistent unexpected access.

MITRE ATT&CK coverage

TacticTechniques
PersistenceT1078 Valid Accounts

Rule body yaml

AnalysisType: policy
Filename: aws_iam_inline_policy_does_not_grant_network_admin_access.py
PolicyID: "AWS.IAM.Entity.InlinePolicyDoesNotGrantNetworkAdminAccess"
DisplayName: "IAM Inline Policy Network Admin"
Enabled: true
ResourceTypes:
  - AWS.IAM.User
  - AWS.IAM.Role
  - AWS.IAM.Group
Tags:
  - AWS
  - PCI
  - Persistence:Valid Accounts
Reports:
  PCI:
    - 1.1.5
    - 2.2.4
    - 7.1.2
  MITRE ATT&CK:
    - TA0003:T1078
Severity: Medium
Description: >
  This policy validates that IAM entities (Groups, Roles, and Users) do not have inline policies attached that grant network admin privileges. Inline policies are more difficult to track and audit than managed policies, and can lead to persistent unexpected access.
Runbook: >
  Remove the inline policy, and if the IAM entity needs the provided permissions create an IAM managed policy with those permissions and apply it to the entity.
Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html
Tests:
  - Name: IAM Entity Has No Inline Policy
    ExpectedResult: true
    Resource:
      {
        "AccountId": "123456789012",
        "Arn": "arn:aws:iam::123456789012:user/example-user",
        "CredentialReport":
          {
            "ARN": "arn:aws:iam::123456789012:user/example-user",
            "AccessKey1Active": true,
            "AccessKey1LastRotated": "2019-01-01T00:00:00Z",
            "AccessKey1LastUsedDate": "0001-01-01T00:00:00Z",
            "AccessKey1LastUsedRegion": "N/A",
            "AccessKey1LastUsedService": "N/A",
            "AccessKey2Active": false,
            "AccessKey2LastRotated": "0001-01-01T00:00:00Z",
            "AccessKey2LastUsedDate": "0001-01-01T00:00:00Z",
            "AccessKey2LastUsedRegion": "N/A",
            "AccessKey2LastUsedService": "N/A",
            "Cert1Active": false,
            "Cert1LastRotated": "0001-01-01T00:00:00Z",
            "Cert2Active": false,
            "Cert2LastRotated": "0001-01-01T00:00:00Z",
            "MfaActive": false,
            "PasswordEnabled": true,
            "PasswordLastChanged": "2019-01-01T00:00:00Z",
            "PasswordLastUsed": "2019-01-01T00:00:00Z",
            "PasswordNextRotation": "2019-12-01T00:00:00Z",
            "UserCreationTime": "2019-01-01T00:00:00Z",
            "UserName": "example-user",
          },
        "Groups":
          [
            {
              "Arn": "arn:aws:iam::123456789012:group/example-group",
              "CreateDate": "2019-01-01T00:00:00Z",
              "GroupId": "1111",
              "GroupName": "example-group",
              "Path": "/",
            },
          ],
        "Id": "1111",
        "InlinePolicies": null,
        "ManagedPolicyNames": ["example-policy"],
        "Name": "example-user",
        "PasswordLastUsed": "2019-01-01T00:00:00Z",
        "Path": "/",
        "PermissionsBoundary": null,
        "Region": "global",
        "ResourceId": "arn:aws:iam::123456789012:user/example-user",
        "ResourceType": "AWS.IAM.User",
        "Tags": null,
        "TimeCreated": "2019-01-01T00:00:00.000Z",
        "VirtualMFA":
          {
            "EnableDate": "2019-01-01T00:00:00Z",
            "SerialNumber": "arn:aws:iam::123456789012:mfa/example-mfa",
          },
      }

Detection logic

Condition

InlinePolicies 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
InlinePoliciesis_null(no value, null check)