Missing HSTS header in checkmarx report - java

I am using Checkmarx to analyse my project, and the only remaining medium severity item is Missing_HSTS_Filter, with the Destination name being HSTSFilter. In my web.xml, I have :
<filter>
<filter-name>HSTSFilter</filter-name> <!-- checkmarx says problem is here -->
<filter-class>c.h.i.c.web.security.HSTSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HSTSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The HSTSFilter class :
public class HSTSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse resp = (HttpServletResponse) res;
if (req.isSecure())
resp.setHeader("Strict-Transport-Security", "max-age=31622400; includeSubDomains");
chain.doFilter(req, resp);
}
}
So I tried something else and because I am using Tomcat 7, I tried adding the following instead in web.xml :
<filter> <!-- checkmarx now complains here -->
<filter-name>httpHeaderSecurity</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>hstsMaxAgeSeconds</param-name>
<param-value>31622400</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>httpHeaderSecurity</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
Checkmarx still complains, saying the Destination name this time was StatementCollection. I don't understand what that means.
What am I missing ?

Strange thing. You really use the right configuration. On this Checkmarx rule, I find a lot of False Positive in some scan. Anyway,try to add this lines to your web.xml in the filter configuration :
<init-param>
<param-name>hstsIncludeSubDomains</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>hstsEnabled</param-name>
<param-value>true</param-value>
</init-param>

I got this error in check Marx violations in the JSP where a scriptlet tag is used to execute java source code in JSP. Syntax is as follows: <% java source code %>
So I fixed it just by providing
<% response.setHeader("Strict-Transport-Security" ,"max-age=7776000" ); %>
Also made changes in java code , a class file and web.xml changes :
web.xml :
<filter>
<filter-name>HSTSFilter</filter-name>
<filter-class>com.abc.gbm.test.config.HSTSFilter</filter-class>
<init-param>
<param-name>maxAgeSeconds</param-name>
<param-value>31536000</param-value>
</init-param>
<init-param>
<param-name>includeSubDomains</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HSTSFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
Java class filter :
package com.abc.gbm.test.config;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HSTSFilter implements Filter {
private static final String HEADER_NAME = "Strict-Transport-Security";
private static final String MAX_AGE_DIRECTIVE = "max-age=%s";
private static final String INCLUDE_SUB_DOMAINS_DIRECTIVE = "includeSubDomains";
private static final Logger logger = LoggerFactory.getLogger(HSTSFilter.class);
private int maxAgeSeconds = 0;
private boolean includeSubDomains = false;
private String directives;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
logger.info("request.isSecure() :: {}" , request.isSecure());
if (request.isSecure() && response instanceof HttpServletResponse) {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader(HEADER_NAME, this.directives);
}
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
maxAgeSeconds = Integer.parseInt(filterConfig.getInitParameter("maxAgeSeconds"));
includeSubDomains = "true".equals(filterConfig.getInitParameter("includeSubDomains"));
if (this.maxAgeSeconds <= 0) {
throw new ServletException("Invalid maxAgeSeconds value :: " + maxAgeSeconds);
}
this.directives = String.format(MAX_AGE_DIRECTIVE, this.maxAgeSeconds);
if (this.includeSubDomains) {
this.directives += (" ; " + INCLUDE_SUB_DOMAINS_DIRECTIVE);
}
System.out.println("directives :: "+directives);
}
#Override
public void destroy() {
}
}

Related

Modifying HTML and JSP

How can I add a HTML comment on every HTML and JSP page?
I've tried to modify it with a filter and it could only modify the JSP pages and not the HTML pages.
I used a filter like this:
package com.app.server.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
public class WaterMarkFilter implements Filter {
private List<String> extensionsToFilter = new ArrayList<>();
#Override
public void init(FilterConfig filterConfig) throws ServletException {
String[] extensions = filterConfig.getInitParameter("extensionsToFilter").split(",");
for (String extension : extensions) {
extensionsToFilter.add(extension.trim());
}
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
postFilter(request, response);
}
#Override
public void destroy() {
}
private void postFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
String path = ((HttpServletRequest) request).getRequestURI();
if (canIntercept(path)) {
response.getWriter().write("modified");
response.getWriter().close();
}
}
private boolean canIntercept(String path) {
if (path.equals("/")) {
return true;
}
for (String extension : extensionsToFilter) {
if (path.endsWith("." + extension)) {
return true;
}
}
return false;
}
}
This is the Web.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>com.app.configuration ShoppingCartService</servlet-name>
<servlet-class>com.app.server.servlet.ShoppingCartServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>com.app.configuration ShoppingCartService</servlet-name>
<url-pattern>/application/ShoppingCartServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>com.app.server.servlet.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/application/test</url-pattern>
</servlet-mapping>
<listener>
<listener-class>com.app.server.ApplicationInitializer</listener-class>
</listener>
<filter>
<filter-name>WaterMarkFilter</filter-name>
<filter-class>com.app.server.filter.WaterMarkFilter</filter-class>
<init-param>
<param-name>extensionsToFilter</param-name>
<param-value>jsp, html</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>WaterMarkFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
The actual question is how to manipulate the ServletResponse using Filter.
My detailed answer with full code example and many links is here
Short:
In the doFilter implementation:
before the chain.doFilter call, prepare a HttpServletResponseWrapper and a PrintWriter
after the call, write in the PrintWriter a copy of the wrapped response + "the text you want"
Bellow are the code changes in order the filter to work with HTML too:
public class WaterMarkFilter implements Filter {
private ServletRequest request;
private PrintWriter out;
private CharResponseWrapper wrapper;
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
this.request = request;
out = response.getWriter();
wrapper = new CharResponseWrapper((HttpServletResponse) response);
chain.doFilter(request, wrapper);
postFilter();
out.close();
}
private void postFilter() throws IOException, ServletException {
String path = ((HttpServletRequest) request).getRequestURI();
if (canIntercept(path)) {
out.write(wrapper.toString() + "modified");
}
else {
out.write(wrapper.toString());
}
}
}
The CharResponseWrapper is the same as in my detailed answer here.
There is also a better example how to include text into already created html.
Just adding text at the end is good only for plain text files.
For HTML - It is better to insert the text inside the HTML. The example there is with <head> tag, but it could be adapted to insert to <body> tag.

