aws-elasticache-network-reach-no-auth

A Redis/Valkey cluster with AuthTokenEnabled=false (or absent) or a Memcached cluster is accessible to any VPC-reachable compute resource with an inbound security group rule on the cache port (6379 Redis, 11211 Memcached) - no credential is required. Both read and write operations are permitted without authentication, enabling cache poisoning and lateral movement attacks.

derived aws emits CanReadDataCanWriteData

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'compute': None} CanNetworkReach {'cache': None}

where

generic_type(?cache) == Cache class(?compute) in [Compute] ?cache.provider_type in ['AWS::ElastiCache::ReplicationGroup', 'AWS::ElastiCache::CacheCluster', 'AWS::ElastiCache::ServerlessCache'] (?cache.properties.Engine == 'memcached') OR (?cache.properties.Engine in ['redis', 'valkey'] AND (?cache.properties.AuthTokenEnabled == false OR ?cache.properties.AuthTokenEnabled is null or absent) AND (?cache.properties.UserGroupIds is null or empty)) # Redis/Valkey with AuthTokenEnabled=false OR no UserGroup attached == no auth

emit

Raw rule rules/derived/aws/elasticache.yaml

id: aws-elasticache-network-reach-no-auth
emits:
- CanReadData
- CanWriteData
description: "A Redis/Valkey cluster with AuthTokenEnabled=false (or absent) or a Memcached cluster is\
  \ accessible to any VPC-reachable compute resource with an inbound security group rule on the cache\
  \ port (6379 Redis, 11211 Memcached) \u2014 no credential is required. Both read and write operations\
  \ are permitted without authentication, enabling cache poisoning and lateral movement attacks."
match:
- - compute: null
  - CanNetworkReach
  - cache: null
where:
- generic_type(?cache) == Cache
- class(?compute) in [Compute]
- ?cache.provider_type in ['AWS::ElastiCache::ReplicationGroup', 'AWS::ElastiCache::CacheCluster', 'AWS::ElastiCache::ServerlessCache']
- "(?cache.properties.Engine == 'memcached') OR (?cache.properties.Engine in ['redis', 'valkey']\n   \
  \ AND (?cache.properties.AuthTokenEnabled == false\n         OR ?cache.properties.AuthTokenEnabled is\
  \ null or absent)\n    AND (?cache.properties.UserGroupIds is null or empty))\n# Redis/Valkey with AuthTokenEnabled=false\
  \ OR no UserGroup attached == no auth"
emit:
- source_type: Compute
  target_type: Cache
  source: ?compute
  target: ?cache
  permissions: []
  conditions:
  - network_reachability
  - service_state
  state_logic: "CONDITIONAL(network_reachability): the cache is readable without a credential IF network\
    \ reachability is confirmed (VPC compute in the same VPC/peered VPC with an SG inbound rule allowing\
    \ TCP on the cache port from the compute resource's security group or CIDR). Upgrade to ACTIVE only\
    \ when a CanNetworkReach or CanReachPort edge has been derived confirming TCP access on port 6379\
    \ (Redis/Valkey) or 11211 (Memcached) between ?compute and ?cache. CONDITIONAL(service_state) when\
    \ the cluster is in a non-AVAILABLE state (creating, modifying, deleting). BLOCKED when the cache\
    \ engine enforces auth (AuthTokenEnabled=true OR UserGroupIds is non-empty for Redis/Valkey) \u2014\
    \ in that case knowledge of the credential is the gate, not network reachability."
  confidence: min(contributing_confidences) * 0.85
  edge_type: CanReadData
  derived_from:
  - ?compute CanNetworkReach ?cache (port 6379 or 11211 confirmed reachable)
  - ?cache.properties.AuthTokenEnabled == false or absent (DescribeReplicationGroups / DescribeCacheClusters
    evidence)
  false_positive_note: "The most critical gate for this rule is the AUTH status. Check: (1) For Redis/Valkey\
    \ replication groups: DescribeReplicationGroups returns\n    AuthTokenEnabled (bool). If true or if\
    \ UserGroupIds is non-empty,\n    auth is ON \u2014 do NOT emit ACTIVE; emit BLOCKED or do not emit.\n\
    (2) For single-node Redis clusters (DescribeCacheClusters): AuthTokenEnabled\n    field is present\
    \ on the cache cluster object.\n(3) For Memcached: always no auth \u2014 emit regardless of the field\
    \ value. (4) For Serverless: check UserGroupId in DescribeServerlessCaches. The network_reachability\
    \ condition is MANDATORY \u2014 ElastiCache is VPC-only. Do NOT emit ACTIVE without a confirmed CanNetworkReach\
    \ or CanReachPort edge for the relevant port from a specific compute resource. KMS at-rest encryption\
    \ does NOT block wire-protocol access \u2014 it encrypts the underlying disk, not the Redis protocol.\
    \ Do not add key_permission as a condition for this rule. A Redis cluster using TLS (TransitEncryptionEnabled=true)\
    \ still uses the same AUTH token / ACL mechanism; TLS alone does not grant or deny data access."
  narrative: '{cache.name} is a {cache.properties.Engine} cluster with no AUTH requirement and is network-reachable
    from {compute.name} (TCP port {port}). Any code running on {compute.name} can connect to {cache.name}
    and read all cached data without providing any credential.'
- source_type: Compute
  target_type: Cache
  source: ?compute
  target: ?cache
  permissions: []
  conditions:
  - network_reachability
  - service_state
  state_logic: "CONDITIONAL(network_reachability): the cache is fully writable without a credential IF\
    \ network reachability is confirmed. A no-auth Redis/Memcached cluster permits any write operation\
    \ \u2014 poisoning session caches, injecting template data, or corrupting application state. This\
    \ enables lateral movement through cache-based attacks. Upgrade to ACTIVE when CanNetworkReach or\
    \ CanReachPort is derived. CONDITIONAL(service_state) for non-AVAILABLE clusters. BLOCKED when auth\
    \ is enforced."
  confidence: min(contributing_confidences) * 0.85
  edge_type: CanWriteData
  derived_from:
  - ?compute CanNetworkReach ?cache (port 6379 or 11211 confirmed reachable)
  - ?cache.properties.AuthTokenEnabled == false or absent (DescribeReplicationGroups / DescribeCacheClusters
    evidence)
  false_positive_note: "Same AUTH status gates as CanReadData apply. No-auth Redis/Memcached clusters\
    \ permit unrestricted write operations \u2014 this CanWriteData path models cache-poisoning and lateral\
    \ movement attacks via stored cache data."
  narrative: "{cache.name} is a {cache.properties.Engine} cluster with no AUTH requirement and is network-reachable\
    \ from {compute.name} (TCP port {port}). Any code running on {compute.name} can connect to {cache.name}\
    \ and write all cached data without providing any credential \u2014 full cache modification via network\
    \ reachability alone, enabling cache poisoning and lateral movement."
move · open · esc close