GCP - Storage Enum

Support HackTricks

Storage

Google Cloud Platform (GCP) Storage는 구조화되지 않은 데이터에 대해 매우 내구성이 뛰어나고 가용성이 높은 객체 저장소를 제공하는 클라우드 기반 저장 솔루션입니다. 성능, 가용성 및 비용에 따라 Standard, Nearline, Coldline 및 Archive를 포함한 다양한 저장소 클래스를 제공합니다. GCP Storage는 데이터 관리 및 보안을 효과적으로 수행하기 위한 수명 주기 정책, 버전 관리 및 액세스 제어와 같은 고급 기능도 제공합니다.

버킷은 지역, 2개 지역 또는 **다중 지역(기본값)**에 저장할 수 있습니다.

Storage Types

  • Standard Storage: 이는 자주 액세스되는 데이터에 대해 높은 성능과 낮은 대기 시간의 액세스를 제공하는 기본 저장 옵션입니다. 웹사이트 콘텐츠 제공, 미디어 스트리밍 및 데이터 분석 파이프라인 호스팅을 포함한 다양한 사용 사례에 적합합니다.

  • Nearline Storage: 이 저장소 클래스는 Standard Storage보다 낮은 저장 비용약간 높은 액세스 비용을 제공합니다. 30일의 최소 저장 기간을 가지며, 자주 액세스되지 않는 데이터에 최적화되어 있습니다. 백업 및 아카이브 용도로 이상적입니다.

  • Coldline Storage: 이 저장소 클래스는 자주 액세스되지 않는 데이터의 장기 저장을 위해 최적화되어 있으며, 최소 저장 기간은 90일입니다. Nearline Storage보다 저렴한 저장 비용을 제공하지만 더 높은 액세스 비용이 있습니다.

  • Archive Storage: 이 저장소 클래스는 매우 드물게 액세스되는 차가운 데이터를 위해 설계되었으며, 최소 저장 기간은 365일입니다. 모든 GCP 저장 옵션 중에서 가장 낮은 저장 비용을 제공하지만 가장 높은 액세스 비용이 있습니다. 규정 준수 또는 규제 이유로 데이터를 장기 보관해야 하는 경우에 적합합니다.

  • Autoclass: 데이터에 얼마나 자주 액세스할지 모르겠다면 Autoclass를 선택할 수 있으며, GCP가 비용을 최소화하기 위해 자동으로 저장소 유형을 변경합니다.

Access Control

기본적으로 IAM을 통해 액세스를 제어하는 것이 권장되지만, ACL 사용을 활성화하는 것도 가능합니다. IAM(기본값)만 사용하도록 선택하고 90일이 경과하면, 버킷에 대해 ACL을 활성화할 수 없습니다.

Versioning

버전 관리를 활성화할 수 있으며, 이는 버킷 내에서 파일의 이전 버전을 저장합니다. 유지할 버전 수비현재 버전(이전 버전)이 존재할 기간을 구성할 수 있습니다. Standard 유형의 경우 7일이 권장됩니다.

비현재 버전의 메타데이터가 유지됩니다. 또한, 비현재 버전의 ACL도 유지되므로, 이전 버전은 현재 버전과 다른 ACL을 가질 수 있습니다.

자세한 내용은 docs에서 확인하세요.

Retention Policy

버킷 내 객체의 삭제를 금지하고 싶은 기간을 지정합니다(규정 준수에 매우 유용합니다). 버전 관리 또는 보존 정책 중 하나만 동시에 활성화할 수 있습니다.

Encryption

기본적으로 객체는 Google 관리 키를 사용하여 암호화됩니다, 그러나 KMS의 키를 사용할 수도 있습니다.

Public Access

외부 사용자(GCP에 로그인한 사용자 또는 아닌 사용자)에게 버킷 콘텐츠에 대한 액세스를 제공할 수 있습니다. 기본적으로 버킷이 생성될 때 공개 노출 옵션이 비활성화되어 있지만, 충분한 권한이 있으면 변경할 수 있습니다.

버킷에 액세스하기 위한 URL 형식은 **https://storage.googleapis.com/<bucket-name> 또는 https://<bucket_name>.storage.googleapis.com**입니다(둘 다 유효합니다).

HMAC Keys

