Un incident de sécurité ? Faites-vous assister : 01 47 28 38 39

tl;dr: we bypassed several steps of a challenge, based on a virtual machine, by directly extracting, decrypting and mounting its disk instead of abusing its network services. This technique is not new nor very clever, but it was still a fun bypass that interested many people so here are our explanations.

 

During the Nuit du Hack XV conference, we participated and won the challenge organized by Wavestone: our booth neighbours. We thank them for this interesting challenge and for the wonderful prize: a 3D-printer that is already sitting in our office!

 

For the last step of the challenge, we download an OVA file which is an exported virtual machine that can be imported, e.g. in VirtualBox. We can boot the VM: the drive is encrypted but the password is given. Once started, we cannot login because we do not have any credential, however a webapp and the SSH service are exported and usable. We observe that this is a Linux system.

We know that the flags are certainly stored in the VM so we decide to directly attack its drive instead of trying to use the webapp as the challenge author envisioned.

We encourage you to read the author’s writeup to discover the proper way to solve this whole challenge:

 

The disk is encrypted but we know the password, so we can try to extract it and mount it, or we can simply try to obtain a root shell through a well-known trick.

First, we can simply extract the OVA with the following command to obtain an .ovf (VM settings) and a .vmdk files (hard-drive image):

tar -xvf connected_missile.ova

We convert the VMDK to the raw format (same format as for disk images obtained with the dd command) with the VBoxManage command (from VirtualBox):

VBoxManage clonehd --format RAW connected_missile-disk1.vmdk disk.raw

Then we use fdisk to see how the drive is partitioned:

# fdisk -l disk.raw
Disk disk.raw: 4 GiB, 4294967296 bytes, 8388608 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x3b69d3a9

Device     Boot  Start     End Sectors  Size Id Type
disk.raw1  *      2048  499711  497664  243M 83 Linux
disk.raw2       501758 8386559 7884802  3.8G  5 Extended
disk.raw5       501760 8386559 7884800  3.8G 83 Linux

Solution #1: By changing the boot options

There is a well-known technique to elevate our privileges on Linux by changing the boot options to add a parameter to the kernel to replace the init program by a shell (e.g. /bin/bash).

The first partition is small so we suppose it is the /boot partition. It starts at offset 2048 and we see that the sector size is of 512 bytes, so its start is at 2048*512 bytes. We mount it with this command:

mount -o loop,offset=$((2048*512)) disk.raw /media

The /boot partition is not encrypted so we can directly browse it and confirm that we have indeed the /boot partition. We analyze the grub configuration in /grub/grub.cfg and change it to add “init=/bin/bash” at the end of the kernel line (“linux /vmlinuz-3.16.0-4-586…”).

We unmount the partition and convert back the raw image to a VMDK file:

umount ~/disk.raw
VBoxManage convertfromraw --format vmdk disk.raw disk.vmdk

Now, in VirtualBox, we just have to change the VMDK in the VM settings under the Storage menu: remove the “connected_missile-disk1.vmdk” disk, add a new disk from existing file and select the new “disk.vmdk” file.

We start the VM, type the encryption password and directly obtain a root shell:

Actually, during the challenge, we took another path: we tried to add the init parameter in the Grub prompt (by typing ‘e’ when selecting the OS to boot), however Grub was protected by a password. So we decided to replace its hash in the grub.cfg by one we generated for a known password. It worked, however the technique explained previously is more straightforward.

Solution #2: By mounting the disk

We suppose that the root partition is the last one. Its start offset is 501760 and we take into account that the sector size is of 512 bytes. We mount it as a loop device:

losetup /dev/loop0 disk.raw -o $((501760 * 512))

In Gnome we get an automatic prompt asking for the password. Otherwise we manually run cryptsetup to decrypt it with the password we already have:

cryptsetup open /dev/loop0 challdisk

Under /dev/mapper, we now have the whole disk and two LVM volumes virtual–rpi–vg-root and the associated swap. Now we can mount the root LVM volume:

# mount /dev/mapper/virtual--rpi--vg-root /media

The disk is small enough that we can launch a dumb exhaustive search for the flags:

# grep -Fr "NDH{" /media 2>/dev/null
/media/var/www/backups/flag:NDH{DamnWildcards*}
/media/etc/motd:     NDH{IsThatANewPublicKey?}            __/   /
/media/flag:NDH{HowDoesItFeelToBeRoot?}

 Clément Notin