elastic / integrations

Elastic Integrations
https://www.elastic.co/integrations
Other
198 stars 427 forks source link

[Google Workspace] Create Apps Script Integration or Execution Log Ingestion #5388

Open terrancedejesus opened 1 year ago

terrancedejesus commented 1 year ago

Overview

The Elastic Stack should have an Apps Script integration or ingest the execution logs via the existing Google Workspace integration. This enhancement would be important to identifying Apps Script abuse, which is not highlighted, if at all, by other SIEM products on the market or researchers.

Additional Information

Apps Script is the native JavaScript (JS) platform in Google Workspace. It allows those with privileges to programmatically manage and interact with all aspects of the Google Workspace software suite through APIs for each service. Similar to macros for Excel, Google Scripts can be container-based to a specific document.

The threat is mainly phishing with links and attachments through Google Workspace using malicious Google Script that is container-bound to each document.

Logging

At the moment, there is no specific Apps Script API reporting for log ingestion, similar to OAuth or Gmail in Google Workspace for the integration. However, execution logs can be ingested from scripts.google.com.

The logs themselves are very valuable for threat detection and research because the name of functions executed, the apps script name itself and even the whole function executed is observable.

Screenshot 2023-02-26 at 1 31 54 PM

Apps Script does have an API itself, but I am not sure if that is enough to identify actual executions and actions taken similar to the execution logs. I believe there may be some sequencing here that can be done such as "pull execution logs, use scripts API to pull enrichment data" which would be amazing.

I am currently exploring how to at least have Apps Script logged fully to GCP as described here. If done so, this may just be part of the GCP integration rather then the Google Workspace. Any assistance would be gladly appreciated!

terrancedejesus commented 1 year ago

@jamiehynds or @vinit-elastic - Please let me know if there is anything else I can provide or if a meeting would be beneficial to discussing this and related Google Workspace requests. I greatly appreciate your team's help!

elasticmachine commented 1 year ago

Pinging @elastic/security-external-integrations (Team:Security-External Integrations)

terrancedejesus commented 1 year ago

So I have been digging into this myself and I do not think there is currently a way to pull the tabular data from the API within the "My Executions" tab as shown in the UI.

However, similar results seem achievable with the Apps Script API and from googleapiclient.discovery import build in Python. Below is some PoC code I have been using that may help jump start this.

import os
import pandas as pd
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build as DiscoveryBuild

# The scope required to access the Google Workspace Apps Script API
SCOPES = [
    'https://www.googleapis.com/auth/script.projects',
    'https://www.googleapis.com/auth/script.processes',
    'https://www.googleapis.com/auth/script.metrics',
    'https://www.googleapis.com/auth/script.deployments']

# The location of the 'credentials.json' file you downloaded from the Google Cloud Console
CREDENTIALS_FILE = 'credentials.json'

def get_credentials():
    flow = InstalledAppFlow.from_client_secrets_file(CREDENTIALS_FILE, SCOPES)
    creds = flow.run_local_server(port=0)
    return creds

def get_script_details(project_id):
    creds = get_credentials()
    service = DiscoveryBuild('script', 'v1', credentials=creds)

    # Get the project's executions
    scripts = service.scripts()
    projects = service.projects()
    processes = service.processes()

    print("Debugging....")

def main():
    project_id = 'dejesus-archeology'
    get_script_details(project_id)

if __name__ == '__main__':
    main()

I have a breakpoint set at the print statement in get_script_details and from there have been exploring some of the classes, methods and libraries available. With the service variable there are classes for scripts, processes and projects. projects does not seem to have much but processes may be the key.

Within processes additional methods can be found as shown below that seem promising. From an integration standpoint, every 30min (default) use the API to get a list of scripts and processes within Apps Script. With these IDs identified, we can then leverage projects() to get metadata about it for extra details in the log.

Screenshot 2023-03-21 at 12 23 16 PM

Follow up with projects enrichment.

Screenshot 2023-03-21 at 12 30 12 PM

Unfortunately, scriptID is a necessary parameter for most of these calls which is why I "think" we can use processes to get a list of them, retrieve the IDs and then pass those around.

Overall, the integration logging may not have a generic JSON log from the API that is built and given, but has the capability to build a log with the necessary calls.

Example:

{"scriptId:"waiknmd9imd22","scriptName":"Malicious","executions":2,"container":"company.doc","contents":"{main()}"}

I have ran into a hurdle with authentication when calling processes.list() as the HTTP response is a 401 and I am not sure why since I have already used credentials to establish service and agreed to oauth scope requests.

andrewkroh commented 2 months ago

It's not clear how to use the API to get the executions and metadata about the scripts.

Unfortunately, scriptID is a necessary parameter for most of these calls which is why I "think" we can use processes to get a list of them, retrieve the IDs and then pass those around.

I'm tried using the processes list API ( https://developers.google.com/apps-script/api/reference/rest/v1/processes/list), but didn't get back any scriptID.

{
  "processes": [
    {
      "projectName": "Elastic X Reporter",
      "processType": "ADD_ON",
      "processStatus": "COMPLETED",
      "userAccessLevel": "NONE",
      "startTime": "2024-07-10T13:38:00.745Z",
      "duration": "1.041s",
      "runtimeVersion": "V8"
    },
    {
      "projectName": "Elastic X Reporter",
      "processType": "ADD_ON",
      "processStatus": "COMPLETED",
      "userAccessLevel": "NONE",
      "startTime": "2024-07-10T13:37:50.438Z",
      "duration": "0.817s",
      "runtimeVersion": "V8"
    },
    {
      "projectName": "Jira Cloud for Sheets",
      "processType": "SIMPLE_TRIGGER",
      "processStatus": "COMPLETED",
      "userAccessLevel": "NONE",
      "startTime": "2024-07-09T20:18:11.707Z",
      "duration": "0.546s",
      "runtimeVersion": "V8"
    },
    {
      "projectName": "Releases Update",
      "functionName": "onOpen",
      "processType": "SIMPLE_TRIGGER",
      "processStatus": "FAILED",
      "userAccessLevel": "WRITE",
      "startTime": "2024-07-08T18:41:02.907Z",
      "duration": "0.310s",
      "runtimeVersion": "V8"
    },
    {
      "projectName": "Jira Cloud for Sheets",
      "processType": "SIMPLE_TRIGGER",
      "processStatus": "COMPLETED",
      "userAccessLevel": "NONE",
      "startTime": "2024-07-08T18:41:02.906Z",
      "duration": "0.572s",
      "runtimeVersion": "V8"
    },
    {
      "processStatus": "COMPLETED",
      "duration": "2.777s"
    }
  ],
  "nextPageToken": "CgJYAQ=="
}
narph commented 1 month ago

@terrancedejesus , are there any updates here based on @andrewkroh's feedback ?

terrancedejesus commented 2 weeks ago

@andrewkroh @narph - Thanks for taking a look into this. At the moment, GWS is not on my development cycles as we prioritized AWS, Azure and Okta for Q2/Q3. We would like to circle back to this potentially in Q4, but TRADE does not have cycles at the moment to explore how to gain visibility into Apps Script logs.