HMAC 키는 _자격 증명_의 일종이며, Cloud Storage의 서비스 계정 또는 사용자 계정과 연결될 수 있습니다. HMAC 키를 사용하여 _서명_을 생성하고, 이는 Cloud Storage에 대한 요청에 포함됩니다. 서명은 주어진 요청이 사용자 또는 서비스 계정에 의해 승인되었음을 보여줍니다.

HMAC 키는 두 가지 주요 구성 요소로 구성됩니다: _access ID_와 secret.

  • Access ID: 특정 서비스 또는 사용자 계정에 연결된 영숫자 문자열입니다. 서비스 계정에 연결될 때 문자열의 길이는 61자이며, 사용자 계정에 연결될 때 문자열의 길이는 24자입니다. 다음은 access ID의 예입니다:

GOOGTS7C7FUP3AIRVJTE2BCDKINBTES3HC2GY5CBFJDCQ2SYHV6A6XXVTJFSA

  • Secret: 특정 access ID에 연결된 40자 Base-64 인코딩 문자열입니다. 비밀은 오직 당신과 Cloud Storage만 아는 사전 공유 키입니다. 인증 프로세스의 일환으로 서명을 생성하는 데 비밀을 사용합니다. 다음은 비밀의 예입니다:

bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ

access ID와 secret은 HMAC 키를 고유하게 식별하지만, secret은 서명을 생성하는 데 사용되므로 훨씬 더 민감한 정보입니다.

Enumeration

# List all storage buckets in project
gsutil ls

# Get each bucket configuration (protections, CLs, times, configs...)
gsutil ls -L

# List contents of a specific bucket
gsutil ls gs://bucket-name/
gsutil ls -r gs://bucket-name/ # Recursive
gsutil ls -a gs://bucket-name/ # Get ALL versions of objects

# Cat the context of a file without copying it locally
gsutil cat 'gs://bucket-name/folder/object'
gsutil cat 'gs://bucket-name/folder/object#<num>' # cat specific version

# Copy an object from the bucket to your local storage for review
gsutil cp gs://bucket-name/folder/object ~/

# List using a raw OAuth token
## Useful because "CLOUDSDK_AUTH_ACCESS_TOKEN" and "gcloud config set auth/access_token_file" doesn't work with gsutil
curl -H "Authorization: Bearer $TOKEN" "https://storage.googleapis.com/storage/v1/b/<storage-name>/o"
# Download file content from bucket
curl -H "Authorization: Bearer $TOKEN" "https://storage.googleapis.com/storage/v1/b/supportstorage-58249/o/flag.txt?alt=media" --output -

# Enumerate HMAC keys
gsutil hmac list

# Get permissions
gcloud storage buckets get-iam-policy gs://bucket-name/
gcloud storage objects get-iam-policy gs://bucket-name/folder/object

버킷을 나열할 때 권한 거부 오류가 발생하면 여전히 콘텐츠에 접근할 수 있습니다. 이제 버킷의 이름 규칙에 대해 알았으므로 가능한 이름 목록을 생성하고 접근을 시도할 수 있습니다:

for i in $(cat wordlist.txt); do gsutil ls -r gs://"$i"; done

storage.objects.liststorage.objects.get 권한이 있으면 버킷에서 모든 폴더와 파일을 나열하여 다운로드할 수 있어야 합니다. 다음 Python 스크립트를 사용하여 이를 달성할 수 있습니다:

import requests
import xml.etree.ElementTree as ET

def list_bucket_objects(bucket_name, prefix='', marker=None):
url = f"https://storage.googleapis.com/{bucket_name}?prefix={prefix}"
if marker:
url += f"&marker={marker}"
response = requests.get(url)
xml_data = response.content
root = ET.fromstring(xml_data)
ns = {'ns': 'http://doc.s3.amazonaws.com/2006-03-01'}
for contents in root.findall('.//ns:Contents', namespaces=ns):
key = contents.find('ns:Key', namespaces=ns).text
print(key)
next_marker = root.find('ns:NextMarker', namespaces=ns)
if next_marker is not None:
next_marker_value = next_marker.text
list_bucket_objects(bucket_name, prefix, next_marker_value)

list_bucket_objects('<storage-name>')

권한 상승

다음 페이지에서 저장소 권한을 악용하여 권한을 상승시키는 방법을 확인할 수 있습니다:

GCP - Storage Privesc

인증되지 않은 열거

GCP - Storage Unauthenticated Enum

포스트 익스플로잇

GCP - Storage Post Exploitation

지속성

GCP - Storage Persistence
HackTricks 지원하기

Last updated