aws-lambda-execute-as-via-code

Replace function code, then run it, to execute as the function's role.

derived aws emits CanExecuteAs

match

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

{'principal': None} CanModifyCode {'function': None} {'function': None} ExecutesAs {'role': None}

where

node_type(?function) == ServerlessFunction

optional

Present → upgrade the emitted state; absent → downgrade (not a hard requirement).

{'principal': None} CanInvoke {'function': None}

emit

source typeIdentity
target typeIdentity
source?principal
target?role
permissionslambda:UpdateFunctionCode lambda:InvokeFunction?
conditionstrigger_exists
state logicif matched(optional[0]) or trigger_exists(?function): ACTIVE else CONDITIONAL(trigger_exists)

Narrative

{principal.name} can replace the code of {function.name} (lambda:UpdateFunctionCode), which executes as {role.name}; running it (direct invoke or existing trigger) executes attacker code as {role.name}.

Raw rule rules/derived/aws/lambda.yaml

id: aws-lambda-execute-as-via-code
emits: CanExecuteAs
description: Replace function code, then run it, to execute as the function's role.
match:
- - principal: null
  - CanModifyCode
  - function: null
- - function: null
  - ExecutesAs
  - role: null
where:
- node_type(?function) == ServerlessFunction
optional:
- - principal: null
  - CanInvoke
  - function: null
emit:
  source_type: Identity
  target_type: Identity
  source: ?principal
  target: ?role
  permissions:
  - lambda:UpdateFunctionCode
  - lambda:InvokeFunction?
  conditions:
  - trigger_exists
  state_logic: 'if matched(optional[0]) or trigger_exists(?function): ACTIVE else CONDITIONAL(trigger_exists)'
  confidence: min(contributing_confidences) * 0.95
  derived_from:
  - <CanModifyCode edge_id>
  - <ExecutesAs edge_id>
  - <CanInvoke edge_id?>
  false_positive_note: Only ACTIVE if the principal can invoke (lambda:InvokeFunction) OR a trigger already
    exists (event source mapping / S3 / EventBridge / SNS / URL); otherwise CONDITIONAL(trigger_exists).
    Do not emit if the code action is scoped to a different function than the one that ExecutesAs the
    target role.
  narrative: '{principal.name} can replace the code of {function.name} (lambda:UpdateFunctionCode), which
    executes as {role.name}; running it (direct invoke or existing trigger) executes attacker code as
    {role.name}.'
move · open · esc close