I know this is a toy example, but really, people should not be storing passwords in plaintext in a database. jBCrypt has a simple API, and can be used from Clojure.
Also, the password authentication finishes early if it detects a mismatch between the given password and the one in the database. This makes it fairly easy for an attacker to get people's passwords with a straightforward timing attack. To fix it, always go through all the characters in the strings to compare them.
"Also, the password authentication finishes early if it detects a mismatch between the given password and the one in the database. This makes it fairly easy for an attacker to get people's passwords with a straightforward timing attack. To fix it, always go through all the characters in the strings to compare them."
The password check is a database query that, since there are no indices on the users table, will check for string equality in every row of the table. Timing the response tells you a lot about the number of users, and the instantaneous server load, not so much about how closely the latest guess matches someone's password.
Even with a more optimized program, I'd be surprised if "fairly easy" were an accurate characterization of the effort to separate timing of comparing one extra character of a password from all the other stuff going on during a request: database access, routing, parsing query parameters, load from other requests, garbage collection pauses, network latency... The signal-to-noise ratio is just too low.
> Even with a more optimized program, I'd be surprised if "fairly easy" were an accurate characterization of the effort to separate timing of comparing one extra character of a password from all the other stuff going on during a request: database access, routing, parsing query parameters, load from other requests, garbage collection pauses, network latency... The signal-to-noise ratio is just too low.
Timing attacks are possible over networks, even when the timing differences are minuscule. [1]
That's an interesting article. While I feel less certain of my original position, I am still skeptical about a timing attack based on the time required to compare two password strings for equality.
Note that while the article deals with similar sources of noise, it also deals with a larger signal. They are trying to time a decryption process, which has a high computational complexity by design. We are talking about timing the difference between checking for equality of the first few characters of a string, versus checking for equality between all characters of strings that are unlikely to be more than 20 characters long.
Chrome tells me that it took 109 milliseconds to load a 50-line stylesheet on my personal website.
So the operation we are trying to time shows a lot of variability even if you can isolate it by running that code directly in a terminal, and a typical small HTTP response takes up about a million times more runtime.
Yes, these are very crude estimates. Good profiling is much harder than this. Still, if I knew this was the only security hole in my application, I'd be feeling very safe.
The way enliven works is really neat and interesting.
One thing that jumped out at me though. The author talked about how he changed the login/logout text from being plan HTML in his template, to being what looks like a tokenized representation, a pre parsed format, f or performance reasons.
If this is something people are tempted to do whenever they use large sequences of static text in enliven templates, then it seems like there's maybe room for an improvement in enliven here. Since it's lisp, couldn't enliven somehow detect that this is the first time a template is used, and scan through the code looking for opportunities to make these kinds of speed optimizations automatically before first use?
It seems like a great way to keep design from getting too tightly coupled with a changing app. It would be great if there was some way to "precompile" the selectors and use this as a performant replacement for messy templates.
Enlive already performs some caching on static parts of the template (and will do more as soon as I get enough time in a row to work on it). Lau's way of handling login/logout is rather unusual and goes against the grain of Enlive: he puts html in program code! A way to do that in enlive is to put both login form and logout text in the html template and then to make Enlive remove the one which doesn't apply.
It walks you through taking a Clojure web app that uses the Ring middleware -- similar to WSGI in Python, or Rack in Ruby -- and deploying it as a WAR file that runs under Tomcat, behind Apache. Since the OP uses Ring, this should work.
It's also possible to run the app from a REPL on your server, with a Swank connection to emacs for remote hot-patching and debugging, with something like nginx in front of the built-in Jetty HTTP server, but that's not really something I'd feel good about.
I've been relearning <s>programming</s> Java and trying out the Play! framework, and a slashdot/HN clone is to be my first project of substance. I want a few more features, sure, but man... way to make me feel slow.
/Honestly, learning the ins and outs of a web framework of Rails caliber is very time-consuming.
The difficulty of programming depends a lot on your tools. I haven't used Play!, but I've had more experience with Java, Java frameworks, and Java libraries than is healthy. They tend to make programming a lot harder than it should be.
Every year this phenomenon that you identified gets worse, and the rate of that change is getting worse, too. Don't be too hard on yourself, though. Just finish something, and keep going. Because it'd be even slower if you tried to keep 100% "current" on all the new ideas, because then you'd never finish anything at all. And how slow would that be? Don't sweat it. Work hard, do your best.
But in general the days of big mega frameworks seem to be numbered, and nimble micro-frameworks is the way of the future. Or at very least it's a very powerful fad right now. Play! is a great thing to be working with.
http://www.mindrot.org/projects/jBCrypt/
Also, the password authentication finishes early if it detects a mismatch between the given password and the one in the database. This makes it fairly easy for an attacker to get people's passwords with a straightforward timing attack. To fix it, always go through all the characters in the strings to compare them.
Fantastic article otherwise, though.