GWT-No 'Access-Control-Allow-Origin' header is present on the requested resource

We are trying to Implement CORS filter on tomcat to allow cross domain request. We have two GWT projects both on two different tomcat (different machines). After reading the CORS filter DocumentCORS , I just added the CORS filter in the web.xml file of the tomcat.
`<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
</init-param>
<init-param>
<param-name>cors.exposed.headers</param-name>
<param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
</init-param>
<init-param>
<param-name>cors.support.credentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.preflight.maxage</param-name>
<param-value>10</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>`
But its not working. I got another stack question related to it but a little bit confusion how to implement filters in GWT ?
StackQues
WHAT IS THE ACTUAL PROCEDURE TO IMPLEMENT CORS FILTER WITH GWT?
Extend Filter and add the class on your server side like in this:
NOTE: this is just a simple example to get you going. inform yourself about the security risks if you dont configure it the right way...
check the last part of this article
public class CORSFilter implements Filter {
// For security reasons set this regex to an appropriate value
// example: ".*example\\.com"
private static final String ALLOWED_DOMAINS_REGEXP = ".*";
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
String origin = req.getHeader("Origin");
if (origin != null && origin.matches(ALLOWED_DOMAINS_REGEXP)) {
resp.addHeader("Access-Control-Allow-Origin", origin);
if ("options".equalsIgnoreCase(req.getMethod())) {
resp.setHeader("Allow", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS");
if (origin != null) {
String headers = req.getHeader("Access-Control-Request-Headers");
String method = req.getHeader("Access-Control-Request-Method");
resp.addHeader("Access-Control-Allow-Methods", method);
resp.addHeader("Access-Control-Allow-Headers", headers);
// optional, only needed if you want to allow cookies.
resp.addHeader("Access-Control-Allow-Credentials", "true");
resp.setContentType("text/x-gwt-rpc");
}
resp.getWriter().flush();
return;
}
}
// Fix ios6 caching post requests
if ("post".equalsIgnoreCase(req.getMethod())) {
resp.addHeader("Cache-Control", "no-cache");
}
if (filterChain != null) {
filterChain.doFilter(req, resp);
}
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig arg0) throws ServletException {
}
}
Dont forget to add the Filter in your web.xml(inside your WAR file, not the tomcat web.xml) file.
<filter>
<filter-name>corsFilter</filter-name>
<filter-class><YourProjectPath>.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>corsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

How to set Filter to be applied for content-type "html/text" ONLY?

I wrote following code.
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
public class CacheFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse resp = (HttpServletResponse) response;
resp.setHeader("Cache-Control", "no-store, no-cache,must-revalidate,max-age=0");
resp.setHeader("Pragma", "no-cache");
chain.doFilter(request, response);
}
public void destroy() {
//delegate.destroy();
}
public void init(FilterConfig filterConfig) {
//delegate.destroy();
}
}
and here's the maping code in web.xml file
<filter>
<filter-name>CacheFilter</filter-name>
<filter-class>com.util.CacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CacheFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
This thing works but this filter gets applied for all the content, thus slowing my site's performance. I want this filter to be applied for content type "text/html" only. This can be easily achieved through ExpiresFilter like this
<init-param>
<param-name>ExpiresByType text/html</param-name>
<param-value>access plus 0 seconds</param-value>
</init-param>
but how to achieve it in this code?
I'd appreciate your earliest help.
I think you need to write Response Wrapper to modify the response from servlet-
See this links- http://www.java2s.com/Tutorial/Java/0400__Servlet/Filterthatusesaresponsewrappertoconvertalloutputtouppercase.htm
http://sqltech.cl/doc/oas10gR31/web.1013/b28959/filters.htm
http://software.it168.com/manual/servlet/0596005725_jsvltjspckbk-chp-19-sect-7.html
-Thanks

