XSS and CRLF Injection Prevention with HST-2
1. Overview
Cross-Site Scripting (XSS) and Carriage Return Line Feed (CRLF) injection are common web application vulnerabilities. XSS allows attackers to inject malicious scripts into web pages viewed by other users. CRLF injection exploits the way HTTP headers are constructed, enabling attackers to manipulate HTTP responses.
For background information on XSS, refer to the following resources:
The OWASP cheat sheet outlines practical rules for preventing XSS.
CRLF injection is less widely known. Some servlet containers, such as Tomcat, provide built-in protection. Because Bloomreach Content (HST) supports multiple containers, HST includes its own CRLF injection prevention. For more details, see Veracode: CRLF Injection:
"CRLF refers to the special character elements 'Carriage Return' and 'Line Feed'. These elements are embedded in HTTP headers and other software code to signify an End of Line (EOL) marker. ... Exploits occur when an attacker is able to inject a CRLF sequence into an HTTP stream. By introducing this unexpected CRLF injection, the attacker is able to maliciously exploit CRLF vulnerabilities in order to manipulate the web application's functions."
HST is designed and tested to mitigate XSS and CRLF injection risks. URLs generated by HST link or URL tags are encoded to prevent XSS. HST also provides a servlet filter to further secure your web application.
Despite these safeguards, you are responsible for following secure coding practices. Always encode untrusted data and follow the recommendations in the OWASP cheat sheet.
When generating HTML from untrusted sources (such as user input), always encode the data. Use the following techniques:
- With JSTL core tags,
${expression}outputs raw values, while<c:out value="${expression}" />encodes the value. Use<c:out>to prevent XSS. - With JSTL fn tags, use the
escapeXmlfunction to encode values. For example:${fn:escapeXml(fn:join(document:tags, ', '))}. - In client-side scripts, use
encodeURIComponent(value)when inserting user data into the DOM. - In Freemarker templates, use
${expression?html}to encode output.
2. XSSUrlFilter for XSS and CRLF Injection Prevention
The default archetype includes the XSSUrlFilter servlet filter to enforce XSS and CRLF injection prevention.
Configure this filter as the first filter in your web application's filter chain to inspect all incoming URLs:
<filter> <filter-name>XSSUrlFilter</filter-name> <filter-class>org.hippoecm.hst.container.XSSUrlFilter</filter-class> </filter> <!-- SNIP --> <filter-mapping> <filter-name>XSSUrlFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
The filter inspects the request URI and query string for the following characters and encoded values: <, >, %3C, %3c, %3E, and %3e. If any are found, the filter returns an HTTP 400 Bad Request error and terminates processing.
For example, a request such as:
http://www.example.com/news/search?p=><script>alert('attack')</script>
will result in an HTTP 400 error.
This filter is useful if you are not certain that all web pages handle encoding correctly. The filter also wraps the HTTP servlet response to inspect headers for CRLF characters. If a header contains CRLF, the filter returns a server error to prevent CRLF injection.
3. Encoding Untrusted Data
When your application stores user-provided data in the repository, you must sanitize input to prevent XSS.
For example, in a news article comment feature, a user could submit a comment containing malicious scripts. If you display this comment without sanitization, all visitors to the article page are exposed to XSS.
To mitigate this, strip script tags or remove all markup from user input before storing it. You can use libraries such as htmlcleaner to remove unwanted tags while allowing limited markup.
If you only need plain text, use the HST utility method org.hippoecm.hst.utils.SimpleHtmlExtractor#getText(String html). This method extracts only the text content from an HTML string.
Example usage from the HST demosuite application (org.hippoecm.hst.demo.components.Detail.java):
import org.hippoecm.hst.utils.SimpleHtmlExtractor; //... String title = request.getParameter("title"); String comment = request.getParameter("comment"); // ... commentBean.setTitle(SimpleHtmlExtractor.getText(title)); commentBean.setHtml(SimpleHtmlExtractor.getText(comment)); // ... // update now wpm.update(commentBean);
4. Summary
HST is designed to minimize XSS and CRLF injection risks and follows the practices recommended by OWASP. However, you must ensure that your application encodes untrusted data before rendering or storing it.
Use the XSSUrlFilter to block malicious URLs and prevent CRLF injection in HTTP headers. Always sanitize user input before storing it in the repository or backend systems, using either a markup-cleaning library or the HST utility method for extracting plain text. Proper encoding and input validation are essential for maintaining application security.