An attacker holding a cloud identity with permission to create functions or automations can run code inside your environment, under a role you trusted, without deploying a single server. MITRE ATT&CK tracks this as T1648 Serverless Execution in the Execution tactic (TA0002), on the IaaS, SaaS and Office Suite platforms. It covers AWS Lambda, Google Cloud functions and Azure Functions, but also Microsoft Power Automate flows and Google Apps Script. This guide explains the defender view of the technique in ATT&CK v20, the role and identity mistakes that make it work, the CloudTrail, Microsoft 365 and Google Workspace events to watch, and the guardrails that stop it. It is written for cloud security, detection engineering and SaaS administration teams.
Key takeaways
- It is an identity problem first. Serverless execution needs a principal that can create or update functions, and usually one that can attach a role to them, such as
iam:PassRolein AWS oriam.serviceAccounts.actAsin Google Cloud. - The function's role is the prize. ATT&CK describes adversaries attaching a role to a function so it can do what the original user cannot; the function becomes a privilege escalation path.
- Triggers make it persistent. A function wired to an event, such as new user creation, can quietly add credentials every time the event fires.
- Office suites count. Power Automate flows that forward mail and Apps Script bound to file opens are serverless execution too, and are run by user identities and connections rather than cloud roles.
- Log the control plane and correlate. Function creation, role assignment, permission changes and new triggers are management events you already collect; correlate them with unusual principals and follow-on credential activity.
How the technique works
ATT&CK v20 (technique version 1.2, last modified 15 April 2025) defines T1648 as adversaries abusing serverless computing, integration and automation services to execute arbitrary code in cloud environments. The technique has no sub-techniques. ATT&CK gives four patterns, which together define what to look for:
| Pattern | Example from ATT&CK | Linked technique | Identity precondition |
|---|---|---|---|
| Run unwanted workloads | Functions running crypto-mining code | T1496 Resource Hijacking | Create and invoke function permissions |
| Escalate through the function role | Using iam:PassRole (AWS) or iam.serviceAccounts.actAs (Google Cloud) to give a function a more privileged role | T1098.003 Additional Cloud Roles | Pass or act-as rights on a privileged role or service account |
| Persist through triggers | A Lambda function that adds access keys to a user, invoked by an event rule whenever a user is created | T1546 Event Triggered Execution, T1098.001 Additional Cloud Credentials | Create rule and function permissions |
| Automate collection in SaaS | A Power Automate flow that forwards all email, or creates anonymous sharing links; an Apps Script that exfiltrates data when a file is opened | T1114.003 Email Forwarding Rule (similar effect) | A user account allowed to create flows or scripts and grant them connections or OAuth scopes |
The technique almost always follows T1078.004 Cloud Accounts: a stolen access key, a leaked CI/CD credential or a phished session. ATT&CK v20 lists the open source framework Pacu (S1091) as able to create malicious Lambda functions, which is why authorised cloud penetration tests often show this path.
What it looked like in a real campaign
In the AWS crypto-mining campaign of November 2025, attackers used compromised IAM credentials with admin-like privileges. The mining ran on ECS Fargate and EC2, but for persistence they created a Lambda execution role with AWSLambdaBasicExecutionRole, a function exposed through a function URL with authType set to NONE, and an invoke permission for any principal. They also created an IAM user with an access key and console profile. Every step was a normal control plane call made by a non-human credential, which is exactly what makes T1648 hard to spot without identity context.
Where non-human identities fit
- Function execution roles: AWS documents that Lambda assumes the execution role automatically on invocation, and the trust policy names the
lambda.amazonaws.comprincipal. Any principal that can pass that role to a new function can borrow its permissions. - Default service accounts: Google's Cloud Run documentation states that when no identity is specified, the Compute Engine default service account is used, and depending on organisation policy it may automatically be granted the Editor role. Google strongly recommends disabling that automatic grant and using a user-managed service account with minimal permissions. See the Google Cloud IAM and Service Accounts Guide.
- Managed identities on Azure Functions: a function app with a system-assigned or user-assigned managed identity carries whatever role assignments that identity has. See How to find over-privileged Azure managed identities.
- Automation connections: Power Automate flows run through connections that hold delegated access to mail, files and APIs. A malicious flow inherits that access. See Power Automate connections security.
- Deployment pipelines: CI/CD roles that deploy functions usually hold PassRole or actAs on many roles. A stolen pipeline credential is often the fastest route into T1648.
Detection
ATT&CK v20 detection strategy DET0374 has three analytics: AN1053 for IaaS (function creation or modification correlated with anomalous role assignment, then unexpected actions by the new function), AN1054 for Office Suite (new flows triggering on user or file events, then forwarding, anonymous links or external calls) and AN1055 for SaaS (Apps Script with event-driven triggers followed by abnormal data access). The table maps them to concrete events.
| Platform | Log source | Events to collect | Alert when |
|---|---|---|---|
| AWS Lambda | CloudTrail management events | CreateFunction20150331, UpdateFunctionCode20150331v2, UpdateFunctionConfiguration20150331v2, AddPermission20150331v2, CreateFunctionUrlConfig, CreateEventSourceMapping20150331, PublishLayerVersion20181031 | Principal has never deployed functions; function URL with NONE; AddPermission with principal *; role passed is more privileged than the caller |
| AWS IAM and events | CloudTrail | CreateRole, AttachRolePolicy, PassRole context on CreateFunction, EventBridge PutRule and PutTargets | New role trusted by Lambda plus new rule targeting a new function within a short window |
| AWS invocations | CloudTrail data events (Invoke, not on by default) and CloudWatch Logs | Invoke for AWS::Lambda::Function | Invocations of new functions outside known workflows; function then calls IAM CreateAccessKey |
| Google Cloud functions and Cloud Run | Cloud Audit Logs (Admin Activity) | Function and service create or update; IAM policy changes on service accounts | Deployment with a service account the deployer has not used before; default compute service account with Editor |
| Microsoft 365 | Unified audit log | Flow creation and update (AddFlow, UpdateFlow); Exchange New-InboxRule | New flow triggered on mail or file events with external forwarding or anonymous sharing |
| Google Workspace | Admin and Drive audit logs | Apps Script project create or update; Drive file access | Script with installable triggers followed by bulk access or external transfer |
Correlation logic
- Rare deployer: alert when a principal creates or updates a function and has not done so in the last 90 days, unless it is a known pipeline role.
- Privilege gap: compare the passed execution role or service account against the caller's own permissions; a function more privileged than its creator is the escalation pattern ATT&CK describes.
- Public exposure: any
CreateFunctionUrlConfigor update with auth typeNONE, and any AddPermission granting*, outside an approved public API list. - Trigger plus credential: a new event rule or event source mapping whose target function later calls credential APIs such as
CreateAccessKeyorCreateLoginProfile. - SaaS automations: new flows or scripts that touch mail or files and send to external endpoints, especially when created by accounts that do not normally build automations.
For rule building see the Cloud Detection Engineering Guide and the AWS CloudTrail Guide.
Prevention
| Control | How | ATT&CK mitigation |
|---|---|---|
| Remove create, update and run rights from people who do not need them | Function deployment only through pipelines; humans read-only in production | M1018 User Account Management |
| Scope pass and act-as rights | Grant iam:PassRole only on named execution role ARNs; grant Service Account User only on specific service accounts, never project-wide | M1018 |
| Block unauthenticated function URLs | SCP denying lambda:CreateFunctionUrlConfig and lambda:UpdateFunctionUrlConfig where lambda:FunctionUrlAuthType is not AWS_IAM, as AWS documents | M1036 Account Use Policies |
| Least-privilege execution roles | Start from AWSLambdaBasicExecutionRole; use IAM Access Analyzer policy generation from CloudTrail activity before production | M1018 |
| No default service accounts | Disable the automatic Editor grant; assign user-managed service accounts per function | M1018 |
| Restrict automation platforms | Power Platform data policies to block connectors at design time; conditional access for flow creators; restrict high-risk OAuth scopes for Apps Script | M1036 |
Microsoft documents that when a data policy blocks a connector, makers cannot save a flow that uses it, and existing flows that violate the policy are suspended. Changes usually take effect within an hour and can take up to 24 hours. See the IAM Access Analyzer Guide for policy generation.
Implementation sequence
- Inventory: list every function, function URL, event rule and automation flow per account and tenant, with its execution identity and owner.
- Map who can deploy: enumerate principals with function create or update rights and pass or act-as rights. This is the T1648 attack surface.
- Turn on the right logs: confirm CloudTrail management events in all regions, Google Admin Activity logs, the Microsoft 365 unified audit log and Workspace audit logs; enable Lambda Invoke data events for sensitive functions.
- Deploy the detections in alert-only mode: run the five correlations for two weeks and tune for pipeline roles.
- Apply guardrails in rings: attach the function URL SCP and PassRole scoping to a sandbox OU first, then non-production, then production. Roll back by detaching the SCP.
- Fix identities: replace default service accounts and broad execution roles, starting with functions that hold write access to IAM.
- Exercise response: rehearse removing a malicious function, its triggers, its role and any credentials it created. See the Cryptojacking Incident Response Playbook.
Decision guidance
- SCPs versus detections: preventive guardrails are cheap for clear rules such as no unauthenticated function URLs. Privilege-gap and rare-deployer logic is too contextual for policy and belongs in detection.
- Invoke data events: they cost extra; enable them for functions with IAM, secrets or data export permissions rather than everywhere.
- Small versus large estates: a small team can remove human deploy rights and rely on one pipeline role. Large estates need a function ownership register and per-team roles so that a rare-deployer alert means something.
- SaaS automation: blocking flow creation outright breaks real business use. Prefer connector data policies plus monitoring of flows that forward data externally.
Measuring progress
- Deploy surface: number of human principals with function create or update rights in production, trending to zero.
- Wildcard PassRole: policies granting PassRole or Service Account User on
*or project-wide, target zero. - Public functions: function URLs with auth type
NONEoutside the approved list, target zero. - Owned functions: percentage of functions and flows with a named owner and a non-default identity.
- Detection latency: time from a test function creation to alert in exercises.
Common failure patterns
- Wildcard PassRole: a developer or pipeline policy allows
iam:PassRoleon all roles, so anyone holding it can launch a function as an admin role. - Default identities everywhere: functions running as a default compute service account with Editor, which turns every function deploy into project-wide access.
- Ignoring persistence objects: responders delete the malicious function but leave the event rule, layer, resource policy or created user. AWS notes that deleting a
NONEfunction URL does not delete its resource-based policy. - Logs without identity context: CloudTrail is collected but nobody can tell whether a principal normally deploys functions, so creation events are ignored.
- SaaS automation out of scope: the cloud team watches Lambda while mail-forwarding flows built by a compromised user run unnoticed.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| MITRE ATT&CK v20 | T1648; mitigations M1018, M1036; related T1098.003, T1098.001, T1546, T1496 | Technique, mitigations and follow-on behaviour |
| NIST SP 800-53 Rev. 5 | AC-2, AC-6, CM-7, CM-8, AU-12, SI-4 | Account and privilege control, least functionality, inventory, logging, monitoring |
| NIST CSF 2.0 | PR.AA-05, ID.AM-08, DE.CM-09 | Least privilege, lifecycle management of services, runtime monitoring |
| CIS Controls v8.1 | 6.8 Define and Maintain Role-Based Access Control; 8.2 Collect Audit Logs | Role scoping and log collection |
| ISO/IEC 27001:2022 Annex A | A.5.18 Access rights; A.8.15 Logging; A.8.16 Monitoring activities | Access provisioning and monitoring |
Practitioner checklist
- Inventory functions, function URLs, triggers and automation flows with their execution identities.
- Remove human create and update rights on production functions; deploy through pipelines.
- Scope PassRole and Service Account User to named roles and service accounts.
- Deny unauthenticated function URLs with an SCP using
lambda:FunctionUrlAuthType. - Replace default service accounts and broad execution roles.
- Alert on rare deployers, privilege gaps, public exposure and trigger-plus-credential chains.
- Apply Power Platform data policies and monitor flows and Apps Script that send data externally.
- In response, remove functions, triggers, layers, resource policies, roles and any credentials created.
Standards and references
- MITRE ATT&CK: Serverless Execution (T1648)
- AWS: Defining Lambda function permissions with an execution role
- AWS: Control access to Lambda function URLs
- AWS: Logging Lambda API calls using CloudTrail
- Google Cloud: Introduction to service identity (Cloud Run)
- Google Cloud: Function identity
- Microsoft: Power Platform data policies
Related NHI Mgmt Group resources: Serverless Security Guide · AWS Lambda Security Guide · Cloud Run and Cloud Functions Security Guide · MITRE ATT&CK T1098 Account Manipulation Guide · ATT&CK Execution Tactic Guide