filesystem-exploration
practicalLesson 4 — Filesystem Exploration
The Extracted Root Is a Real Linux System
After extraction, squashfs-root/ is a complete embedded Linux root filesystem. It contains every file that runs on the device. You are not dealing with a VM image or a partial dump — this is the entire OS as it exists on the device's flash. Treat it like a live system's filesystem, because that is exactly what it is.
Start by confirming the architecture and understanding the scope:
cd _firmware.bin.extracted/squashfs-root
# Confirm architecture from a known-present binary
file bin/busybox
# See the total structure
find . -maxdepth 2 -type d | sort
# Count total files
find . -type f | wc -l
A typical embedded Linux firmware has 200–1500 files. Larger is not better for security — more files means more attack surface and often more hardcoded credentials.
Key Directories and What They Hold
/etc/
The most valuable directory for initial analysis. Contains configuration files, init scripts, and often credentials.
ls etc/
/etc/passwd and /etc/shadow:
cat etc/passwd
# Typical output:
# root:x:0:0:root:/root:/bin/sh
# admin:x:1000:1000::/home/admin:/bin/sh
# nobody:x:65534:65534:nobody:/var/run/nobody:/bin/false
cat etc/shadow
# If readable (it often is on extracted firmware — no filesystem permissions enforced):
# root:$1$abc123$abcdefghijklmnopqrstuvw:0:0:99999:7:::
# admin:$1$xyz789$zyxwvutsrqponmlkjihgfe:0:0:99999:7:::
A password hash in /etc/shadow can be cracked offline with john or hashcat. The hash type is indicated by the prefix: $1$ = MD5, $5$ = SHA-256, $6$ = SHA-512. MD5 ($1$) is common on older devices and cracks quickly.
/etc/passwd with non-x password field: Some embedded devices skip shadow entirely and store the hash directly in passwd:
root:$1$abc123$abcdefghijklmnopqrstuvw:0:0:root:/:/bin/sh
This is immediately crackable — no /etc/shadow needed.
/etc/init.d/ and /etc/rc.d/
Startup scripts that run on boot. These scripts configure services and often contain hardcoded credentials passed to service binaries:
grep -r "pass\|user\|key\|secret\|token" etc/init.d/ 2>/dev/null
Common findings:
- Database passwords passed as CLI arguments: mysql -u root -p hardcoded_password
- Wireless PSKs in wpa_supplicant.conf setup commands
- SNMP community strings
- Default WiFi passwords set at boot
/etc/config/ (OpenWrt) or /etc/ flat configs
OpenWrt-based devices use UCI config files in /etc/config/. These are human-readable:
cat etc/config/wireless
# config wifi-device 'radio0'
# option type 'mac80211'
# option channel '6'
# config wifi-iface 'default_radio0'
# option ssid 'DeviceSSID'
# option key 'default_wifi_password'
/usr/bin/ and /usr/sbin/
Stripped ELF binaries. You cannot read them directly, but you can extract strings:
# Find all executables
find usr/bin usr/sbin bin sbin -type f -executable 2>/dev/null
# Identify which binary handles a function of interest (web auth, telnet, etc.)
file usr/bin/*
/www/ or /var/www/
The web interface served by the embedded HTTP daemon. Often contains:
ls www/
# Typical: cgi-bin/ index.html login.html js/ css/
# CGI scripts often contain hardcoded credentials or SQL-injectable code
cat www/cgi-bin/login.cgi 2>/dev/null
grep -r "admin\|password\|secret" www/ 2>/dev/null
Lua, shell, or compiled CGI scripts are common. Shell CGI scripts are often readable as plaintext.
/lib/
Shared libraries. Contains libc, libssl, and vendor-specific shared libraries. Vendor libraries sometimes contain:
- Hardcoded encryption keys (look for 16 or 32-byte blocks of non-printable data)
- Embedded certificates
- Hardcoded cloud endpoint URLs
strings lib/libvendor.so | grep -E "http|key|cert|secret"
Finding Writable Paths
In a SquashFS (read-only) root, writable paths at runtime are typically overlaid with tmpfs mounts or symlinked to a separate writable partition. These paths tell you about runtime behavior:
# Find symlinks pointing to /tmp or /var (usually tmpfs at runtime)
find . -type l | xargs ls -la 2>/dev/null | grep "tmp\|var"
# In many firmwares, /var is a symlink to /tmp
ls -la var
If /etc → /tmp/etc at runtime, the device copies /etc to RAM on boot. This means any process can modify /tmp/etc on a running device, which has security implications.
Identifying the Web Server Binary
The HTTP daemon binary handles admin authentication. Finding it lets you focus binary analysis:
# Common names
ls usr/sbin/httpd usr/bin/httpd usr/sbin/lighttpd usr/sbin/mini_httpd 2>/dev/null
# If not obvious, check init scripts
grep -r "httpd\|lighttpd\|nginx\|uhttpd" etc/init.d/ 2>/dev/null
# What does it link against? (shows capabilities)
file usr/sbin/httpd
# ELF 32-bit LSB executable, ARM, statically linked
# Statically linked = all library code is inside the binary
Checking for Default Credential Files
Some devices have default credential files that are applied on first boot or factory reset:
find . -name "default*" -o -name "factory*" -o -name "*.default" 2>/dev/null
find . -name "*.nvs" -o -name "*.cfg" -o -name "*.conf" 2>/dev/null | head -20
Permissions Are Not Enforced
A critical point: when you explore the extracted filesystem on your Linux machine, file permissions from the original SquashFS are generally irrelevant to you. You are running as your own user with read access to everything. Files that would be 0640 root shadow on the live device are freely readable by you in the extraction directory.
This is why /etc/shadow is so useful in firmware analysis — on the live device it is readable only by root, but in your extracted copy you read it like any other text file.
Building a Target List
After initial exploration, build a list of targets for the next lesson:
# Save interesting files for detailed analysis
find . -name "*.conf" -o -name "*.cfg" -o -name "*.pem" \
-o -name "*.key" -o -name "id_rsa" 2>/dev/null > interesting_files.txt
# Note the httpd binary path for string analysis
# Note any .lua, .cgi, .sh files in web directories
find www/ -type f | sort >> interesting_files.txt