Berkner Tech

From Recon to Root: An Embedded Pentest Walkthrough

An embedded penetration test walkthrough from board recon through firmware extraction to a root shell

It helps to see how the pieces fit together. This is a start-to-finish walkthrough of a typical embedded penetration test, from first contact with an unfamiliar board to a root shell, using a composite of the devices I see. The specific commands change per target, but the shape of the work is consistent, and that shape is what this shows.

First Contact

The device arrives as a black box: a plastic enclosure with a power input and maybe an Ethernet port or an antenna. The first move is to open it carefully and look. A teardown reveals the board, and the board reveals the plan, because every later step depends on knowing what is on it and how the parts connect.

Before any probing, I photograph both sides of the board at high resolution and note the obvious features: the largest chip, anything under a shield, headers and unpopulated footprints, and rows of pads that look like debug. That first survey is cheap and it frames everything, turning an anonymous object into a set of candidate targets to identify.

Identify the Major Chips

With a loupe I read the markings on the major parts and look them up. The goal is the big three: the processor, the storage, and any radio. Their part numbers lead to datasheets, and the datasheets tell me where debug, boot, and bus signals live on each chip.

# markings read off the board, then resolved
U1  MT7621AT        -> MediaTek MIPS SoC (router-class)
U4  W25Q128         -> 16 MB SPI NOR flash (firmware lives here)
U7  shielded, "MT7615" -> Wi-Fi radio

That inventory already tells a story: a MIPS Linux SoC, 16 MB of SPI flash holding the firmware, and a Wi-Fi radio. I now know the firmware is on an accessible SPI chip and that the device runs Linux, which shapes both how I will extract the firmware and what I will look for inside it.

Find the Debug Interface

Next I hunt for UART, the easiest way onto a Linux embedded device. A row of four pads near the SoC is the usual candidate. I find ground with a multimeter, watch for the pad that flickers at boot as TX, wire a 3.3V adapter, and try 115200 baud first.

picocom -b 115200 /dev/ttyUSB0
Example output
U-Boot 2018.03 ...
Starting kernel ...
BusyBox v1.28 built-in shell (ash)
device login:

A boot log scrolls by and ends at a login prompt. That tells me UART is live and the device wants credentials. A login prompt is progress but not access; I note it and keep the boot log, which already leaked the bootloader version, the kernel, and the partition layout for later.

Get the Firmware

Rather than guess the login, I read the firmware directly, because having the image makes everything else easier. The SPI flash I identified takes a SOIC-8 clip and a CH341A programmer, and a couple of reads with flashrom give a dump I can verify by comparing them.

flashrom -p ch341a_spi -r dump1.bin
flashrom -p ch341a_spi -r dump2.bin
cmp dump1.bin dump2.bin && echo "clean read"
binwalk dump1.bin
Example output
clean read
0x0      uImage header, U-Boot
0x40     Kernel, lzma
0x150000 Squashfs filesystem

A clean, repeatable read and a binwalk that shows a kernel and a SquashFS filesystem means I have the whole firmware. Now the device’s secrets are in a file on my laptop, and I can analyze them at leisure rather than poking at the running device blind.

Extract and Explore the Filesystem

Carving the filesystem out turns the dump into a browsable Linux root, where the interesting files live. I extract it and go straight for the credentials and the startup scripts, which usually answer the access question quickly.

binwalk -e dump1.bin
cd _dump1.bin.extracted/squashfs-root
cat etc/passwd
ls etc/init.d/
Example output
root:$1$xyz$abcd...:0:0:root:/root:/bin/sh
# init.d: rcS  telnetd_debug  httpd

Two things jump out: a root password hash in /etc/passwd, and an init script named telnetd_debug that the running device showed no sign of. The hash is something I can attack offline, and the debug telnet service is a likely way in that the login prompt did not advertise.

Crack the Credentials

The root hash is an old-style md5crypt, which falls quickly to a wordlist. I run it offline against the firmware’s own hash, so there is no rate limit and no lockout to worry about.

john --wordlist=rockyou.txt hash.txt
Example output
admin1234        (root)
1g 0:00:00:03 ...

The root password is admin1234, a weak shared credential baked into the firmware. That alone is a serious finding, because every unit of this product ships with the same root password, and now I have it. But I also want to confirm the access on the live device, not just in the dump.

Get a Shell

With the password in hand, I go back to the UART login, or to the debug telnet service the init script revealed, and authenticate. Either way the device hands over a root shell, confirming the credential works on real hardware.

device login: root
Password: admin1234
Example output
BusyBox v1.28 built-in shell (ash)
root@device:/# id
uid=0(root) gid=0(root)

That is root. From recon to a root shell took identifying the chips, reading the flash, cracking a weak shared password, and logging in, a few hours of mostly unglamorous work. No exotic attack was needed, because the easy path, an accessible flash and a weak shared credential, was wide open.

Confirm the Impact

Root on one device is the start, not the end, of understanding impact. From the shell I confirm what the access yields: the running services, the stored keys, the network configuration, and whether this credential and these keys are shared across the product line, which decides whether this is a one-device or a fleet-wide problem.

root@device:/# netstat -tlnp; ls /etc/*.key /etc/ssl/private/ 2>/dev/null
Example output
tcp 0.0.0.0:9999 LISTEN telnetd_debug
/etc/ssl/private/device.key   # same key present in the firmware image

The undocumented debug telnet on 9999 and a private key shipped in the firmware confirm the worst: shared credentials and a shared key across the fleet. One device on a bench compromised the design for all of them, which is the headline the report will lead with.

What the Path Reveals

The walkthrough shows that real attacks usually take the cheapest path, not the most impressive one. No glitching, no side-channel work, just an accessible flash chip, a weak shared password, and a forgotten debug service. The dramatic attacks exist, but most devices fall to the mundane weaknesses first, which is exactly why they matter most.

It also shows how the phases build on each other: recon enables extraction, extraction enables analysis, analysis hands you the credentials, and the credentials give you root. Each step is ordinary on its own, and together they are a complete compromise. A defender who closes any one of those steps, encrypts the flash, uses per-device credentials, removes the debug service, breaks the chain.

Turning It Into Fixes

The report writes itself from the path: weak shared root password, firmware readable from an unprotected SPI chip, an undocumented debug service, and a shared private key. Each maps to a concrete fix, per-device credentials, flash encryption with a hardware-held key, stripping debug services from release builds, and per-device key provisioning.

Fixing any one raises the bar, and fixing all of them changes the device from a few-hours compromise to a genuinely hard target. That is the value of walking the whole path: it shows not just that the device can be rooted, but exactly which decisions made it easy and which changes would make it hard.

Where This Fits

This start-to-finish work, recon, extraction, analysis, and exploitation, is what an embedded penetration test actually is. If you want to know how your connected product holds up against this exact path, before someone else walks it, that is the kind of work we do at Berkner Tech.


References and Further Reading