-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 All,
On 4/18/2011 9:51 PM, Christopher Schultz wrote: > I'm leaning more towards just protecting against control characters in a > header: there's no need to do a complete URL-parse to check for response > splitting. > > A simple filter that wraps the response and overrides either > sendRedirect or setHeader(String, String) should do it. > > I'd have to check to see how the two interact... whether calling > sendRedirect on a wrapped response will also set the header on the > wrapped response or set the header at a higher level where the wrapper > won't get called. Looks like I must override sendRedirect because otherwise the setHeader call implemented in Response.sendRedirect isn't intercepted by the wrapper class. For those interested, see below for the implementation I came up with. Enjoy, - -chris import java.io.IOException; import java.net.MalformedURLException; import javax.servlet.Filter; import javax.servlet.FilterConfig; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; /** * Prevents the application from setting HTTP headers that include * CR or LF characters. Specifically throws a MalformedURLException * for the sendRedirect method which is already declared to throw * IOException. */ public class HttpResponseSplittingPreventionFilter implements Filter { public void init(FilterConfig config) { } /** * Performs the filtering operation provided by this filter. * * @param request The request being made to the server. * @param response The response object prepared for the client. * @param chain The chain of filters providing request services. */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if(response instanceof HttpServletResponse) response = new Wrapper((HttpServletResponse)response); chain.doFilter(request, response); } /** * Called by the servlet container to indicate that a filter is being * taken out of service.<p> */ public void destroy() { } class Wrapper extends HttpServletResponseWrapper { Wrapper(HttpServletResponse response) { super(response); } public void sendRedirect(String location) throws IOException { if(containsCRorLF(location)) throw new MalformedURLException("CR or LF detected in redirect URL: possible http response splitting attack"); super.sendRedirect(location); } public void setHeader(String name, String value) { if(containsCRorLF(value)) throw new IllegalArgumentException("Header value must not contain CR or LF characters"); super.setHeader(name, value); } public void addHeader(String name, String value) { if(containsCRorLF(value)) throw new IllegalArgumentException("Header value must not contain CR or LF characters"); super.addHeader(name, value); } private boolean containsCRorLF(String s) { if(null == s) return false; int length = s.length(); for(int i=0; i<length; ++i) { char c = s.charAt(i); if('\n' == c || '\r' == c) return true; } return false; } } } -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk2s66gACgkQ9CaO5/Lv0PDcSgCfbJnJkhqAYeZ/i7TgdGqX9adr BZ4An1G8gf8EAdV6ywyo0b7c6PWqg+AD =9kiL -----END PGP SIGNATURE----- --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org