3.8 KiB
UNDF: UNDF-2026-000001105
UNDF: (assigned later)
Target: irssi
MOAD: 0004 — CWE-312 Cleartext Storage of Sensitive Information
Severity: HIGH
File: src/core/rawlog.c + src/irc/core/irc-servers.c
Summary
irssi's rawlog facility records all outbound IRC commands verbatim to an
in-memory ring buffer (default 200 lines) and optionally to a file on disk
via /rawlog open <file>. Every command sent via irc_send_cmd_now() flows
through rawlog_output(), including credentials sent during connection setup.
Two credential exposure paths exist:
Path 1 — Server password (PASS command)
src/irc/core/irc-servers.c:223:
cmd = g_strdup_printf("PASS %s", conn->password);
irc_send_cmd_now(server, cmd);
irc_send_cmd_now → irc_send_cmd_full → irc_server_send_data →
rawlog_output(server->rawlog, str->str) (irc-servers.c:747)
Result: << PASS secretpassword123 appears in the rawlog ring buffer and,
if the user has run /rawlog open irc.log, in the log file on disk.
Path 2 — SASL PLAIN credentials (AUTHENTICATE command)
src/irc/core/sasl.c — sasl_step_complete():
g_string_append(resp, conn->sasl_username);
g_string_append_c(resp, '\0');
g_string_append(resp, conn->sasl_username);
g_string_append_c(resp, '\0');
g_string_append(resp, conn->sasl_password);
sasl_send_response(server, resp); // → irc_send_cmdv(server, "AUTHENTICATE %.*s", ...)
sasl_send_response calls irc_send_cmdv which calls irc_send_cmd which
goes through the same rawlog path.
Result: << AUTHENTICATE dXNlcm5hbWUAdXNlcm5hbWUAcGFzc3dvcmQ= (base64 of
username\0username\0password) appears in rawlog. The base64 is trivially
decoded: echo dXNlcm5hbWUAdXNlcm5hbWUAcGFzc3dvcmQ= | base64 -d.
Proxy password exposure (bonus)
src/irc/core/irc-servers.c:271:
cmd = g_strdup_printf("PASS %s", conn->proxy_password);
irc_send_cmd_now(server, cmd);
Same path — proxy PASS also logged.
Attack Scenario
- User runs
/rawlog open ~/irc-debug.logto debug a connection issue. - User reconnects to their IRC server (triggers PASS or SASL PLAIN).
- Log file now contains plaintext or trivially-decoded credentials.
- File may be exfiltrated via: shared home directories, backup systems, shell history leaks, or a compromised process with file-read access.
Even without /rawlog open, the in-memory ring buffer (200 lines) is
accessible to Perl scripts via $server->{rawlog} — a malicious plugin
or a plugin with an XSS/eval-equivalent vulnerability could read it.
Fix
Redact PASS and AUTHENTICATE commands before passing to rawlog:
// In rawlog_output() or in the send path, apply a credential denylist:
static char *redact_credential_command(const char *str) {
if (g_ascii_strncasecmp(str, "PASS ", 5) == 0)
return g_strdup("PASS ***");
if (g_ascii_strncasecmp(str, "AUTHENTICATE ", 13) == 0)
return g_strdup("AUTHENTICATE ***");
return g_strdup(str);
}
Apply in rawlog_output() before storing/writing:
void rawlog_output(RAWLOG_REC *rawlog, const char *str) {
char *safe = redact_credential_command(str);
rawlog_add(rawlog, g_strdup_printf("<< %s", safe));
g_free(safe);
}
Alternatively, pass a sensitive flag through the send path and suppress
rawlog entirely for those commands (precedent: OpenSSH does not log
USERAUTH_REQUEST payloads in its protocol trace).
Impact
- Credentials written to disk if rawlog file is active (user opt-in but common during debugging)
- Credentials in memory ring buffer accessible to all Perl plugins
- SASL PLAIN especially dangerous: base64 is not encryption; any reader of the rawlog immediately has the plaintext password
References
- CWE-312: Cleartext Storage of Sensitive Information
- irssi rawlog: https://irssi.org/documentation/rawlog/
- IRCv3 SASL PLAIN: https://ircv3.net/specs/extensions/sasl-3.1.html