rpcs3: 1 new defect (MOAD-0004 CWE-312 room password logged verbatim)
This commit is contained in:
parent
20b8a57f89
commit
0ba09a4f4c
3 changed files with 131 additions and 0 deletions
39
defects/rpcs3/patch/rpcs3-0004-np-room-password-cwe312.patch
Normal file
39
defects/rpcs3/patch/rpcs3-0004-np-room-password-cwe312.patch
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# UNDF: UNDF-2026-XXXXXXXXX
|
||||
--- a/rpcs3/Emu/NP/np_structs_extra.cpp
|
||||
+++ b/rpcs3/Emu/NP/np_structs_extra.cpp
|
||||
@@ -121,8 +121,8 @@ namespace np
|
||||
sceNp2.warning("roomPassword: *0x%x", req->roomPassword);
|
||||
|
||||
- if (req->roomPassword)
|
||||
- sceNp2.warning("data: %s", fmt::buf_to_hexstring(req->roomPassword->data, sizeof(req->roomPassword->data)));
|
||||
+ if (req->roomPassword)
|
||||
+ sceNp2.warning("data: [REDACTED %zu bytes]", sizeof(req->roomPassword->data));
|
||||
|
||||
sceNp2.warning("groupConfig: *0x%x", req->groupConfig);
|
||||
|
||||
# Defect: rpcs3-0004
|
||||
# MOAD: 0004 (CWE-312 — Cleartext Storage of Sensitive Information)
|
||||
# File: rpcs3/Emu/NP/np_structs_extra.cpp
|
||||
# Function: print_SceNpMatching2CreateJoinRoomRequest
|
||||
# Line: 124
|
||||
#
|
||||
# Description:
|
||||
# When a PS3 game creates or joins a password-protected online room via
|
||||
# SceNpMatching2, RPCS3 logs the raw session password bytes verbatim at
|
||||
# WARNING severity using buf_to_hexstring. The SceNpMatching2SessionPassword
|
||||
# struct holds up to SCE_NP_MATCHING2_SESSION_PASSWORD_SIZE (8) bytes of
|
||||
# opaque password material. Any logging framework that persists WARNING-level
|
||||
# output — file logs, remote log aggregators, crash-dump collectors — will
|
||||
# capture those bytes in cleartext (CWE-312).
|
||||
#
|
||||
# The JoinRoomRequest path (print_SceNpMatching2JoinRoomRequest) only logs the
|
||||
# pointer address, not the data, so that path is not affected.
|
||||
#
|
||||
# Severity: MEDIUM
|
||||
# - Requires WARNING log level to be active (on by default in debug builds)
|
||||
# - Password is 8 bytes of opaque PS3 material, used for session access control
|
||||
# - If logs are captured by a third-party service the password is exposed
|
||||
#
|
||||
# Fix:
|
||||
# Replace buf_to_hexstring(req->roomPassword->data, ...) with a redacted
|
||||
# placeholder that indicates the password is present but does not expose it.
|
||||
BIN
defects/rpcs3/test/Rpcs3NpPasswordTest.class
Normal file
BIN
defects/rpcs3/test/Rpcs3NpPasswordTest.class
Normal file
Binary file not shown.
92
defects/rpcs3/test/Rpcs3NpPasswordTest.java
Normal file
92
defects/rpcs3/test/Rpcs3NpPasswordTest.java
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Unit test for RPCS3 MOAD-0004 defect.
|
||||
*
|
||||
* rpcs3-0004: np_structs_extra.cpp print_SceNpMatching2CreateJoinRoomRequest
|
||||
* logs raw SceNpMatching2SessionPassword bytes via buf_to_hexstring
|
||||
* at WARNING level (CWE-312: Cleartext Storage of Sensitive Information).
|
||||
*
|
||||
* The fix: replace buf_to_hexstring with a redacted placeholder so password
|
||||
* material never enters our log stream.
|
||||
*/
|
||||
public class Rpcs3NpPasswordTest {
|
||||
|
||||
// Simulates the defective log serializer: formats raw bytes as hex
|
||||
static String logPassword_defective(byte[] passwordData) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : passwordData) {
|
||||
sb.append(String.format("%02x", b));
|
||||
}
|
||||
return sb.toString(); // raw hex of secret bytes in log output
|
||||
}
|
||||
|
||||
// Simulates the fixed log serializer: redacts the password
|
||||
static String logPassword_fixed(byte[] passwordData) {
|
||||
return "[REDACTED " + passwordData.length + " bytes]";
|
||||
}
|
||||
|
||||
// Checks whether a log entry contains any of the secret bytes
|
||||
static boolean logContainsSecret(String logEntry, byte[] secret) {
|
||||
// Build hex representation of secret
|
||||
StringBuilder hex = new StringBuilder();
|
||||
for (byte b : secret) hex.append(String.format("%02x", b));
|
||||
return logEntry.contains(hex.toString());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int passed = 0;
|
||||
int failed = 0;
|
||||
|
||||
// Representative SceNpMatching2SessionPassword: 8 bytes
|
||||
byte[] password = new byte[]{0x4e, 0x50, 0x33, (byte)0xDE, (byte)0xAD, (byte)0xBE, (byte)0xEF, 0x01};
|
||||
|
||||
// --- Test 1: defective path exposes raw bytes ---
|
||||
{
|
||||
String logEntry = logPassword_defective(password);
|
||||
boolean exposesSecret = logContainsSecret(logEntry, password);
|
||||
boolean ok = exposesSecret; // defective SHOULD contain the secret (confirming the defect)
|
||||
System.out.println((ok ? "PASS" : "FAIL") + " rpcs3-0004 defect confirmed: raw bytes in log = \"" + logEntry + "\"");
|
||||
if (ok) passed++; else failed++;
|
||||
}
|
||||
|
||||
// --- Test 2: fixed path does NOT expose raw bytes ---
|
||||
{
|
||||
String logEntry = logPassword_fixed(password);
|
||||
boolean exposesSecret = logContainsSecret(logEntry, password);
|
||||
boolean ok = !exposesSecret;
|
||||
System.out.println((ok ? "PASS" : "FAIL") + " rpcs3-0004 fix: secret absent from log = \"" + logEntry + "\"");
|
||||
if (ok) passed++; else failed++;
|
||||
}
|
||||
|
||||
// --- Test 3: fixed path still indicates presence of password (not null suppression) ---
|
||||
{
|
||||
String logEntry = logPassword_fixed(password);
|
||||
boolean ok = logEntry.contains("REDACTED") && logEntry.contains("8 bytes");
|
||||
System.out.println((ok ? "PASS" : "FAIL") + " rpcs3-0004 fix: placeholder present = \"" + logEntry + "\"");
|
||||
if (ok) passed++; else failed++;
|
||||
}
|
||||
|
||||
// --- Test 4: null/empty password handled gracefully ---
|
||||
{
|
||||
byte[] emptyPassword = new byte[0];
|
||||
String logEntry = logPassword_fixed(emptyPassword);
|
||||
boolean ok = logEntry.contains("REDACTED") && logEntry.contains("0 bytes");
|
||||
System.out.println((ok ? "PASS" : "FAIL") + " rpcs3-0004 fix: empty password placeholder = \"" + logEntry + "\"");
|
||||
if (ok) passed++; else failed++;
|
||||
}
|
||||
|
||||
// --- Test 5: all-zero password still redacted (not treated as absent) ---
|
||||
{
|
||||
byte[] zeroPassword = new byte[8]; // all zeros
|
||||
String logEntry = logPassword_fixed(zeroPassword);
|
||||
boolean exposesSecret = logEntry.contains("00000000"); // would be all zeros hex
|
||||
boolean ok = !exposesSecret && logEntry.contains("REDACTED");
|
||||
System.out.println((ok ? "PASS" : "FAIL") + " rpcs3-0004 fix: all-zero password redacted = \"" + logEntry + "\"");
|
||||
if (ok) passed++; else failed++;
|
||||
}
|
||||
|
||||
System.out.printf("%n%d/%d tests passed%n", passed, passed + failed);
|
||||
if (failed > 0) System.exit(1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue