본문 바로가기

Program/토스뱅크 사이버보안 엔지니어 부트캠프(공격&방어 기술)

Google Drive API 사용 방법

1. Google Drive API

1.1 Google Drive API 개요

Google Drive API는 Google Drive에 저장된 파일과 폴더를 외부 애플리케이션에서 직접 제어할 수 있도록 제공되는 REST API이다. 단순한 파일 저장 기능을 넘어, 파일 검색, 메타데이터 조회, 권한 제어, 대용량 파일 전송까지 포함하는 종합적인 파일 관리 인터페이스를 제공한다. 이로 인해 개인용 애플리케이션뿐만 아니라 기업 환경의 백엔드 자동화, 로그 보관, 데이터 파이프라인 구성에도 널리 활용된다.
 

1.2 Google Drive API 동작 구조

https://developers.google.com/static/workspace/drive/images/drive-intro.svg?hl=ko

Google Drive API는 클라이언트, 인증 계층, 그리고 Drive API 엔드포인트라는 세 가지 요소로 구성된다. 클라이언트는 Python, JavaScript, PowerShell, 또는 서버 애플리케이션이 될 수 있으며, 이 클라이언트는 OAuth 2.0 또는 Service Account 기반 인증을 통해 Access Token을 발급받는다. 이후 모든 요청은 HTTPS 기반 REST 호출 형태로 Drive API 엔드포인트에 전달된다.

구성 요소설명
ClientPython, JS, PowerShell, Backend 서버
AuthOAuth 2.0 / Service Account
Drive APIREST Endpoint (HTTPS)

이 구조로 인해 Drive API는 일반적인 웹 API와 동일한 방식으로 동작하지만, 인증 토큰의 권한 범위(Scope)에 따라 접근 가능한 리소스가 엄격히 제한된다는 특징을 가진다.
 

1.3 인증 방식

1) OAuth 2.0
OAuth 2.0 방식은 사용자가 직접 Google 계정으로 로그인하고 애플리케이션에 권한을 위임하는 구조이다. 개인 Drive 파일 접근이나 사용자 인터랙션이 필요한 데스크톱·웹 애플리케이션에 주로 사용된다. 이 방식에서는 사용자가 승인한 Scope 범위 내에서만 파일 접근이 가능하며, 토큰은 사용자 계정에 종속된다.
 
2) Service Account
Service Account는 사용자 개입 없이 서버가 자체적으로 인증을 수행하는 방식이다. 배치 작업이나 백엔드 자동화에 적합하며, 조직 환경에서는 특정 Drive 폴더를 서비스 계정에 공유하는 방식으로 접근 권한을 부여한다. 이 방식은 정상적인 서버 자동화에도 사용되지만, 보안 사고 관점에서는 은닉성이 높아 악성 행위에 악용되는 사례도 존재한다.
 
 
 

2. 보안 관점에서의 Google Drive API

2.1 공격자 활용 시나리오

Google Drive API는 정상적인 클라우드 서비스 트래픽으로 위장되기 쉬워 공격자에게 매력적인 통신 수단이 될 수 있다. OAuth 토큰 탈취 이후 Drive를 C2 채널로 사용하거나, 민감 정보 유출을 위한 Exfiltration 경로로 악용되는 사례가 존재한다.

단계설명
Initial Access OAuth Token 탈취
C2 Google Drive를 C2 서버로 사용
Exfiltration 문서·로그 업로드
Evasion 정상 Google HTTPS 트래픽 위장

 

 

2.2 탐지 포인트

이러한 악용을 탐지하기 위해서는 단순히 Google 트래픽을 차단하기보다는 API 호출 패턴을 분석하는 접근이 필요하다. 특히 비정상적인 Resumable Upload 반복, 서버 환경에서의 OAuth 인증 시도, 비표준 User-Agent 조합 등이 주요 탐지 포인트가 된다.
 

 
 

3. Google Cloud Console에서 프로젝트 생성

3.1 프로젝트 선택

 
 

3.2 새 프로젝트

프로젝트 이름 입력 후 만들기 클릭
위치는 상위 조직 또는 폴더이므로, 현재 여기서는 생략한다.

 
 
 

4. Google Drive API 활성화

4.1 탐색메뉴 → API 및 서비스 → 라이브러리

 
 

