import java.util.ArrayList; import java.util.List; /** * Test for vlc-0003: CWE-312 SMB credentials logged verbatim via msg_Warn() * in modules/access/dsm/access.c (VLC SMB1 DSM access module). * * Pattern: * msg_Warn( p_access, "Creds: username = '%s', domain = '%s'", * psz_login, psz_domain ); * * This line executes on every successful SMB1 login, writing plaintext * username + domain to our VLC log (debug file, syslog, or any log sink). * VLC debug logs are routinely included in bug reports, exposing SMB * identity information (username + domain) to third parties. In corporate * environments, domain/username is sufficient to enumerate valid accounts * and facilitate lateral movement. * * Fix: remove our credential log line. Successful login is implicit from * reaching this code path without error. Username and domain do not need * to be announced in the log after authentication completes. * * Compile and run (no build tool required): * javac defects/vlc-0003/unit/VlcDsmCredentialLogTest.java -d /tmp/vlc-0003 * java -cp /tmp/vlc-0003 VlcDsmCredentialLogTest */ public class VlcDsmCredentialLogTest { private static int passed = 0; private static int failed = 0; // --- Simulated VLC log sink --- static class LogSink { private final List messages = new ArrayList<>(); void warn(String fmt, Object... args) { messages.add(String.format(fmt, args)); } boolean containsText(String text) { for (String m : messages) { if (m.contains(text)) return true; } return false; } int size() { return messages.size(); } } // --- Defective: logs username + domain via msg_Warn --- static void smbLoginDefective(LogSink log, String username, String domain) { // smb_connect() succeeds ... // smb_session_is_guest() returns 0 (not guest) boolean isGuest = false; if (!isGuest) { // CWE-312 site — logs credentials verbatim log.warn("Creds: username = '%s', domain = '%s'", username, domain); } // vlc_credential_store(...) } // --- Fixed: credential log line removed --- static void smbLoginFixed(LogSink log, String username, String domain) { // smb_connect() succeeds ... // No credential log line // vlc_credential_store(...) boolean isGuest = false; // isGuest path still logs the guest warning, but not credentials } // --- Tests --- static void testDefectiveLogsUsername() { LogSink log = new LogSink(); smbLoginDefective(log, "alice", "CORP"); check("defective path must log the username (confirms CWE-312 site present)", log.containsText("alice")); } static void testDefectiveLogsDomain() { LogSink log = new LogSink(); smbLoginDefective(log, "alice", "CORP"); check("defective path must log the domain name", log.containsText("CORP")); } static void testFixedDoesNotLogUsername() { LogSink log = new LogSink(); smbLoginFixed(log, "alice", "CORP"); check("fixed path must NOT log the SMB username", !log.containsText("alice")); } static void testFixedDoesNotLogDomain() { LogSink log = new LogSink(); smbLoginFixed(log, "alice", "CORP"); check("fixed path must NOT log the SMB domain", !log.containsText("CORP")); } static void testFixedSuppressesAllCredentials() { // Simulate 100 SMB1 logins — none should produce credential log entries String[] usernames = new String[100]; String[] domains = new String[100]; for (int i = 0; i < 100; i++) { usernames[i] = "user" + i; domains[i] = "DOMAIN" + i; } int leaks = 0; for (int i = 0; i < 100; i++) { LogSink log = new LogSink(); smbLoginFixed(log, usernames[i], domains[i]); if (log.containsText(usernames[i]) || log.containsText(domains[i])) { leaks++; } } check("fixed path must produce 0 credential leaks across 100 logins (got " + leaks + ")", leaks == 0); } static void testFixedProducesNoLogLines() { LogSink log = new LogSink(); smbLoginFixed(log, "administrator", "WORKGROUP"); check("fixed login produces no log output (login success is implicit)", log.size() == 0); } // --- 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("=== VlcDsmCredentialLogTest (vlc-0003, CWE-312 SMB credentials logged) ===\n"); testDefectiveLogsUsername(); testDefectiveLogsDomain(); testFixedDoesNotLogUsername(); testFixedDoesNotLogDomain(); testFixedSuppressesAllCredentials(); testFixedProducesNoLogLines(); System.out.println("\n--- " + passed + " passed, " + failed + " failed ---"); if (failed > 0) System.exit(1); } }