Servlet filter chain order is changing on continous refresh

In my application we have implemented several filters. For example I have three filters
Locale Filter
License Filter
Login Filter
The order is working fine in normal case. But when I am giving continuous refresh it sometimes skips the License Filter (execution then is: Locale Filter -> Login Filter).
Is there any way to avoid this? The order should not change even when I continuously refresh. The order should be followed every time.
public class LicenseFilter implements Filter {
#Override
public void destroy() {
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
try {
LOGGER.info("In LicenseFilter");
licenseValidator.validate();
chain.doFilter(req, res);
}catch (Exception excep) {
LOGGER.error("License Error " + excep.getMessage());
req.setAttribute("error", excep.getMessage());
RequestDispatcher dispatcher = req
.getRequestDispatcher("license_list.action");
dispatcher.forward(req, res);
}
}
}
#Override
public void init(FilterConfig cfg) throws ServletException {
WebApplicationContext wctx = WebApplicationContextUtils.getWebApplicationContext(cfg
.getServletContext());
licenseValidator = (licenseValidator) wctx.getBean("licenseValidator");
ctx = cfg.getServletContext().getContextPath();
}
}
web.xml
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>web</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>META-INF/beans-*.xml</param-value>
</context-param>
<filter>
<filter-name>localeFilter </filter-name>
<filter-class>com.filter.LocaleFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>localeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>licenseFilter</filter-name>
<filter-class>com.filter.licenseFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>licenseFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>com.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>

Java servlet filter not working on login

I've written a filter class to add a P3P header to every page. I added this to my web.xml:
<filter>
<filter-name>AddP3pHeaderFilter</filter-name>
<filter-class>com.mycompany.AddP3pHeaderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AddP3pHeaderFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
It adds the header to every page request, but it doesn't work when the user first logs in. The user submits the form to j_security_check, but the response doesn't include the header. How can I make my filter apply to the login request?
Doesn't work in Tomcat.
I ended up having to use Tomcat valves.
The login request forwards to the appropriate page. By default, filters only apply to REQUEST dispatches. You need to modify the web.xml as follows:
<filter>
<filter-name>AddP3pHeaderFilter</filter-name>
<filter-class>com.mycompany.AddP3pHeaderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AddP3pHeaderFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
EDIT: I thought this had fixed it, but I was mistaken.
Most servletcontainers indeed does not allow hooks on /j_security_check requests due to security reasons. Some older versions will do, but that should be fixed in newer versions.
The best way to hook on this anyway would be to check the presence of the user principal in the HttpSession which you've manually put there if absent.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
UserPrincipal user = httpRequest.getUserPrincipal();
HttpSession session = httpRequest.getSession();
if (user != null && session.getAttribute("user") == null) {
session.setAttribute("user", user);
// First-time login. You can do your intercepting thing here.
}
chain.doFilter(request, response);
}
Don't know about tomcat, but it works for me in jetty, just put your filter before spring filter :
<filter>
<filter-name>AddP3pHeaderFilter</filter-name>
<filter-class>com.mycompany.AddP3pHeaderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AddP3pHeaderFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
My web.xml
<filter>
<description>
FBIS Filter</description>
<display-name>Fbisfilter</display-name>
<filter-name>Fbisfilter</filter-name>
<filter-class>fbis.filter.Fbisfilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Fbisfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
and myfilter is
package fbis.filter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.sqlconnection.SQLConnect;
import com.sun.security.auth.UserPrincipal;
import fbis.interfaces.abstractclasses.Connections;
/**
* Servlet Filter implementation class Fbisfilter
*/
public class Fbisfilter extends Object implements Filter,Connections {
public void destroy() {
// System.out.println("Filter Service finished");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpresponse = (HttpServletResponse) response;
System.out.println("FILTER INSIDE");
// place your code here
HttpSession session = httpRequest.getSession(true);
String usrid = httpRequest.getParameter("txtuname");
String pwd = httpRequest.getParameter("txtpassword");
PreparedStatement pstmt;
try {
pstmt = con
.prepareStatement("SELECT l.Userid,n.First_name from Login_details_dtls l join New_Registration_dtls n on l.Userid=n.Userid where n.Userid=? AND l.pwd=?");
pstmt.setString(1, usrid);
pstmt.setString(2, pwd);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
session.setAttribute("usr", rs.getString("Userid"));
session.setAttribute("usrname", rs.getString("First_name"));
}
} catch (SQLException e) {
e.printStackTrace();
}
chain.doFilter(httpRequest, httpresponse);
}
/**
* #see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
System.out.println("Filter Service has started");
}
}

Categories