Free tech learning for everyone, from basics to pro

IoT LabsLabsIntermediate

Lab: safe firmware updates for IoT devices

In short: Updates fix vulnerabilities, but a careless update can brick a device or install tampered code. In this lab you back up and verify firmware before flashing, then build a simple over-the-air update that checks a hash, writes to a temporary file and keeps the previous version.

Aim and what you need

The aim is to practise the habits behind safe updates: know what is installed, verify what you install, be able to go back, and update a few devices before all of them. OTA (over-the-air) means delivering updates over the network instead of a cable.

  • The ESP32 from the ESP32 sensor lab, its USB cable, and esptool and mpremote.
  • A small web server on your LAN to host update files, such as python3 -m http.server for testing, then HTTPS for anything real.
  • Your own devices only; never push code to devices you do not own.
A safe update pipelineBuildversionedSign orhashpublishdigestDeliverover HTTPSVerifyon deviceInstallA/B or tempHealthcheckor roll back
Figure 1. Each stage adds a check, so a corrupted or tampered update is rejected and a bad one can be undone.

Steps

  1. Back up the current flash (4 MB on most boards) and record its hash.
  2. Download the new MicroPython firmware and compare its SHA-256 hash with the one published by the project before flashing.
  3. Flash, then restore your application files.
  4. For code updates over the air, publish a manifest with the version and SHA-256 of the new main.py.
  5. On the device, download to a temporary file, check the hash, keep the old file as a backup, then swap and reboot.
  6. After reboot, if the app fails a simple health check, copy the backup back.
esptool --chip esp32 --port /dev/ttyUSB0 read-flash 0 0x400000 backup-2026-10.bin
sha256sum backup-2026-10.bin ESP32_GENERIC-<version>.bin
esptool --chip esp32 --port /dev/ttyUSB0 write-flash -z 0x1000 ESP32_GENERIC-<version>.bin

# on the update server
sha256sum main.py
# manifest.json
{ "version": "1.1.0", "file": "main.py", "sha256": "<hash-from-sha256sum>" }

# ota.py on the device (MicroPython)
import os, hashlib, binascii, requests

BASE = "https://updates.lab.example/sensor1/"

def update():
    m = requests.get(BASE + "manifest.json").json()
    data = requests.get(BASE + m["file"]).content
    digest = binascii.hexlify(hashlib.sha256(data).digest()).decode()
    if digest != m["sha256"]:
        print("hash mismatch, update rejected")
        return False
    with open("main.new", "wb") as f:
        f.write(data)
    try:
        os.remove("main.bak")
    except OSError:
        pass
    os.rename("main.py", "main.bak")
    os.rename("main.new", "main.py")
    return True

A hash only proves the file matches the manifest. If an attacker can change both, they win, so real products sign updates with a private key kept off the server and verify the signature on the device. ESP-IDF, the ESP32's main framework, offers signed app images, secure boot and A/B partitions with automatic rollback; note that enabling secure boot or flash encryption burns eFuses and cannot be undone, so practise on a spare board.

Unsafe versus safe updatesUnsafePlain HTTP downloadNo integrity checkOverwrites in placeAll devices at onceSafeHTTPS and signaturesHash or signature verifiedSecond slot, rollbackStaged rollout
Figure 2. Safe updates are authenticated, verified, reversible and rolled out in stages.

How to verify and troubleshoot

Change one character in the hosted main.py without updating the manifest: the device must print a mismatch and keep running the old version. Then publish a correct update and check the version in the device's output. To test rollback, publish a deliberately broken but correctly hashed file and confirm your health check restores main.bak.

  • Out of memory: large files may not fit in RAM; download in chunks and hash as you go.
  • TLS errors: the device clock may be wrong; set time with NTP (Network Time Protocol) first.
  • Board will not boot after flashing: re-flash over USB or restore the backup image with write-flash 0 backup-2026-10.bin.

Clean-up and real-world practice

Stop the test web server, delete the backup images once you no longer need them (they contain your Wi-Fi password), and keep a version log. At work, the same ideas scale up: an inventory of firmware versions, vendor advisories, staged rollouts to a pilot group, maintenance windows and a rollback plan. UK and EU product security rules increasingly expect manufacturers to state how long devices will receive updates, which is worth checking before you buy.

Practice

Why is a SHA-256 hash in a manifest not enough on its own?
An attacker who controls the server can change both file and manifest; a signature verified with a key the attacker lacks is needed.
Why write the download to a temporary file first?
So a failed or partial download never replaces the working version.
What must you be careful of when enabling secure boot on an ESP32?
It burns eFuses permanently; mistakes cannot be undone, so practise on a spare board.

Key takeaways

  • Back up and record versions before any update.
  • Verify hashes, and in real products signatures, before installing.
  • Install to a temporary file or second slot and keep a rollback.
  • Roll out to a few devices first, then the rest.
  • Secure boot and flash encryption are permanent; practise on spares.
Tracks your learning on this device only. See your progress on the learning paths.

About the author

Mohamed Fayas

Founder of FM TecHub. CCNA certified, with a BTEC HND in Network Engineering, and BEng (Hons) in Computer Networking and Cloud Security. He writes practical, plain-English guides on networking, security and cloud.

More about the author

Original content written by Mohamed Fayas for FM TecHub. © 2026 FM TecHub. You're welcome to share a link to this page; please don't copy the text elsewhere without permission.

Stay up to date by email

New notes, tools and security news from FM TecHub, explained simply. Free.

We only use your email to send these updates. See our privacy policy.