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}