Skip to content

Latest commit

 

History

History
369 lines (270 loc) · 10.9 KB

File metadata and controls

369 lines (270 loc) · 10.9 KB

IoT Firmware Assignment Quickstart

Date: 2026-05-25

Use this file during the assignment.

If the simple path breaks, use research-algorithms.md to choose the next experiment and field-manual.md as the challenge index. Use reference-guide.md as the long reference manual.

Goal

Produce one defensible vulnerability path:

reachable input -> vulnerable code path -> reproducer -> impact/exploitability -> limitations

Do not submit scanner output as the finding.

Use these evidence states while working:

lead -> hypothesis -> confirmed root cause -> demonstrated impact

A CVE, unsafe function, open port, version string, AI note, or EMBA result starts as a lead. Promote it only when the missing edge is proven.

Recommended Setup

Default:

Windows host
  -> VMware Workstation Pro
    -> Kali VM with EMBA classic Docker mode
    -> optional Ubuntu 24.04.4 LTS VM only as no-EMBA backup/manual workbench

If Kali/EMBA works, stay on that path. Use Windows GUI tools for IDA/Ghidra and notes.

Weak host with 4 logical cores:

VM: 2 vCPU
RAM: 6-12 GB depending on host RAM
Run only one VM at a time
Run IDA/Ghidra GUI on Windows host
Avoid heavy full-system emulation

Remote fallback:

Rent strong EC2 Ubuntu host
Run tools directly over SSH
Use Firecracker only later if you need many isolated workers

First Commands

Create a run folder:

mkdir -p runs/fw1/artifacts
cd runs/fw1

Record metadata:

sha256sum /path/to/firmware.bin | tee 01_sha256.txt
file /path/to/firmware.bin | tee 02_file.txt
binwalk /path/to/firmware.bin | tee 03_binwalk.txt

Extract:

binwalk -eM /path/to/firmware.bin
find . -maxdepth 4 -type f | tee artifacts/file_tree.txt

If Binwalk fails and Kali/EMBA works, try EMBA quick scan:

cd ~/tools/emba
sudo ./emba -l ~/emba_logs/fw1/quick_scan \
  -f /path/to/firmware.bin \
  -p ./scan-profiles/quick-scan.emba

If Kali/EMBA/Docker is blocked, use ../lab-setup/ubuntu-no-emba-backup-guide.md instead of spending the assignment on setup.

Attack Surface

Before grepping for bug patterns, build a small graph:

startup/config -> listener or scheduled job -> input -> parser/transform -> sink -> effect

For each row, record the process user, default or feature-gated state, attacker position, and cheapest test that could confirm reachability. Use research-algorithms.md when several components compete.

Find services and web roots:

rg -n "httpd|lighttpd|boa|uhttpd|telnetd|dropbear|sshd|upnp|miniupnp|cgi-bin" .
find . -type d \( -name "www" -o -name "htdocs" -o -name "cgi-bin" \)
find . -type f \( -name "*.cgi" -o -name "*.sh" -o -name "*.lua" -o -name "*.php" \)

Find high-ROI bug patterns:

rg -n "system\(|popen\(|exec|eval|wget|curl|tftp|nc |/bin/sh|sh -c" .
rg -n "password|passwd|secret|token|key|admin|root" .
rg -n "\.\./|realpath|fopen|open\(|readfile|download|upload" .
rg -n "firmware|upgrade|update|signature|md5|sha1|openssl" .
rg -n "ubi|ubifs|jffs2|/mnt/jffs2|/overlay|/dev/mtd|/proc/mtd|fw_printenv|factory|caldata|Config|Env|Storage" .
rg -n "uart|rs232|rs-232|jtag|swd|spi|i2c|can|socketcan|usb|uboot|u-boot|uefi|initramfs|failsafe|recovery|otp|efuse|secure boot|root of trust|plc|modbus|profinet|ethercat|bacnet" .

Research-derived shortcuts:

  • Start from default-started services and update clients. Synacktiv's Netgear R6700v3 work turned a background update daemon into the main finding.
  • Map web routes to parsers before reversing deeply. Claroty's Synology BC500 writeup moved from firmware layout to web config to CGI parser.
  • Treat logging strings and source-like function names as anchors. SpaceRaccoon's Tapo C260 writeup used logging/source functions to find request handlers fast.
  • Record feature preconditions. NCC's BrokenPrint finding depended on ReadySHARE being reachable only when a USB printer was connected.

Pick One Candidate

Use the complete-chain test before choosing by bug class:

reachable entry point
  -> attacker-controlled value
  -> vulnerable operation or trust decision
  -> safe observable effect

If one edge is missing, write it as a hypothesis and identify the cheapest test for that edge. Prioritize a reachable lower-impact lead over an isolated high-impact sink.

Prefer:

  • command injection in CGI/API/script
  • path traversal
  • hardcoded credential with reachable service
  • auth/session flaw
  • insecure update path
  • controlled crash in exposed parser

Reject weak candidates:

  • version-only CVE with no reachable path
  • hardcoded string with no service/login path
  • crash with no input control
  • AI claim with no code evidence

