zesarux: 1 CWE-312 defect, MOAD 0001/0002/0003/0005 CLEAN
yabause: 1 CWE-312 defect, MOAD 0001/0002/0003/0005 CLEAN vita3k-0001: unit test added for pre-existing CWE-407 patch
This commit is contained in:
parent
c7344d5783
commit
2f0da6752a
15 changed files with 741 additions and 0 deletions
217
defects/yabause-0001/test/YabauseNetlinkCredentialLogTest.java
Normal file
217
defects/yabause-0001/test/YabauseNetlinkCredentialLogTest.java
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Unit test for yabause CWE-312 defect yabause-0001.
|
||||
*
|
||||
* yabause-0001: In yabause/src/netlink.c, NetlinkWriteByte() handles the
|
||||
* Saturn NetLink modem dial-up login sequence. When NETLINK_DEBUG is
|
||||
* compiled in, two NETLINK_LOG calls write the Saturn internet credentials
|
||||
* verbatim into the debug log:
|
||||
*
|
||||
* Line 582: NETLINK_LOG("login response: %s", inbuffer+inbufferstart)
|
||||
* Line 592: NETLINK_LOG("password response: %s", inbuffer+inbufferstart)
|
||||
*
|
||||
* This test models the C logging logic and verifies the redaction fix.
|
||||
*/
|
||||
public class YabauseNetlinkCredentialLogTest {
|
||||
|
||||
/** Connection state machine, mirroring NL_CONNECTSTATUS_* enum. */
|
||||
enum ConnectStatus {
|
||||
IDLE, LOGIN1, LOGIN2, LOGIN3, CONNECTED
|
||||
}
|
||||
|
||||
/** Simulates the NETLINK_LOG debug output sink. */
|
||||
static class NetlinkLog {
|
||||
private final List<String> entries = new ArrayList<>();
|
||||
|
||||
void log(String msg) {
|
||||
entries.add(msg);
|
||||
}
|
||||
|
||||
boolean anyEntryContains(String substring) {
|
||||
for (String e : entries) {
|
||||
if (e.contains(substring)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
List<String> getEntries() {
|
||||
return Collections.unmodifiableList(entries);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// DEFECTIVE: logs login name and password verbatim
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
static ConnectStatus defectiveHandleCarriageReturn(
|
||||
NetlinkLog log, ConnectStatus status, String inbuffer) {
|
||||
|
||||
if (status == ConnectStatus.LOGIN1) {
|
||||
// Line 582 — logs login name verbatim
|
||||
log.log(String.format("login response: %s", inbuffer));
|
||||
return ConnectStatus.LOGIN2;
|
||||
}
|
||||
if (status == ConnectStatus.LOGIN2) {
|
||||
// Line 592 — logs password verbatim
|
||||
log.log(String.format("password response: %s", inbuffer));
|
||||
return ConnectStatus.LOGIN3;
|
||||
}
|
||||
if (status == ConnectStatus.LOGIN3) {
|
||||
log.log(String.format("shell response: %s", inbuffer));
|
||||
return ConnectStatus.CONNECTED;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// FIXED: redacts credentials, logs byte count only
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
static ConnectStatus fixedHandleCarriageReturn(
|
||||
NetlinkLog log, ConnectStatus status, String inbuffer) {
|
||||
|
||||
if (status == ConnectStatus.LOGIN1) {
|
||||
// Patched line 582: redacted
|
||||
log.log(String.format("login response: [REDACTED %d bytes]",
|
||||
inbuffer.length()));
|
||||
return ConnectStatus.LOGIN2;
|
||||
}
|
||||
if (status == ConnectStatus.LOGIN2) {
|
||||
// Patched line 592: redacted
|
||||
log.log(String.format("password response: [REDACTED %d bytes]",
|
||||
inbuffer.length()));
|
||||
return ConnectStatus.LOGIN3;
|
||||
}
|
||||
if (status == ConnectStatus.LOGIN3) {
|
||||
log.log(String.format("shell response: %s", inbuffer));
|
||||
return ConnectStatus.CONNECTED;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Test cases
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
static class TestCase {
|
||||
final String loginName;
|
||||
final String password;
|
||||
|
||||
TestCase(String loginName, String password) {
|
||||
this.loginName = loginName;
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
|
||||
static final TestCase[] CASES = {
|
||||
new TestCase("saturn_user", "hunter2"),
|
||||
new TestCase("netlink_player", "S3cr3tP@ss"),
|
||||
new TestCase("segaNet001", "CorrectHorseBattery"),
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
int pass = 0;
|
||||
int fail = 0;
|
||||
|
||||
for (TestCase tc : CASES) {
|
||||
// --- DEFECTIVE path ---
|
||||
NetlinkLog defLog = new NetlinkLog();
|
||||
ConnectStatus s = ConnectStatus.LOGIN1;
|
||||
|
||||
s = defectiveHandleCarriageReturn(defLog, s, tc.loginName);
|
||||
s = defectiveHandleCarriageReturn(defLog, s, tc.password);
|
||||
defectiveHandleCarriageReturn(defLog, s, "$ ");
|
||||
|
||||
boolean defExpLogin = defLog.anyEntryContains(tc.loginName);
|
||||
boolean defExpPass = defLog.anyEntryContains(tc.password);
|
||||
|
||||
if (defExpLogin) {
|
||||
System.out.println("PASS (defect confirmed): login name '"
|
||||
+ tc.loginName + "' appears in defective log");
|
||||
pass++;
|
||||
} else {
|
||||
System.out.println("FAIL (defect NOT confirmed): login name '"
|
||||
+ tc.loginName + "' missing from defective log");
|
||||
fail++;
|
||||
}
|
||||
|
||||
if (defExpPass) {
|
||||
System.out.println("PASS (defect confirmed): password '"
|
||||
+ tc.password + "' appears in defective log");
|
||||
pass++;
|
||||
} else {
|
||||
System.out.println("FAIL (defect NOT confirmed): password '"
|
||||
+ tc.password + "' missing from defective log");
|
||||
fail++;
|
||||
}
|
||||
|
||||
// --- FIXED path ---
|
||||
NetlinkLog fixLog = new NetlinkLog();
|
||||
s = ConnectStatus.LOGIN1;
|
||||
|
||||
s = fixedHandleCarriageReturn(fixLog, s, tc.loginName);
|
||||
s = fixedHandleCarriageReturn(fixLog, s, tc.password);
|
||||
fixedHandleCarriageReturn(fixLog, s, "$ ");
|
||||
|
||||
boolean fixExpLogin = fixLog.anyEntryContains(tc.loginName);
|
||||
boolean fixExpPass = fixLog.anyEntryContains(tc.password);
|
||||
|
||||
if (!fixExpLogin) {
|
||||
System.out.println("PASS (fix confirmed): login name '"
|
||||
+ tc.loginName + "' NOT in fixed log");
|
||||
pass++;
|
||||
} else {
|
||||
System.out.println("FAIL (fix broken): login name '"
|
||||
+ tc.loginName + "' still appears in fixed log");
|
||||
fail++;
|
||||
}
|
||||
|
||||
if (!fixExpPass) {
|
||||
System.out.println("PASS (fix confirmed): password '"
|
||||
+ tc.password + "' NOT in fixed log");
|
||||
pass++;
|
||||
} else {
|
||||
System.out.println("FAIL (fix broken): password '"
|
||||
+ tc.password + "' still appears in fixed log");
|
||||
fail++;
|
||||
}
|
||||
|
||||
// Redaction markers must be present
|
||||
boolean hasLoginRedact = fixLog.anyEntryContains("login response: [REDACTED");
|
||||
boolean hasPassRedact = fixLog.anyEntryContains("password response: [REDACTED");
|
||||
|
||||
if (hasLoginRedact) {
|
||||
System.out.println("PASS (login redaction marker present)");
|
||||
pass++;
|
||||
} else {
|
||||
System.out.println("FAIL (login redaction marker missing)");
|
||||
fail++;
|
||||
}
|
||||
|
||||
if (hasPassRedact) {
|
||||
System.out.println("PASS (password redaction marker present)");
|
||||
pass++;
|
||||
} else {
|
||||
System.out.println("FAIL (password redaction marker missing)");
|
||||
fail++;
|
||||
}
|
||||
|
||||
// Shell response (non-credential) must still log verbatim
|
||||
boolean shellVisible = fixLog.anyEntryContains("shell response: $ ");
|
||||
if (shellVisible) {
|
||||
System.out.println("PASS (non-credential shell response visible)");
|
||||
pass++;
|
||||
} else {
|
||||
System.out.println("FAIL (non-credential shell response missing)");
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Results: " + pass + " passed, " + fail + " failed");
|
||||
if (fail > 0) {
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue