Proper input validation can ensure that sanitization can prevent insertion of malicious data is not inserted into the systeminto a subsystem such as a database. However, it fails to provide the assurance that validated data will remain consistent throughout its lifetime. For instance, if an insider is allowed to insert data into a database without validation, it is possible to glean unauthorized information or execute arbitrary code on the client side by means of attacks such as Cross Site Scripting (XSS). Consequently, output filtering is as important as input validation. different subsystems require different types of sanitization. Fortunately, it is usually obvious which subsystems will eventually receive which inputs, and consequently what type of sanitization is required.
Several subsystems exist for the purpose of outputting data. An HTML renderer is one common subsystem for displaying output. Data sent to an output subsystem may appear to originate from a trusted source. However, it is dangerous to assume that output sanitization is unnecessary because such data may indirectly originate from an untrusted source and may include malicious content. Failure to properly sanitize data passed to an output subsystem can allow several types of attacks. For example, HTML renderers are prone to HTML injection and cross-site scripting (XSS) attacks [OWASP 2011]. Output sanitization to prevent such attacks is as vital as input sanitization.
As with input validation, data must should be normalized before sanitizing it is filtered for malicious characters. To ensure that any data that bypasses the validation does not cause vulnerabilities, it is highly recommended that output characters be encoded, except those that are known to be safeProperly encode all output characters other than those known to be safe to avoid vulnerabilities caused by data that bypasses validation. See IDS01-J. Normalize strings before validating them for more information.
Noncompliant Code Example
This noncompliant code example displays input obtained from a database directly uses the model-view-controller (MVC) concept of the Java EE–based Spring Framework to display data to the user without performing any output validation or encodingencoding or escaping it. Because the data is sent to a web browser, the code is subject to both HTML injection and XSS attacks.
Code Block | ||
---|---|---|
| ||
@RequestMapping("/getnotifications.htm") public class BadOutput ModelAndView getNotifications( HttpServletRequest request, HttpServletResponse response) { ModelAndView publicmv static= voidnew displayModelAndView(); try { UserInfo userDetails = getUserInfo(); List<Map<String,Object>> list = new ArrayList<Map<String, Object>>(); List<Notification> notificationList = NotificationService.getNotificationsForUserId(userDetails.getPersonId()); // description and input are String variables containing valuesfor obtained(Notification fromnotification: anotificationList) database{ // description = "description" and input = "<script> XSS </script>" // display to the user or pass description and input to another system } } |
Compliant Solution
Map<String,Object> map = new HashMap<String, Object>();
map.put("id", notification.getId());
map.put("message", notification.getMessage());
list.add(map);
}
mv.addObject("Notifications", list);
}
catch(Throwable t) {
// Log to file and handle
}
return mv;
}
|
Compliant Solution
This compliant solution defines a ValidateOutput
class that normalizes the output to a known character set, performs output sanitization using a whitelist, and encodes any unspecified data values to enforce a double-checking mechanism. Note that the required whitelisting patterns can vary according to the specific needs of different fields [OWASP 2013]. This compliant solution defines a {{ValidateOutput}} class that normalizes the output to a known character set, performs output validation using a whitelist and encodes any non-specified data to enforce a double checking mechanism. Different fields may require different whitelisting patterns. \[[OWASP 08|AA. Java References#OWASP 08]\] Wiki Markup
Code Block | ||
---|---|---|
| ||
public class ValidateOutput { // allowsAllows only alphanumeric characters and spaces private static final Pattern pattern = Pattern.compile("^[a-zA-Z0-9\\s]{0,20}$"); // validatesValidates and encodes the input field based on a whitelist privatepublic String validate(String name, String input) throws ValidationException { String canonical = normalize(input); if (!pattern.matcher(canonical).matches()) { throw new ValidationException( "Improper format in " + name + " field"); } // performsPerforms output encoding for non validnonvalid characters canonical = HTMLEntityEncode(canonical); return canonical; } // normalizesNormalizes to known instances private String normalize(String input) { String canonical = java.text.Normalizer.normalize(input, Normalizer.Form.NFKC); return canonical; } // Encodes nonnonvalid valid data publicprivate static String HTMLEntityEncode(String input) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < input.length(); i++i) { char ch = input.charAt( i ); if (Character.isLetterOrDigit(ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9' || ) || Character.isWhitespace(ch)) { sb.append(ch); } else { sb.append("&#" + (int)ch + ";"); } } return sb.toString(); } } // ... @RequestMapping("/getnotifications.htm") public ModelAndView getNotifications(HttpServletRequest request, HttpServletResponse response) { ValidateOutput vo = new ValidateOutput(); publicModelAndView mv static= voidnew displayModelAndView(); throws ValidationExceptiontry { UserInfo userDetails = getUserInfo(); List<Map<String,Object>> list = new ArrayList<Map<String,Object>>(); // descriptionList<Notification> andnotificationList input= are String variables containing values obtained from a database NotificationService.getNotificationsForUserId(userDetails.getPersonId()); // description = "description" and input = "2 items available" for (Notification notification: notificationList) { ValidateOutput vo Map<String,Object> map = new ValidateOutput(); vo.validate(description, input); // pass to another system or display to the user } } |
Risk Assessment
Failure to encode or escape output before it is displayed or passed to another system can result in the execution of arbitrary code on the client's side.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
MSC44-J | high | probable | medium | P12 | L1 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Wiki Markup |
---|
\[[OWASP 08|AA. Java References#OWASP 08]\] [How to add validation logic to HttpServletRequest|http://www.owasp.org/index.php/How_to_add_validation_logic_to_HttpServletRequest]
\[[MITRE 09|AA. Java References#MITRE 09]\] [CWE ID 116|http://cwe.mitre.org/data/definitions/116.html] "Improper Encoding or Escaping of Output" |
HashMap<String,Object>();
map.put("id", vo.validate("id", notification.getId()));
map.put("message", vo.validate("message", notification.getMessage()));
list.add(map);
}
mv.addObject("Notifications", list);
}
catch(Throwable t) {
// Log to file and handle
}
return mv;
}
|
Output encoding and escaping is mandatory when accepting dangerous characters such as double quotes and angle braces. Even when input is whitelisted to disallow such characters, output escaping is recommended because it provides a second level of defense. Note that the exact escape sequence can vary depending on where the output is embedded. For example, untrusted output may occur in an HTML value attribute, CSS, URL, or script; output encoding routine will be different in each case. It is also impossible to securely use untrusted data in some contexts. Consult the OWASP XSS (Cross-Site Scripting) Prevention Cheat Sheet for more information on preventing XSS attacks.
Noncompliant Code Example
This noncompliant code example takes a user input query string and build a URL. Because the URL is not properly encoded, the URL returned may not be valid if it contains non-URL-safe characters, as per RFC 1738.
Code Block | ||
---|---|---|
| ||
String buildUrl(String q) {
String url = "https://example.com?query=" + q;
return url;
}
|
For example, if the user supplies the input string "<#catgifs>", the url
returned is "https://example.com?query=<#catgifs>"
which is not a valid URL.
Compliant Solution (Java 8)
Use java.util.Base64
to encode and decode data when transferring binary data over mediums that only allow printable characters like URLs, filenames, and MIME.
Code Block | ||
---|---|---|
| ||
String buildEncodedUrl(String q) {
String encodedUrl = "https://example.com?query=" + Base64.getUrlEncoder().encodeToString(q.getBytes());
return encodedUrl;
}
|
If the user supplies the input string "<#catgifs>", the url
returned is "
https://example.com?query=%3C%23catgifs%3E"
which is a valid URL.
Applicability
Failure to encode or escape output before it is displayed or passed across a trust boundary can result in the execution of arbitrary code.
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
The Checker Framework |
| Tainting Checker | Trust and security errors (see Chapter 8) | ||||||
Parasoft Jtest |
| CERT.IDS51.TDRESP CERT.IDS51.TDXSS | Protect against HTTP response splitting Protect against XSS vulnerabilities |
Related Vulnerabilities
The Apache GERONIMO-1474 vulnerability, reported in January 2006, allowed attackers to submit URLs containing JavaScript. The Web Access Log Viewer failed to sanitize the data it forwarded to the administrator console, thereby enabling a classic XSS attack.
Bibliography
[OWASP 2011] | Cross-site Scripting (XSS) |
[OWASP 2014] | How to Add Validation Logic to HttpServletRequest XSS (Cross-Site Scripting) Prevention Cheat Sheet |
...
FIO36-J. Do not create multiple buffered wrappers on an InputStream 09. Input Output (FIO) 09. Input Output (FIO)