2013-09-11
Understanding why CSRF protection really needs cookies
For reasons beyond the scope of this entry I've been thinking about adding some CSRF protection to the comment posting system here (which is the only thing that's exposed to CSRF attacks). My understanding is that the standard approach to CSRF protection is to set the same magic number as a cookie and as a hidden form parameter when you initially send the form to the user then reject form submissions when the two don't match. The problem with this, from my perspective, is that this needs you to accept cookies from Wandering Thoughts and I don't want to require that.
At first I thought I could get around this by using a hidden authenticator in the form, formed by a HMAC of various bits of information signed with a server secret. With appropriate protection I could prevent the attacker from getting the victim to make an initial form request and then reading out the hidden form field from it. This even half-works in that I could make it protect me (and a few other people), just not ordinary commentators. The problem is that in general the attacker doesn't actually need the victim's hidden authenticator. All they need is an authenticator that will work and I'll give them that authenticator if they ask me for one by requesting the form themselves. What I need is a way to tell apart the attacker's authenticator from the victim's authenticator and I don't have that in general.
(You might think that I could embed some version of the request's IP address into the authenticator. Unfortunately I've already discovered that that doesn't work these days; people's activity can legitimately hop between IP addresses too much. In theory I could try to fingerprint the specific browser from various identifying information it sends, but I don't feel like going there and it's a heuristic.)
This is what browser cookies do in the standard CSRF approach. CSRF cookies let us identify browser sessions so we can tell that the attacker's 'authenticator' doesn't come from the victim's browser session. And cookies attach to the browser session in a way that is deliberately invisible to the attacker. Once you have that session identification you can junk anything else in the authenticator because all you really need to do is tie the request to a particular browser session and reject cross-session requests.
(Realizing this has changed my thinking about CSRF cookie lifetimes. Initially I thought that they should be cleared after a successful form submission for somewhat fuzzy reasons; now I think that you're better off having them persist.)
Sidebar: when I think signed authenticators do work
When they work is if you actually have user logins, because then an attacker A can't manufacture a valid authenticator for user B. They can manufacture an authenticator for themselves (as before you'll give them one), but you'll detect that the authenticator's user is not correct when the attacker has the victim submit the form.
(This is why I could protect myself and a few other people who actually have logins here, but not most people who don't. One non-login authenticator can't be told from another non-login one.)
2013-09-07
Good SSL for your website is absurdly difficult in practice
It all started with a tweet by Thomas Ptacek which I replied to. That inspired me to take another run at configuring my personal site so that it had a top-grade SSL/TLS configuration.
I failed. Which leads to this rant. In order to have good TLS on your website, here is what you need (in the abstract):
- You need to know what the current state of the art is in recommended
TLS settings and attacks, both for things to actively support
(such as perfect forward secrecy)
and things to avoid (RC4, TLS compression, and so on). All by
itself this is a minefield of outdated or contradictory advice.
- Your system's TLS libraries must support everything you want to do
(and sometimes your application software too). You also need to
know how to find out whether they do. This is far from guaranteed;
on Unix systems, your OpenSSL library may be too old or compiled
without patent-encumbered technology like elliptic curve
cryptography.
If good TLS settings require things your normal libraries don't
have you may have to build your own.
(Did you know that Fedora compiles OpenSSL without ECC? I didn't until I started reading deeply in this. Oh, and you may have to rebuild not just OpenSSL but also applications that depend on it, per this bug comment.)
- You must successfully translate those abstract good TLS settings
into actual concrete settings for your TLS libraries and application.
This primarily means controlling cipher choices through cipher
names. You also need to deal with the
fact that different clients support different ciphers so your job
is not just to specify a few really good ciphers but to come up
with a cipher ordering that prioritizes the good stuff, avoids
the bad stuff, works as best as possible for as many clients as
possible, and probably doesn't leave any clients in the cold.
Oh, and the available documentation for your TLS library is probably not very good and may not be complete. You also get to go through a three way translation process between full cipher names as reported in, eg, protocol decodes of actual client traffic, how you name and configure various sorts of ciphers in your TLS library, and the names that were used for ciphers in the abstract good TLS settings you've read up on.
Unless you're a real expert there is a lot of black magic and superstition in this process. You're taking guesses and hoping that they work right, which brings us to the next issue.
- Having come up with what you think is a good configuration, you need
to test it to see if it does what you think it does and gives
clients good results. In the process you may have to make decisions
about client support; for example, is it okay if IE 6 on Windows
XP probably can't connect to you? Is the testing you're doing
really covering the smartphone and tablet world?
There are testing sites but their results aren't necessarily complete and may require interpretation.
In the current environment you can apparently look forward to doing all of this all over again in six months when a new vulnerability gets discovered in another part of the TLS world.
Of course if you don't care about having top grade TLS support on your website, life is much easier; you can just accept the TLS defaults on your software. I'm not surprised that lots of people do just this because doing significantly better is a lot of work.
(You can also try following recipes that you found on the Internet. This may or may not actually work for you. If it doesn't work it may be because of something obscure in your specific environment, as it may have been for me until I discovered you have to recompile not just OpenSSL but lighttpd too in the process of writing this entry.)
2013-09-04
What (and how) I use HTML tables for layout here
I'd like to say, to start with, that I'm not particularly opposed to using CSS for layout as an alternative to tables. It's just that I find HTML tables easier to write in practice and as far as I know, CSS lacks the features that would make it really work well for this. Today I want to talk about three specific uses I make of tables in Wandering Thoughts.
The first is my most common use of tables for layout in general: aligning form labels and form entry fields. What I almost invariably want in my forms (whether it is smart or foolish) is something that looks like:
a field label <input field> label 2 <another input field> name? <input field>
I want the labels to line up (either left or right aligned depending on my mood) and all of the input fields to line up too (always left), without me specifying any widths explicitly. I want the entire thing to take up as little or as much space as needed by the fields (and to wrap label fields if necessary and appropriate). Wandering Thoughts has an example of this in the current 'add a comment' form where I use a table as part of the form to align a couple of fields below the main comment text entry area.
(Setting up the current version of the 'add a comment' form is what prompted my original entry on giving up my table guilt.)
The most visible use of a table in Wandering Thoughts is the sidebar, which is placed there in a table. Most of the content on every page is wrapped inside a simple two-cell table, with the left cell set to 76% width and the right one to 24% (and some CSS used to style the border between them; that dotted border actually shows the exact span of the table on the page). The relative percentages are questionable, but I was in a grumpy mood back many years ago when I did them and I picked things that came out right on my screen.
(I think the right approach would be to set relative widths but also to set minimum widths in ems for both sides. And ideally there would be CSS magic that dropped the sidebar off to the bottom if there wasn't enough room, because the sidebar is less important than the main content. But I'm dreaming here.)
The other use of tables in Wandering Thoughts is visible at the bottom of individual entries (such as this one): the entire area of the previous entry and next entry links are formatted with tables. What I wanted for this is for the previous and next links split the space 50-50 (with a bit of margin between them and the divider line) and that the « and » markers be centered vertically within the overall box (if they're present). Right now this actually uses nested tables because at the time I was hitting things with brute force hammers and I find tables easier than CSS.
I suspect that if I knew more CSS I would naturally gravitate to doing
a number of these effects with CSS instead of tables. But the last time
I wrestled with float and so on the result just kind of barely worked
when the dust settled and I've been scared of touching it ever since.
(That CSS is still here today, handling the breadcrumbs at the top of every Wandering Thoughts page.)
Sidebar: the CSS layout-related feature I really want
The killer CSS feature would be the ability to define a grid (hopefully flexibly) and then arbitrarily relocate <div>s or other content blocks into it. One of the big drawbacks of tables is that they force an order on the HTML; the top left table cell must be first in the HTML, the bottom right one last. This may not correspond to the right content ordering for, say, accessibility (see that for more discussion).