4.2 Google Drive API 선택

 
 

4.3 사용

 
 

5. Google 인증 플랫폼 구성

5.1 API 및 서비스 → OAuth 동의 화면

 

5.2 브랜딩 만들기

 
 

5.3 구성 완료

 
 


6. OAuth 2.0 클라이언트 생성

6.1 클라이언트 만들기

 
 

6.2 애플리케이션 유형 선택

google drive로 download만 진행할 경우, 데스크톱 앱으로 진행해도 됨
 
 

6.3 이름 및 승인된 리디렉션 URI 입력

 

승인된 리디렉션 URI에 https://developers.google.com/oauthplayground 입력

 
 

6.4 만들기


 
 

7. OAuth Token 얻기

7.1 스콥 선택

1) https://developers.google.com/oauthplayground 접속
2) 왼쪽에서 "Drive API v3" 펼치기
3) https://www.googleapis.com/auth/drive.file 체크
4) Authorize APIs 클릭

 
6.2 계정 선택 및 로그인

 
 
6.3 토큰 생성
"Exchange authorization code for tokens" 클릭

 
 
 

7. Google Drive API에서 다운로드

7.1 다운로드 받을 파일 권한 변경

파일정보 > 세부정보 > 액세스 관리에서 링크가 있는 모든 사용자로 변경한다.

 
 
 

7.2 cmd 명령어

certutil -urlcache -split -f "https://drive.google.com/uc?export=download&id=<FILE_ID>" <PATH>

파일의 링크를 복사하면 https://docs.google.com/document/d/<FILE_ID>/edit?usp=drive_link 이와 유사하게 복사된다.
그중에서 <FILE_ID> 부분을 입력한다.

명령어 구성구성 설명
certutil실행 파일Windows 내장 유틸리티 실행
-urlcache옵션URL에서 데이터를 가져와 로컬에 저장(다운로드 동작)
-split옵션응답 데이터를 분할/스트림 방식으로 처리하도록 지정
-f옵션대상 파일이 존재하면 강제로 덮어쓰기(force overwrite)
"https://drive.google.com/uc?export=download&id=<FILE_ID>"URLGoogle Drive 파일 ID를 이용한 직접 다운로드 URL
<PATH>출력 경로다운로드 결과를 저장할 로컬 파일 경로/파일명

 
 

7.3 확인

 
 
 

8. Google Drive API로 업로드

8.1 powershell 명령어

# === Step 1: OAuth 설정===
$clientId = "<CLIENT_ID>"
$clientSecret = "<CLIENT_SECRET>"
$refreshToken = "<REFRESH_TOKEN>"
$folderId = "<DRIVE_FOLDER_ID>"


# === Step 2: Access Token 발급 ===
$tokenResponse = Invoke-RestMethod -Uri "https://oauth2.googleapis.com/token" -Method Post -Body @{
    client_id     = $clientId
    client_secret = $clientSecret
    refresh_token = $refreshToken
    grant_type    = "refresh_token"
}
$token = $tokenResponse.access_token


# === Step 3: 업로드할 파일 확인 ===
$filePath = "<FILE_PATH>"

$fileInfo = Get-Item $filePath
$fileSize = $fileInfo.Length
$fileSizeMB = ($fileSize / 1MB).ToString('0.00')

$fileName = "<FILE_NAME>"


# === Step 4: Resumable Upload 세션 시작 ===
$metadata = @{
    name    = $fileName
    parents = @($folderId)
} | ConvertTo-Json

$initResponse = Invoke-WebRequest `
    -Uri "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable" `
    -Method Post `
    -Headers @{ 
        Authorization    = "Bearer $token"
        "X-Upload-Content-Type"   = "application/zip"
        "X-Upload-Content-Length" = $fileSize
    } `
    -ContentType "application/json; charset=UTF-8" `
    -Body $metadata `
    -UseBasicParsing

$uploadUrl = $initResponse.Headers.Location


# === Step 5: 파일 업로드 ===
$fileBytes = [System.IO.File]::ReadAllBytes($filePath)

