Privilege Escalation on Embedded Linux
Landing a shell on an embedded Linux device often gives you a limited account, not root. Getting from there to full control is privilege escalation, and embedded systems offer a rich set of paths because they are frequently built with convenience ahead of hardening. Here are the escalation routes I check first, and what they say about the device.
Why Embedded Escalation Is Often Easy
Embedded Linux is still Linux, so the classic privilege-escalation techniques apply, but the environment tilts in the attacker’s favor. These systems are built by teams focused on shipping a working product, often reusing a vendor SDK, with security hardening low on the list, so the userland is full of the shortcuts that escalation exploits.
Where a hardened server has had its SUID binaries pruned, its permissions tightened, and its services dropped to least privilege, an embedded device frequently has none of that. Many processes already run as root because it was easier, world-writable files abound, and old vulnerable binaries linger. Escalation is often a matter of checking the usual suspects and finding one of them open.
The Paths to Check
A handful of paths account for most embedded escalations, and a quick check reveals each:
| Path to root | What you are looking for | Quick check |
|---|---|---|
| Over-privileged services | A service like httpd running as root | ps w |
| SUID / SGID binaries | A SUID-root binary that runs a shell or trusts input | find / -perm -4000 |
| Writable root files | A world-writable script or config root runs | find / -writable -type f |
| Cron / scheduled jobs | A root job that runs a script you can write | cat /etc/crontabs/root |
| Sudo and capabilities | A sudo entry or a cap_setuid binary | sudo -l ; getcap -r / |
| Old kernel or services | Known privesc CVEs in unpatched software | uname -a |
Enumerate First
Escalation starts with enumeration: gathering the facts that reveal a path, who am I, what runs, what is misconfigured. On a constrained device the standard tooling may be missing, so I lean on built-in commands.
id; uname -a; cat /etc/*release 2>/dev/null ps w # what runs, and as whom ls -la /etc/passwd /etc/shadow
uid=1000(app) gid=1000(app) Linux device 3.10.14 #1 mips PID USER COMMAND 214 root /usr/sbin/httpd # web server running as root 311 app /usr/bin/cli
Already a lead: the web server runs as root, so a vulnerability in it is a direct path to root. The kernel version is old too, which raises the possibility of a kernel exploit as a fallback. A process list that shows services needlessly privileged is one of the first things I note.
SUID and SGID Binaries
SUID binaries run with the privileges of their owner regardless of who launches them, so a SUID-root binary that can be made to run arbitrary commands is an escalation. Embedded images often ship unnecessary SUID binaries, sometimes custom ones with exploitable behavior.
find / -perm -4000 -type f 2>/dev/null
/bin/busybox /usr/bin/passwd /usr/sbin/custom_helper # a vendor binary, SUID root
The interesting entry is custom_helper, a vendor-specific SUID-root binary. Vendor SUID binaries are prime targets because they are not battle-tested like the standard tools, and they frequently call out to a shell, trust an environment variable, or run another program by relative path, any of which can be turned into root.
Writable Files Owned by Root
A file that root reads or executes but that I can write is an escalation waiting to happen: world-writable scripts run by root, writable configuration that controls a root process, or a writable binary in root’s path.
find / -writable -type f 2>/dev/null | grep -vE '^/(proc|sys|tmp|dev)' ls -la /etc/init.d/ /etc/cron* 2>/dev/null
/etc/init.d/custom_start # world-writable, runs as root at boot /www/cgi-bin/ # writable web root, served by root httpd
A world-writable init script that root runs at boot is a clean escalation, write a command into it and it executes as root on the next restart. The writable web root served by a root web server is another path, since dropping a script there may let me execute as root through the web interface.
Cron and Scheduled Tasks
Scheduled jobs running as root are a reliable escalation if I can influence what they run, a cron job that executes a script I can write, or that processes files in a directory I control.
cat /etc/crontabs/root 2>/dev/null; ls -la /etc/cron.d 2>/dev/null
*/5 * * * * /usr/bin/backup.sh # backup.sh is writable by group 'app' -> we are in group app
A backup script that runs every five minutes as root and is writable by my group is an escalation on a timer. Appending a command that copies a shell to a SUID-root location, or adds my key, gives root within five minutes. Scheduled jobs are easy to overlook and easy to abuse when their scripts are not locked down.
Sudo and Capabilities
If sudo is present, its configuration may allow my user to run specific commands as root, and a command that can spawn a shell or write a file is enough. Linux capabilities on binaries are the modern equivalent, granting slices of root power that can sometimes be escalated.
sudo -l 2>/dev/null getcap -r / 2>/dev/null
User app may run: /usr/bin/tcpdump /usr/bin/python3 = cap_setuid+ep # python with setuid capability
Python carrying the setuid capability is an immediate win: a one-line script that sets the UID to zero and execs a shell gives root directly. A sudo entry for a command with a known shell escape works the same way. Both are convenience choices that hand a limited user the keys.
Old Kernels and Root Processes
When configuration is tight, the software version becomes the path. Embedded devices run old kernels and userland for years, so a privilege-escalation vulnerability patched upstream long ago may still be live, and a local kernel exploit is a fallback when the easier paths are closed. It is less clean and risks crashing the device, so I reach for it after the configuration checks, but on embedded targets it frequently works.
The web server running as root is also worth attacking directly. Embedded web interfaces are notorious for shelling out to system commands with user input, so a parameter that reaches a system call gives command execution as the web server’s user, which here is root. When a root process has an injectable input, that is often the shortest path, and it ties the network attack surface directly to full device control.
A Worked Escalation Chain
A real escalation often chains several small issues. Starting as the limited app user, enumeration finds a world-writable script run by a root cron job every five minutes; appending a single line that copies a shell and sets it SUID-root, then waiting one cron cycle, yields a root shell, no exploit, just one misconfiguration leveraged.
# app user appends to a root-run, world-writable cron script echo 'cp /bin/sh /tmp/rootsh; chmod 4755 /tmp/rootsh' >> /etc/cron.d/backup.sh # wait one cron cycle, then: /tmp/rootsh -p id
uid=1000(app) euid=0(root) # root shell obtained via a writable cron script
Each link in that chain is an ordinary embedded oversight, a world-writable file, a root cron job, a permissive umask, and individually none looks alarming; combined, they are a clean path from a limited foothold to root. This is why escalation findings are reported as chains: fixing any single link, locking the script’s permissions, breaks the path, and showing the whole chain makes both the risk and the cheapest fix obvious.
Hardening against Escalation
The defenses are well understood and mostly about discipline: run each service as a dedicated unprivileged user instead of root, remove every SUID bit that is not strictly required, tighten file and directory permissions so nothing root relies on is writable by others, lock down scheduled jobs, and keep the kernel and userland patched.
The deeper fix is cultural, build the image with least privilege as the default rather than retrofitting it after an assessment finds the gaps. A hardened build that drops privileges, prunes SUID binaries, and sets restrictive permissions closes not just the paths a test found but the ones the next test would find. Escalation difficulty is a reliable proxy for how seriously a device was hardened, and an easy escalation almost always signals a systemic convenience-over-security habit worth addressing at the build level.
Where This Fits
Testing how far an initial foothold can be escalated, and mapping the paths to root, is a core part of an embedded penetration test. If you want to know how easily a foothold on your device becomes full control, that is the kind of work we do at Berkner Tech.



