java-topology/defects/esp-idf-0001/test/EspIdf0001Test.java

131 lines
4.5 KiB
Java

import java.util.ArrayList;
import java.util.List;
/**
* Test for esp-idf-0001: CWE-312 WiFi password logged verbatim via ESP_LOGD
* in components/esp_wifi/src/smartconfig.c handler_got_ssid_passwd().
*
* Pattern:
* ESP_LOGD(TAG, "PASSWORD:%s", password)
*
* When debug logging is enabled the WiFi PSK (pre-shared key) is emitted
* verbatim to serial/JTAG output. Any listener on those interfaces obtains
* the plaintext credential without any further effort.
*
* Fix: remove the ESP_LOGD("PASSWORD:%s", ...) line. SSID logging (non-secret)
* is acceptable; PSK logging is not.
*
* Compile and run (no build tool required):
* javac defects/esp-idf-0001/test/EspIdf0001Test.java -d /tmp/esp-idf-0001
* java -cp /tmp/esp-idf-0001 EspIdf0001Test
*/
public class EspIdf0001Test {
private static int passed = 0;
private static int failed = 0;
// --- Simulated log collector ---
static class LogCollector {
private final List<String> lines = new ArrayList<>();
void logd(String tag, String fmt, Object... args) {
lines.add(String.format(fmt, args));
}
boolean containsText(String text) {
for (String line : lines) {
if (line.contains(text)) return true;
}
return false;
}
int size() { return lines.size(); }
}
// --- Defective: logs password in DEBUG output ---
static void handleGotSsidPasswdDefective(String ssid, String password, LogCollector log) {
log.logd("smartconfig", "SSID:%s", ssid);
log.logd("smartconfig", "PASSWORD:%s", password); // CWE-312 site
log.logd("smartconfig", "Phone ip: 192.168.1.1");
}
// --- Fixed: password line removed ---
static void handleGotSsidPasswdFixed(String ssid, String password, LogCollector log) {
log.logd("smartconfig", "SSID:%s", ssid);
// PASSWORD log line removed — fix for esp-idf-0001
log.logd("smartconfig", "Phone ip: 192.168.1.1");
}
// --- Tests ---
static void testDefectiveLogsPassword() {
LogCollector log = new LogCollector();
String password = "MySecretWiFiPSK123";
handleGotSsidPasswdDefective("MyNet", password, log);
check("defective must log the password (confirms CWE-312 site is present)",
log.containsText(password));
}
static void testFixedDoesNotLogPassword() {
LogCollector log = new LogCollector();
String password = "MySecretWiFiPSK123";
handleGotSsidPasswdFixed("MyNet", password, log);
check("fixed must NOT log the WiFi PSK in any log line",
!log.containsText(password));
}
static void testFixedStillLogsSsid() {
LogCollector log = new LogCollector();
handleGotSsidPasswdFixed("HomeNetwork_5GHz", "secret", log);
check("SSID (non-sensitive) must still appear in logs after fix",
log.containsText("HomeNetwork_5GHz"));
}
static void testFixedHasFewerLines() {
LogCollector defLog = new LogCollector();
LogCollector fixLog = new LogCollector();
handleGotSsidPasswdDefective("net", "pw", defLog);
handleGotSsidPasswdFixed("net", "pw", fixLog);
check("fixed version produces fewer log lines than defective",
fixLog.size() < defLog.size());
}
static void testPasswordNotLeakedAcrossMultipleCalls() {
// Simulate multiple smartconfig events — none should leak password
String[] passwords = {"PSK-alpha", "PSK-beta", "PSK-gamma"};
for (String pw : passwords) {
LogCollector log = new LogCollector();
handleGotSsidPasswdFixed("net", pw, log);
check("password '" + pw + "' must not appear in any log line",
!log.containsText(pw));
}
}
// --- Harness ---
static void check(String desc, boolean cond) {
if (cond) {
System.out.println(" PASS: " + desc);
passed++;
} else {
System.out.println(" FAIL: " + desc);
failed++;
}
}
public static void main(String[] args) {
System.out.println("=== EspIdf0001Test (CWE-312 WiFi PSK logged) ===\n");
testDefectiveLogsPassword();
testFixedDoesNotLogPassword();
testFixedStillLogsSsid();
testFixedHasFewerLines();
testPasswordNotLeakedAcrossMultipleCalls();
System.out.println("\n--- " + passed + " passed, " + failed + " failed ---");
if (failed > 0) System.exit(1);
}
}