T03 · Remote Payload Retrieval and Execution
Error
- Location
- references/examples.md:114
- Finding
- Unauthenticated Remote Firmware Retrieval and Execution<![CDATA[ ## Vulnerability Details **File Location**: `references/examples.md`, lines 114–159 and 554–558 **Vulnerability Type**: Insecure over-the-air firmware update mechanism **Risk Level**: Critical ### Vulnerable Code ```cpp void checkForUpdate() { if (updateInProgress) return; HTTPClient http; http.begin("http://update.server.com/firmware/latest.json"); int httpCode = http.GET(); if (httpCode == HTTP_CODE_OK) { DynamicJsonDocument doc(1024); DeserializationError error = deserializeJson(doc, http.getStream()); if (!error) { const char* latestVersion = doc["version"]; const char* updateUrl = doc["url"]; if (strcmp(latestVersion, FIRMWARE_VERSION) > 0) { performUpdate(updateUrl); } } } http.end(); } void performUpdate(const char* url) { updateInProgress = true; WiFiClient client; t_httpUpdate_return ret = httpUpdate.update(client, url); switch(ret) { case HTTP_UPDATE_FAILED: Serial.printf("Update failed: %s\n", httpUpdate.getLastErrorString().c_str()); break; case HTTP_UPDATE_NO_UPDATES: Serial.println("No updates available"); break; case HTTP_UPDATE_OK: Serial.println("Update successful, restarting..."); ESP.restart(); break; } updateInProgress = false; } ``` The update check is also invoked automatically: ```cpp // Periodic OTA check (once per hour) static unsigned long lastOTACheck = 0; if (millis() - lastOTACheck > 3600000) { otaHandler.checkForUpdate(); lastOTACheck = millis(); } ``` ### Technical Analysis Firmware metadata is retrieved over plaintext HTTP. The `url` field from that unauthenticated response is passed directly to `httpUpdate.update()` using a plaintext `WiFiClient`. The implementation does not e ...[truncated 1725 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Retrieve update manifests and images exclusively over HTTPS with strict certificate and hostname validation. - Consider certificate or public-key pinning for dedicated update infrastructure. - Reject update URLs whose scheme or host is not explicitly allowlisted. - Sign update manifests and firmware images with an offline-controlled signing key. - Embed only the trusted verification public key in the device and verify signatures before writing firmware. - Bind the signed manifest to the device model, hardware revision, firmware version, image length, and cryptographic digest. - Implement monotonic versioning and secure anti-rollback protection. - Stage updates in a non-active partition and validate them before changing the boot partition. - Retain a known-good recovery image and implement rollback after boot validation failure. - Fail closed on network, parsing, certificate, signature, version, or integrity errors. - Avoid accepting firmware locations directly from an unsigned network response. ]]>