High-ROI choice rule:

Pick the lead with a complete chain: startup/config -> reachable route/service -> attacker-controlled field -> sink/parser -> safe proof.

This is the common pattern across Claroty's router/camera chain, Neodyme's Netgear work, and Talos' WAGO cloud-to-device research. A less severe bug with a full chain is usually better than a scarier sink with no reachable input.

Emulation

Write the question emulation must answer before starting it. Examples include “does the route reach this handler?” and “does the parser accept this field?” Use research-algorithms.md to estimate whether QEMU-user, a service harness, full-system emulation, or hardware is justified.

When using EMBA, consult the source-code capability map before interpreting a boot, port, NVRAM, dependency, or version result. It lists the image repairs and synthetic launch paths that can change the meaning of a successful emulation.

Start with user-mode, not full-system emulation.

Exception: if the lead is a missing secret, account, generated key, calibration value, or config value and the firmware references raw flash storage, check field-manual.md before spending time on generic full-system emulation. A Gemtek-style full NAND dump with known geometry and a UBI/JFFS2 mount such as /mnt/jffs2 may justify MTD/UBI reconstruction; a rootfs-only password helper usually does not.

Find architecture:

file rootfs/bin/busybox
file rootfs/usr/sbin/httpd

Example:

sudo apt install -y qemu-user-static gdb-multiarch strace
cp /usr/bin/qemu-mipsel-static rootfs/usr/bin/
sudo chroot rootfs /usr/bin/qemu-mipsel-static /bin/busybox

If full emulation fails, document the blocker and continue with static reachability.

Research-derived emulation rule:

  • Emulate the smallest thing that answers the question. SpaceRaccoon's Nokia Beacon 1 used Qiling for one password-generation path, not the whole router.
  • Compare manual QEMU against framework output when services do not start, as in Applied Security's IoT Firmware Emulation with Qemu.
  • If hardware-dependent emulation fails, pivot to static proof and record the blocker. Neodyme's HP M479fdw writeup is the model.

EMBA-specific evidence rule:

S115 proves one-binary behavior in a copied/repaired test root.
L10 proves behavior in a modified generic emulation image.
F17/F50 prioritize CVEs and exploits; they do not prove reachability.

Before relying on an EMBA port or service result, map the port to a PID, command line, and launch source, then check whether it came from original init logic or EMBA inference/debug helpers.

Reproducer

For web bugs:

curl -i "http://127.0.0.1:8080/"
curl -i "http://127.0.0.1:8080/cgi-bin/target?param=test"

For safe command injection proof:

Use echo/id/sleep only.
Do not run destructive commands.
Prefer timing proof if output is hidden.

For path traversal:

curl -i "http://127.0.0.1:8080/download?file=../../etc/passwd"

For binary crash:

qemu-mipsel-static -g 1234 -L rootfs rootfs/usr/sbin/target args
gdb-multiarch rootfs/usr/sbin/target

Before claiming impact, write the preconditions:

network side, auth state, service enabled by default or feature-gated, required hardware/config, process user, and whether restart/retry behavior matters

Report Skeleton

# Firmware Vulnerability Research Report

## Scope
- Firmware:
- SHA256:
- Constraints:

## Executive Summary
- Finding:
- Impact:
- Confidence:

## Environment
- Host/VM:
- Tools:
- Limitations:

## Attack Surface
- Architecture:
- Services:
- Web/API routes:

## Finding

### Reachability
- Endpoint/service:
- Startup path:
- Input parameter:

### Root Cause
- File/function/address:
- Vulnerable operation:
- Why validation fails:

### Reproducer
- Command/request:
- Observed result:

### Exploitability
- Attacker control:
- Privileges/context:
- Realistic exploitation path:
- Constraints:

### Fix
- Validate/quote inputs
- Avoid shell
- Canonicalize paths
- Add auth/signature checks

## AI Usage
- Where AI helped:
- What was manually verified:
- False positives:

48-Hour Clock

0-2h: hash, identify, extract
2-5h: services, web roots, grep patterns
5-8h: choose one candidate
8-14h: inspect code and try user-mode/chroot
14-22h: build reproducer
22-30h: root cause and exploitability
30-40h: write report
40-48h: rerun commands and polish evidence

Do Not Waste Time On

  • full-system emulation before static triage
  • Firecracker for a one-off assignment
  • FACT unless already installed
  • broad fuzzing without a target
  • reporting CVEs from versions only
  • letting AI decide exploitability

For a fuller stop rule and hardware decision gate, see research-algorithms.md.

If hardware or boot-access evidence appears, classify it before celebrating:

UART/RS-232: log, login, root shell, bootloader shell, or initramfs shell?
SPI/eMMC: firmware, env, config, factory data, calibration, or logs?
JTAG/SWD: boundary scan, CPU debug, flash access, or locked?
CAN/I2C/USB: which firmware driver or process consumes the traffic?
OT: what lab/simulator state makes proof safe?

Use field-manual.md for the evidence checklist and stop rules.

Reference

Setup/tool reference index: reference-guide.md

Real-world challenge map: field-manual.md