Logging is essential for gathering debugging information, carrying out incident response or forensics activities and for maintaining incriminating , and collecting forensic evidence. HoweverNevertheless, logging sensitive data should not be logged for many reasons. Privacy 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 by insiders are a few concerns. Sensitive information includes and , 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. For example, leaking unencrypted credit card numbers . In JDK v1.4
and above, the into a log file could be a violation of PCI DSS (Payment Card Industry Data Security Standard) regulations [PCI 2010]. Consequently, logs must not contain sensitive data, particularly when prohibited by law.
Unfortunately, violations of this rule are common. For example, prior to version 0.8.1, the LineControl Java client logged sensitive information, including the local user's password, as documented by CVE-2005-2990.
The java.util.logging
class provides a basic logging framework for JDK versions 1.4 and higher. Other logging frameworks exist, but the basic principles apply regardless of the particular logging framework chosen.
Programs typically support varying levels of protection. Some information, such as access times, can be safely logged. Some information can be logged, but the log file must be restricted from everyone but particular administrators. Other information, such as credit card numbers, can be included in logs only in encrypted form. Information such as passwords should not be logged at all.
For the following code examples, the log lies outside the trust boundary of the information being recorded. Also, normal log messages should include additional parameters such as date, time, source event, and so forth. This information has been omitted from the following code examples for brevity. While several instances of this anti-pattern can be found in the wild, one example is of the fix provided in the LineControl Java client. Prior to version 0.8.1, the client logged sensitive information such as the local user's password. \[[CVE 08|AA. Java References#CVE 08]\] Wiki Markup
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 This data can be misused for nefarious purposes such as building , for example, to build a profile of the a user's browsing habits. Many countries disallow the collection of non-anonymous personal data while others allow its retention in an anonymized formSuch logging may violate legal restrictions in many countries.
When the log cannot contain IP addresses, it should not contain any information about a SecurityException
, because it might leak an IP address. 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 ERR00-J. Do not suppress or ignore checked exceptions).
Code Block | ||
---|---|---|
| ||
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. does not log security exceptions except for the logging implicitly performed by MyExceptionReporter
:
Code Block | ||
---|---|---|
| ||
// ... catch (SecurityException e) { Exception e = MyExceptionReporter.handle(e); logger.log(Level.FINEST, "Security Exception Occurred", e); } |
If the exception contains sensitive information, the custom MyExceptionReporter
class should extract or cleanse it, before returning control to the next statement in the catch
block. (EXC05-J. Use a class dedicated to reporting exceptions)
Noncompliant Code Example
Sometimes, some information is fit to be logged but Log messages with sensitive information should not be displayed on printed to the console display for security reasons (for instance, a possible example of sensitive information is 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 By default, the INFO
, WARNING
, and SEVERE
levels print the message to the console in addition to an external source.
Code Block | ||
---|---|---|
| ||
logger.info(passengerAge); // displays passenger age on the console
|
Compliant Solution
This compliant solution logs at the FINEST
level so that the passenger age is not displayed on the console.
Code Block | ||
---|---|---|
| ||
logger.finest(passengerAge); // does not display on the console
|
Noncompliant Code Example
, which is accessible by end users and system administrators.
If we assume that the passenger age can appear in log files on the current system but not on the console display, this code example is noncompliantIt is also possible for sensitive user data to get recorded without deliberate intent, for example, when the log message uses 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 the entered data will be logged so that intrusion detection systems can operate on it. Clearly, logging personally identifiable information is undesirable.
Code Block | ||
---|---|---|
| ||
String str = JOptionPane.showInputDialog(null, "Enter your occupation: ", "Tax Help Form", 1logger.info("Age: " + passengerAge); |
Compliant Solution
As a first step, a filter can be applied to the input to prevent inadvertent logging of sensitive data. In this compliant solution, a check is enforced so that a string of digits from the SSN
field that lies above say the occupation
field, does not accidentally show up in the log filesThis compliant solution logs the passenger age at the FINEST
level to prevent this information from displaying on the console. As noted previously, we are assuming the age may appear in system log files but not on the console.
Code Block | ||
---|---|---|
| ||
public// classMake MyFiltersure implementsthat Filterall { handlers only publicprint booleanlog isLoggable(LogRecord lr) { String msg = lr.getMessagemessages rated INFO or higher Handler handlers[] = logger.getHandlers(); for (int i 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: A log entry should also contain other parameters such as date, time, source event and so on. Some of these parameters have been omitted from this example for the sake of brevity.
= 0; i < handlers.length; i++) {
handlers[i].setLevel(Level.INFO);
}
// ...
logger.finest("Age: " + passengerAge);
|
Risk Assessment
Logging sensitive information can break the security of the system and violate system security policies and can violate user privacy when the logging level is incorrect or when the log files are not secured properlyinsecure.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|
FIO13-J |
Medium |
Probable |
High | P4 | L3 |
Automated Detection
...
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Wiki Markup |
---|
\[[API 06|AA. Java References#API 06]\]] Class {{java.util.logging.Logger}}
\[[Sun 06|AA. Java References#Sun 06]\]] [Java Logging Overview|http://java.sun.com/javase/6/docs/technotes/guides/logging/overview.html]
\[[CVE 08|AA. Java References#CVE 08]\]] [CVE-2005-2990|http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-2990]
\[[Chess 07|AA. Java References#Chess 07]\]] 11.1 Privacy and Regulation: Handling Private Information
\[[MITRE 09|AA. Java References#MITRE 09]\] [CWE ID 532|http://cwe.mitre.org/data/definitions/532.html] "Information Leak Through Log Files", [CWE ID 533|http://cwe.mitre.org/data/definitions/533.html] "Information Leak Through Server Log Files", [CWE ID 359|http://cwe.mitre.org/data/definitions/359.html] "Privacy Violation", [CWE ID 542|http://cwe.mitre.org/data/definitions/542.html] "Information Leak Through Cleanup Log Files" |
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Parasoft Jtest |
| CERT.FIO13.SENS CERT.FIO13.LHII CERT.FIO13.PEO CERT.FIO13.CONSEN | Prevent exposure of sensitive data Avoid logging sensitive Hibernate-related information at the 'info' level in 'log4j.properties' files Do not pass exception messages into output in order to prevent the application from leaking sensitive information Do not log confidential or sensitive information |
Related Guidelines
CWE-359, Privacy Violation |
Android Implementation Details
DRD04-J. Do not log sensitive information is an Android-specific instance of this rule.
Bibliography
[API 2014] | |
Section 11.1, "Privacy and Regulation: Handling Private Information" | |
[CVE 2011] | |
Payment Card Industry (PCI) Data Security Standard | |
[Sun 2006] |
...
FIO03-J. Specify the character encoding while performing file or network IO 09. Input Output (FIO) FIO31-J. Defensively copy mutable inputs and mutable internal components