fix: Harden command auth and prevent remote auth disable
- Flip cmd_requires_auth() from blacklist to whitelist: only read-only query commands are unauthenticated, all state-modifying commands now require HMAC (VULN-007) - Block AUTH OFF command to prevent remote auth disable; secret rotation still allowed, full reset via FACTORY (VULN-005) - Redact auth secret in boot log to first 4 chars only (VULN-003) - Update HELP text to reflect AUTH change
This commit is contained in:
@@ -352,7 +352,7 @@ static void config_load_nvs(void)
|
||||
}
|
||||
s_auth_secret[32] = '\0';
|
||||
config_save_str("auth_secret", s_auth_secret);
|
||||
ESP_LOGW(TAG, "AUTH: generated secret: %s (note this for remote access)", s_auth_secret);
|
||||
ESP_LOGW(TAG, "AUTH: secret generated (%.4s... — retrieve via serial or NVS)", s_auth_secret);
|
||||
}
|
||||
|
||||
/* Boot counter — always increment, even on first boot */
|
||||
@@ -1512,13 +1512,26 @@ static const char *auth_verify(const char *input, char *reply, size_t reply_size
|
||||
|
||||
static bool cmd_requires_auth(const char *cmd)
|
||||
{
|
||||
if (strncmp(cmd, "OTA ", 4) == 0) return true;
|
||||
if (strcmp(cmd, "FACTORY") == 0) return true;
|
||||
if (strcmp(cmd, "REBOOT") == 0) return true;
|
||||
if (strncmp(cmd, "TARGET ", 7) == 0) return true;
|
||||
if (strncmp(cmd, "AUTH ", 5) == 0) return true;
|
||||
if (strncmp(cmd, "HOSTNAME ", 9) == 0) return true;
|
||||
return false;
|
||||
/* Whitelist: read-only / query commands that don't modify state */
|
||||
if (strcmp(cmd, "STATUS") == 0) return false;
|
||||
if (strcmp(cmd, "CONFIG") == 0) return false;
|
||||
if (strcmp(cmd, "PROFILE") == 0) return false;
|
||||
if (strcmp(cmd, "PING") == 0) return false;
|
||||
if (strcmp(cmd, "HELP") == 0) return false;
|
||||
if (strcmp(cmd, "HOSTNAME") == 0) return false;
|
||||
if (strcmp(cmd, "CSI") == 0) return false;
|
||||
if (strcmp(cmd, "CSIMODE") == 0) return false;
|
||||
if (strcmp(cmd, "POWERSAVE") == 0) return false;
|
||||
if (strcmp(cmd, "PRESENCE") == 0) return false;
|
||||
if (strcmp(cmd, "CHANSCAN") == 0) return false;
|
||||
if (strcmp(cmd, "FLOODTHRESH") == 0) return false;
|
||||
if (strcmp(cmd, "AUTH") == 0) return false;
|
||||
if (strcmp(cmd, "ALERT") == 0) return false;
|
||||
if (strcmp(cmd, "LED") == 0) return false;
|
||||
if (strcmp(cmd, "LOG") == 0) return false;
|
||||
if (strcmp(cmd, "CALIBRATE STATUS") == 0) return false;
|
||||
/* Everything else modifies state and requires auth */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* --- Command handler --- */
|
||||
@@ -2086,7 +2099,7 @@ static int cmd_handle(const char *cmd, char *reply, size_t reply_size)
|
||||
return strlen(reply);
|
||||
}
|
||||
|
||||
/* AUTH [secret|OFF] */
|
||||
/* AUTH [secret] — rotate secret (disable not allowed remotely) */
|
||||
if (strcmp(cmd, "AUTH") == 0) {
|
||||
snprintf(reply, reply_size, "OK AUTH %s", s_auth_secret[0] ? "on" : "off");
|
||||
return strlen(reply);
|
||||
@@ -2094,9 +2107,8 @@ static int cmd_handle(const char *cmd, char *reply, size_t reply_size)
|
||||
if (strncmp(cmd, "AUTH ", 5) == 0) {
|
||||
const char *arg = cmd + 5;
|
||||
if (strcmp(arg, "OFF") == 0) {
|
||||
s_auth_secret[0] = '\0';
|
||||
config_save_str("auth_secret", "");
|
||||
snprintf(reply, reply_size, "OK AUTH off");
|
||||
snprintf(reply, reply_size, "ERR AUTH cannot be disabled remotely (use FACTORY to reset)");
|
||||
return strlen(reply);
|
||||
} else {
|
||||
size_t alen = strlen(arg);
|
||||
if (alen < 8 || alen > 64) {
|
||||
@@ -2407,7 +2419,7 @@ static int cmd_handle(const char *cmd, char *reply, size_t reply_size)
|
||||
"BLE [ON|OFF] SCANRATE <5-300> PROBERATE <1-300>\n"
|
||||
"CALIBRATE [STATUS|CLEAR|N] PRESENCE [ON|OFF|THRESHOLD]\n"
|
||||
"CHANSCAN [ON|OFF|NOW|INTERVAL] LED [QUIET|AUTO]\n"
|
||||
"POWERSAVE [ON|OFF] AUTH [secret|OFF] FLOODTHRESH <n> [win]\n"
|
||||
"POWERSAVE [ON|OFF] AUTH [secret] FLOODTHRESH <n> [win]\n"
|
||||
"ALERT [TEMP <c>|HEAP <bytes>|OFF] LOG <level> RSSI RESET\n"
|
||||
"OTA <url> POWERTEST [dwell] IDENTIFY REBOOT FACTORY");
|
||||
return pos;
|
||||
|
||||
Reference in New Issue
Block a user