$uploadResponse = Invoke-RestMethod `
    -Uri $uploadUrl `
    -Method Put `
    -Headers @{ 
        "Content-Length" = $fileSize
    } `
    -ContentType "application/zip" `
    -Body $fileBytes

# === Step 6: 결과 ===
if ($uploadResponse.id) {
    Write-Host "[+] 업로드 성공!" -ForegroundColor Green
    Write-Host "    File: $($uploadResponse.name)" -ForegroundColor Cyan
    Write-Host "    ID: $($uploadResponse.id)" -ForegroundColor Cyan
    Write-Host "    Size: $fileSizeMB MB" -ForegroundColor Cyan
} else {
    Write-Host "[-] 업로드 실패" -ForegroundColor Red
}

 
1) OAuth 설정
명령어 구성항목설명

명령어 구성항목설명
$clientId = "<CLIENT_ID>"변수 값OAuth 클라이언트 ID
$clientSecret = "<CLIENT_SECRET>"변수 값OAuth 클라이언트 시크릿
$refreshToken = "<REFRESH_TOKEN>"변수 값Access Token 발급에 사용하는 Refresh Token
$folderId = "<DRIVE_FOLDER_ID>"변수 값업로드 대상 Google Drive 폴더 ID
https://drive.google.com/drive/folders/<DRIVE_FOLER_ID>

 
2) Access Token 발급

명령어 구성항목설명
Invoke-RestMethod -Uri "https://oauth2.googleapis.com/token" -Method Post엔드포인트, 메서드토큰 발급 API에 POST 요청
-Body @{ client_id=...; client_secret=...; refresh_token=...; grant_type="refresh_token" }요청 바디Refresh Token 기반 Access Token 발급 파라미터
$tokenResponse.access_token변수 값응답에서 Access Token 추출
$token = ...변수 값이후 Drive API 요청의 Authorization Bearer 토큰으로 사용

 
3) 업로드 파일 확인

명령어 구성항목설명
$filePath = "<FILE_PATH>"변수 값업로드할 로컬 파일 경로
Get-Item $filePath파일 조회파일 객체와 메타정보 획득
$fileInfo.Length변수 값파일 크기 바이트 값
($fileSize / 1MB).ToString('0.00')표현식파일 크기를 MB로 계산해 소수 둘째 자리 문자열로 변환하는 표현식
$fileName = "<FILE_NAME>"변수 값Drive에 저장될 파일명

 
4) Resumable Upload 세션 시작

명령어 구성항목설명
$metadata = @{ name=$fileName; parents=@($folderId) } | ConvertTo-Json변수 값업로드 메타데이터를 JSON으로 생성
Invoke-WebRequest -Uri "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable" -Method Post엔드포인트, 메서드Resumable 업로드 세션 생성 요청
-Headers @{ Authorization="Bearer $token" }AuthorizationOAuth 인증 헤더
"X-Upload-Content-Type"="application/zip"content type 힌트실제 업로드될 파일 MIME 타입
"X-Upload-Content-Length"=$fileSizecontent length 힌트실제 업로드될 파일 크기
-ContentType "application/json; charset=UTF-8"요청 타입메타데이터가 JSON임을 명시
-Body $metadata요청 본문파일명, 부모 폴더 등 메타데이터 전달
$initResponse.Headers.Location변수 값업로드 세션 URL 반환
$uploadUrl = ...변수 값Step 4에서 PUT 대상 URL로 사용

 
* uploadType: Google Drive API에서 /upload 엔드포인트로 파일을 올릴 때 업로드 방식을 지정하는 쿼리 파라미터

uploadType이름설명
mediasimple upload파일 데이터만 업로드하며 메타데이터는 포함하지 않음
multipartmultipart upload메타데이터와 파일 데이터를 한 번의 요청으로 함께 업로드
resumableresumable upload업로드 세션을 만든 뒤 2회 이상 요청으로 업로드하며 중단 시 재개에 유리

 
 
5) 파일 업로드

명령어 구성항목설명
$fileBytes = [System.IO.File]::ReadAllBytes($filePath)fileBytes로컬 파일을 바이트 배열로 로드
Invoke-RestMethod -Uri $uploadUrl -Method PutURL, 메서드세션 URL로 PUT 업로드 수행
-Headers @{ "Content-Length" = $fileSize }Content-Length업로드 데이터 길이 지정
-ContentType "application/zip"ContentType업로드 데이터 MIME 타입
-Body $fileBytesBody파일 바이트 데이터 전송
$uploadResponse응답업로드 결과 JSON 저장

 
 
 
8.2 확인