yabause: 1 CWE-312 defect, MOAD 0001/0002/0003/0005 CLEAN vita3k-0001: unit test added for pre-existing CWE-407 patch
153 lines
5.9 KiB
Java
153 lines
5.9 KiB
Java
import java.util.*;
|
|
import java.util.regex.*;
|
|
|
|
/**
|
|
* Unit test for ZEsarUX CWE-312 defect zesarux-0001.
|
|
*
|
|
* zesarux-0001: The ZRCP remote command dispatcher logs the full command
|
|
* string and parameter string verbatim at VERBOSE_DEBUG level. ZENG
|
|
* multiplayer commands carry creator_pass and user_pass as inline parameters
|
|
* (e.g. "authorize-join SECRET123 0 rw"). Any debug log or terminal capture
|
|
* will contain the plaintext session credential.
|
|
*
|
|
* Models the C logging behaviour and verifies the fix (redaction).
|
|
*/
|
|
public class ZesaruxZrcpCredentialLogTest {
|
|
|
|
/** Simulates a debug log sink. */
|
|
static class DebugLog {
|
|
private final List<String> entries = new ArrayList<>();
|
|
|
|
void log(String msg) {
|
|
entries.add(msg);
|
|
}
|
|
|
|
List<String> getEntries() {
|
|
return Collections.unmodifiableList(entries);
|
|
}
|
|
|
|
boolean anyEntryContains(String substring) {
|
|
for (String e : entries) {
|
|
if (e.contains(substring)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------
|
|
// DEFECTIVE: logs full command and parameter strings verbatim
|
|
// ---------------------------------------------------------------
|
|
|
|
static void defectiveProcessCommand(DebugLog log, String command) {
|
|
int len = command.length();
|
|
// Line 3884: logs full command including inline password
|
|
log.log(String.format("Remote command: length: %d [%s]", len, command));
|
|
|
|
// Split into verb + parameters (simple split on first space)
|
|
int spaceIdx = command.indexOf(' ');
|
|
String verb = (spaceIdx >= 0) ? command.substring(0, spaceIdx) : command;
|
|
String params = (spaceIdx >= 0) ? command.substring(spaceIdx + 1) : "";
|
|
|
|
log.log(String.format("Remote command without parameters: length: %d [%s]",
|
|
verb.length(), verb));
|
|
|
|
// Line 3963: logs parameters verbatim — exposes password as first token
|
|
log.log(String.format("Remote command parameters: length: %d [%s]",
|
|
params.length(), params));
|
|
}
|
|
|
|
// ---------------------------------------------------------------
|
|
// FIXED: logs length only, redacts parameter values
|
|
// ---------------------------------------------------------------
|
|
|
|
static void fixedProcessCommand(DebugLog log, String command) {
|
|
int len = command.length();
|
|
// Patched line 3884: length only, no body
|
|
log.log(String.format("Remote command: length: %d", len));
|
|
|
|
int spaceIdx = command.indexOf(' ');
|
|
String verb = (spaceIdx >= 0) ? command.substring(0, spaceIdx) : command;
|
|
String params = (spaceIdx >= 0) ? command.substring(spaceIdx + 1) : "";
|
|
|
|
log.log(String.format("Remote command without parameters: length: %d [%s]",
|
|
verb.length(), verb));
|
|
|
|
// Patched line 3963: parameter length + REDACTED placeholder
|
|
log.log(String.format("Remote command parameters: length: %d [REDACTED]",
|
|
params.length()));
|
|
}
|
|
|
|
// ---------------------------------------------------------------
|
|
// ZENG commands that carry a password as first or later parameter
|
|
// ---------------------------------------------------------------
|
|
|
|
static final String[][] CREDENTIAL_COMMANDS = {
|
|
{"authorize-join", "CREATORPASS_ALPHA 0 rw"},
|
|
{"destroy-room", "CREATORPASS_BETA 1"},
|
|
{"get-keys", "USERPASS_GAMMA 0"},
|
|
{"kick", "CREATORPASS_DELTA 0 uuid-1234"},
|
|
{"leave", "0 USERPASS_EPSILON uuid-5678"},
|
|
{"rename-room", "CREATORPASS_ZETA 0 MyRoom"},
|
|
{"put-snapshot", "CREATORPASS_ETA 0 DEADBEEF"},
|
|
{"send-keys", "USERPASS_THETA 0 uuid-9999 65 1 0"},
|
|
};
|
|
|
|
public static void main(String[] args) {
|
|
int pass = 0;
|
|
int fail = 0;
|
|
|
|
for (String[] entry : CREDENTIAL_COMMANDS) {
|
|
String verb = entry[0];
|
|
String params = entry[1];
|
|
// Extract the password token (first token of params)
|
|
String password = params.split(" ")[0];
|
|
String command = verb + " " + params;
|
|
|
|
// -- DEFECTIVE: password must appear in log --
|
|
DebugLog defLog = new DebugLog();
|
|
defectiveProcessCommand(defLog, command);
|
|
|
|
boolean defectiveExposes = defLog.anyEntryContains(password);
|
|
if (defectiveExposes) {
|
|
System.out.println("PASS (defect confirmed): " + verb
|
|
+ " exposes '" + password + "' in log");
|
|
pass++;
|
|
} else {
|
|
System.out.println("FAIL (defect NOT confirmed): " + verb
|
|
+ " did not expose '" + password + "' — test is wrong");
|
|
fail++;
|
|
}
|
|
|
|
// -- FIXED: password must NOT appear in log --
|
|
DebugLog fixLog = new DebugLog();
|
|
fixedProcessCommand(fixLog, command);
|
|
|
|
boolean fixedExposes = fixLog.anyEntryContains(password);
|
|
if (!fixedExposes) {
|
|
System.out.println("PASS (fix confirmed): " + verb
|
|
+ " does NOT expose '" + password + "' after fix");
|
|
pass++;
|
|
} else {
|
|
System.out.println("FAIL (fix broken): " + verb
|
|
+ " still exposes '" + password + "' after fix");
|
|
fail++;
|
|
}
|
|
|
|
// -- FIXED: [REDACTED] placeholder must appear --
|
|
boolean hasRedacted = fixLog.anyEntryContains("[REDACTED]");
|
|
if (hasRedacted) {
|
|
System.out.println("PASS (redaction marker present): " + verb);
|
|
pass++;
|
|
} else {
|
|
System.out.println("FAIL (no redaction marker): " + verb);
|
|
fail++;
|
|
}
|
|
}
|
|
|
|
System.out.println();
|
|
System.out.println("Results: " + pass + " passed, " + fail + " failed");
|
|
if (fail > 0) {
|
|
System.exit(1);
|
|
}
|
|
}
|
|
}
|