Logging is essential for gathering debugging information, for carrying out incident response or forensics activities and for maintaining incriminating evidence. Nevertheless, logging sensitive data raises many concerns, including the privacy of the stakeholders, limitations imposed by the law on the collection of personal information, and the potential for data exposure through insiders. Sensitive information includes, but is not limited to, IP addresses, user names and passwords, email addresses, credit card numbers and any personally identifiable information such as social security numbers. Many countries prohibit or restrict collection of personal data; others permit retention of personal data only when held in an anonymized form. Consequently, ensure that logs contain only non-sensitive data.
Violations of this guideline are common. For example, prior to version 0.8.1, LineControl Java client logged sensitive information including the local user's password [[CVE 2008]].
The java.util.logging
class provides the basic logging framework in JDK v1.4
and above; the examples below use the logging framework. The basic principles apply regardless of the particular logging framework chosen.
Noncompliant Code Example
In this noncompliant code example, a server logs the IP address of the remote client in the event of a security exception. Such data can be misused in various ways, such as building a profile of a user's browsing habits. Such logging may violate legal restrictions in many countries.
public void logRemoteIPAddress(String name){ Logger logger = Logger.getLogger("com.organization.Log"); InetAddress machine = null; try { machine = InetAddress.getByName(name); } catch (UnknownHostException e){ Exception e = MyExceptionReporter.handle(e); } catch (SecurityException e){ Exception e = MyExceptionReporter.handle(e); logger.severe(name + "," + machine.getHostAddress() + "," + e.toString()); } }
Compliant Solution
This compliant solution excludes the sensitive information from the log message.
// ... catch (SecurityException e){ Exception e = MyExceptionReporter.handle(e); logger.log(Level.FINEST, "Security Exception Occurred", e); }
When an exception contains sensitive information, the custom MyExceptionReporter
class should extract or cleanse it, before returning control to the next statement in the catch
block. (See guideline EXC01-J. Use a class dedicated to reporting exceptions.)
Noncompliant Code Example
Some information that is logged should be elided from console display for security reasons (a possible example might be passenger age). The java.util.logging.Logger
class supports different logging levels that can be used for classifying such information. These are FINEST
, FINER
, FINE
, CONFIG
, INFO
, WARNING
and SEVERE
. All levels after and including INFO
, log the message to the console in addition to an external source.
logger.info(passengerAge); // displays passenger age on the console
Compliant Solution
This compliant solution logs at a level below INFO
— FINEST
, in this case — to prevent the passenger age from being displayed on the console.
logger.finest(passengerAge); // does not display on the console
Noncompliant Code Example
Sensitive user data can be recorded without deliberate intent; this can occur when the log message records user supplied input. In this noncompliant code example, the user mistakenly enters personal details (such as an SSN) in the occupation
field. A suspicious server might throw an exception during input validation and log the entered data so that intrusion detection systems can operate on it. However, logging personally identifiable information is undesirable, and possibly illegal.
String str = JOptionPane.showInputDialog(null, "Enter your occupation: ", "Tax Help Form", 1);
Compliant Solution
Apply a filter to the input to reduce inadvertent logging of sensitive data. This compliant solution uses a simple filter — a check for a string of digits that might have been intended for SSN
field that lies above the occupation
field — to prevent sensitive data from appearing in the log files. The example filter may be too simplistic for production use; ensure that your filters are sufficient to prevent violation of applicable legal restrictions.
public class MyFilter implements Filter { public boolean isLoggable(LogRecord lr) { String msg = lr.getMessage(); if (msg.matches("\\d*")) { // Filters out any digits return false; } return true; } } // Set the filter in main code Logger logger = Logger.getLogger("com.organization.Log"); logger.setFilter(new MyFilter());
NOTE: Log entries should contain additional parameters such as date, time, source event, etc.; these parameters are omitted for brevity.
Risk Assessment
Logging sensitive information can violate system security policies and can violate user privacy when the logging level is incorrect or when the log files are insecure.
Guideline |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
FIO08-J |
medium |
probable |
high |
P4 |
L3 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this guideline on the CERT website.
Bibliography
[[API 2006]]] Class java.util.logging.Logger
[[Chess 2007]]] 11.1 Privacy and Regulation: Handling Private Information
[[CVE 2008]]] CVE-2005-2990
[[MITRE 2009]] CWE ID 532 "Information Leak Through Log Files", CWE ID 533 "Information Leak Through Server Log Files", CWE ID 359 "Privacy Violation", CWE ID 542 "Information Leak Through Cleanup Log Files"
[[Sun 2006]]] Java Logging Overview
FIO07-J. Do not create temporary files in shared directories Input Output (FIO) FIO09-J. Exclude user input from format strings