aws-imagebuilder-s3-component-uri-can-modify-code

Overwrite a component's S3-backed document (s3:PutObject on the component URI bucket/key) to inject malicious steps that execute on the next build as the build instance role.

derived aws emits CanModifyCode

match

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

{'component': None} ContainsResourceReference {'s3_object': None} {'principal': None} CanWrite {'s3_object': None} {'recipe': None} ContainsResourceReference {'component': None} {'pipeline': None} ContainsResourceReference {'recipe': None}

where

node_type(?component) == BuildWorker ?component.provider_type == 'AWS::ImageBuilder::Component' ?component.uri != null # component uses S3-backed document, not inline data node_type(?s3_object) == ObjectStorage node_type(?recipe) == BuildWorker ?recipe.provider_type in ['AWS::ImageBuilder::ImageRecipe', 'AWS::ImageBuilder::ContainerRecipe'] node_type(?pipeline) == BuildWorker ?pipeline.provider_type == 'AWS::ImageBuilder::ImagePipeline'

emit

source typeIdentity
target typeBuildWorker
source?principal
target?pipeline
permissionss3:PutObject
conditionsiam_permission resource_policy
state logicACTIVE when the principal has effective s3:PutObject on the exact S3 bucket/key referenced in the component's uri field, and the component is referenced by an active pipeline (the modification will be executed on the next build). CONDITIONAL(resource_policy) when S3 write is granted only via a bucket policy that may not remain in place. POTENTIAL when the component is present but it is unclear whether any active pipeline references it (pipeline reference unresolved). BLOCKED when an SCP or permission boundary denies s3:PutObject on the bucket.

Narrative

{principal.name} can overwrite the S3 object at {s3_object.name} (s3:PutObject) that backs the Image Builder component document for {component.name}. On the next build of {pipeline.name}, the SSM agent will download and execute the attacker-modified document as the build instance role {role.name}, without any imagebuilder:* API call by the attacker.

Raw rule rules/derived/aws/imagebuilder.yaml

id: aws-imagebuilder-s3-component-uri-can-modify-code
emits: CanModifyCode
description: Overwrite a component's S3-backed document (s3:PutObject on the component URI bucket/key)
  to inject malicious steps that execute on the next build as the build instance role.
match:
- - component: null
  - ContainsResourceReference
  - s3_object: null
- - principal: null
  - CanWrite
  - s3_object: null
- - recipe: null
  - ContainsResourceReference
  - component: null
- - pipeline: null
  - ContainsResourceReference
  - recipe: null
where:
- node_type(?component) == BuildWorker
- ?component.provider_type == 'AWS::ImageBuilder::Component'
- '?component.uri != null  # component uses S3-backed document, not inline data'
- node_type(?s3_object) == ObjectStorage
- node_type(?recipe) == BuildWorker
- ?recipe.provider_type in ['AWS::ImageBuilder::ImageRecipe', 'AWS::ImageBuilder::ContainerRecipe']
- node_type(?pipeline) == BuildWorker
- ?pipeline.provider_type == 'AWS::ImageBuilder::ImagePipeline'
emit:
  source_type: Identity
  target_type: BuildWorker
  source: ?principal
  target: ?pipeline
  permissions:
  - s3:PutObject
  conditions:
  - iam_permission
  - resource_policy
  state_logic: ACTIVE when the principal has effective s3:PutObject on the exact S3 bucket/key referenced
    in the component's uri field, and the component is referenced by an active pipeline (the modification
    will be executed on the next build). CONDITIONAL(resource_policy) when S3 write is granted only via
    a bucket policy that may not remain in place. POTENTIAL when the component is present but it is unclear
    whether any active pipeline references it (pipeline reference unresolved). BLOCKED when an SCP or
    permission boundary denies s3:PutObject on the bucket.
  confidence: min(contributing_confidences) * 0.87
  derived_from:
  - ?component ContainsResourceReference ?s3_object (component.uri -> S3 bucket/key)
  - ?principal CanWrite ?s3_object (s3:PutObject effective permission)
  false_positive_note: "Only applies when the component uses the `uri` field \u2014 an inline `data` component\
    \ cannot be overwritten via S3 (the document is stored in Image Builder's backing store, not in the\
    \ caller-accessible S3 path). Verify the S3 bucket and key match exactly the component's `uri` value;\
    \ a s3:PutObject on an unrelated bucket is not this path. The component must be active in a referenced\
    \ recipe in a running pipeline; a deprecated or orphaned component is POTENTIAL. Do not conflate S3-backed\
    \ component access with imagebuilder:CreateComponent access \u2014 these are independent paths."
  narrative: '{principal.name} can overwrite the S3 object at {s3_object.name} (s3:PutObject) that backs
    the Image Builder component document for {component.name}. On the next build of {pipeline.name}, the
    SSM agent will download and execute the attacker-modified document as the build instance role {role.name},
    without any imagebuilder:* API call by the attacker.'
move · open · esc close