Files
hacktricks-cloud/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md
2024-12-12 19:35:48 +01:00

8.9 KiB

GCP - Artifact Registry Privesc

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

Artifact Registry

For more information about Artifact Registry check:

{% content-ref url="../gcp-services/gcp-artifact-registry-enum.md" %} gcp-artifact-registry-enum.md {% endcontent-ref %}

artifactregistry.repositories.uploadArtifacts

With this permission an attacker could upload new versions of the artifacts with malicious code like Docker images:

{% code overflow="wrap" %}

# Configure docker to use gcloud to authenticate with Artifact Registry
gcloud auth configure-docker <location>-docker.pkg.dev

# tag the image to upload it
docker tag <local-img-name>:<local-tag> <location>-docker.pkg.dev/<proj-name>/<repo-name>/<img-name>:<tag>

# Upload it
docker push <location>-docker.pkg.dev/<proj-name>/<repo-name>/<img-name>:<tag>

{% endcode %}

{% hint style="danger" %} It was checked that it's possible to upload a new malicious docker image with the same name and tag as the one already present, so the old one will lose the tag and next time that image with that tag is downloaded the malicious one will be downloaded. {% endhint %}

Upload a Python library

Start by creating the library to upload (if you can download the latest version from the registry you can avoid this step):

  1. Set up your project structure:

    • Create a new directory for your library, e.g., hello_world_library.
    • Inside this directory, create another directory with your package name, e.g., hello_world.
    • Inside your package directory, create an __init__.py file. This file can be empty or can contain initializations for your package.
    mkdir hello_world_library
    cd hello_world_library
    mkdir hello_world
    touch hello_world/__init__.py
    
  2. Write your library code:

    • Inside the hello_world directory, create a new Python file for your module, e.g., greet.py.
    • Write your "Hello, World!" function:
    # hello_world/greet.py
    def say_hello():
        return "Hello, World!"
    
  3. Create a setup.py file:

    • In the root of your hello_world_library directory, create a setup.py file.
    • This file contains metadata about your library and tells Python how to install it.
    # 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
        ],
    )
    

Now, lets upload the library:

  1. Build your package:

    • From the root of your hello_world_library directory, run:
    python3 setup.py sdist bdist_wheel
    
  2. Configure authentication for twine (used to upload your package):

    • Ensure you have twine installed (pip install twine).
    • Use gcloud to configure credentials:

{% code overflow="wrap" %}

```sh
twine upload --username 'oauth2accesstoken' --password "$(gcloud auth print-access-token)" --repository-url https://<location>-python.pkg.dev/<project-id>/<repo-name>/ dist/*
```

{% endcode %}

  1. Clean the build
rm -rf dist build hello_world.egg-info

{% hint style="danger" %} It's not possible to upload a python library with the same version as the one already present, but it's possible to upload greater versions (or add an extra .0 at the end of the version if that works -not in python though-), or to delete the last version an upload a new one with (needed artifactregistry.versions.delete):

{% code overflow="wrap" %}

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

{% endcode %} {% endhint %}

artifactregistry.repositories.downloadArtifacts

With this permission you can download artifacts and search for sensitive information and vulnerabilities.

Download a Docker image:

# Configure docker to use gcloud to authenticate with Artifact Registry
gcloud auth configure-docker <location>-docker.pkg.dev

# Dowload image
docker pull <location>-docker.pkg.dev/<proj-name>/<repo-name>/<img-name>:<tag>

Download a python library:

{% code overflow="wrap" %}

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

{% endcode %}

  • What happens if a remote and a standard registries are mixed in a virtual one and a package exists in both? Check this page:

{% content-ref url="../gcp-persistence/gcp-artifact-registry-persistence.md" %} gcp-artifact-registry-persistence.md {% endcontent-ref %}

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

Delete artifacts from the registry, like docker images:

{% code overflow="wrap" %}

# Delete a docker image
gcloud artifacts docker images delete <location>-docker.pkg.dev/<proj-name>/<repo-name>/<img-name>:<tag>

{% endcode %}

artifactregistry.repositories.delete

Detele a full repository (even if it has content):

{% code overflow="wrap" %}

gcloud artifacts repositories delete <repo-name> --location=<location>

{% endcode %}

artifactregistry.repositories.setIamPolicy

An attacker with this permission could give himself permissions to perform some of the previously mentioned repository attacks.

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. I tried to modify the image with a new one, and even delete the current image (and the cache image) and nothing changed, the cloud function continue working. Therefore, maybe it might be possible to abuse a Race Condition attack like with the bucket to change the docker container that will be run but just modifying the stored image isn't possible to compromise the Cloud Function.

  • App Engine

Even though App Engine creates docker images inside Artifact Registry. It was tested that even if you modify the image inside this service and removes the App Engine instance (so a new one is deployed) the code executed doesn't change.
It might be possible that performing a Race Condition attack like with the buckets it might be possible to overwrite the executed code, but this wasn't tested.

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}