We take security seriously so instead of shipping our own crypto we simply use proven military grade technology for our firmware updates.
nc military-crypto.ctf.hackover.de 1337
When connecting to the interface we’re presented with a menu:
====================================================
== secure update service
we didn't roll our own, powered by the
best crypto known to humanity
====================================================
1) Update firmware 3) Current firmware
2) Download firmware 4) Quit
Update firmware asks us to upload a new firmware and a detached PGP signature.
Download firmware sends back the source code of the server encoded with base64.
Current firmware sends back a PGP signed message with some information about the current firmware.
Clearly the goal here is to provide a new firmware and a signature to trick the server into running it. So let’s inspect the code of the server and see how the verification is done.
update_firmware() {
cat <<EOF
====================================================
1) send update binary as base64
2) finish with an empty line
3) send detached signature as base64
4) finish with an empty line
====================================================
EOF
echo 'Reading firmware...'
touch update.bin.b64
while IFS='' read -r firmware; do
if [ -z "$firmware" ]; then break; fi
echo "$firmware" >> update.bin.b64
done
base64 -d update.bin.b64 > update.bin
rm update.bin.b64
echo 'Reading detatched signaure...'
touch update.bin.sig
while IFS='' read -r signature; do
if [ -z "$signature" ]; then break; fi
echo "$signature" >> update.bin.sig.b64
done
base64 -d update.bin.sig.b64 > update.bin.sig
rm update.bin.sig.b64
if ! gpg --verify update.bin.sig; then
set +x
echo '!!!!!!!!!!!!!!!!!!!!!!!'
echo '!! INVALID SIGNATURE !!'
echo '!!!!!!!!!!!!!!!!!!!!!!!'
exit 1
else
chmod +x update.bin
echo 'Updating....'
./update.bin
echo 'Rebooting....'
exit 0
fi
}
The firmware is verified with gpg --verify update.bin.sig
.
From man gpg
:
--verify
Assume that the first argument is a signed file and verify it
without generating any output.
...
gpg may assume that a single argument is a file with a detached
signature, and it will try to find a matching data file by
stripping certain suffixes. Using this historical feature to
verify a detached signature is strongly discouraged; you should
always specify the data file explicitly.
It seems that when --verify
can both be used to verify signed files (where the
contents and the signature are in the same file) and files with a detached
signature (where the signature is in a separate file).
The server expects a detached signature for update.bin
but if we instead send
a self-contained signed message, gpg will think that we’re trying to verify the
contents of that file and ignore update.bin
. The Current firmware
command
conveniently sends back exactly that.
For the final exploit we can simply send a shell script that launches
/bin/bash
as the new firmware and the output of Current firmware
as the
signature.
Flag: hackover18{r0ll_y0_0wn_crypt0_w1th_pgp}