

Reddit/HN clone in Clojure - pepijndevos
http://bestinclass.dk/index.clj/2011/01/building-a-social-media-site.html

======
pjscott
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.

<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.

~~~
ericlavigne
_"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.

~~~
LiveTheDream
> 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]

[1]
[http://www.usenix.org/events/sec03/tech/brumley/brumley_html...](http://www.usenix.org/events/sec03/tech/brumley/brumley_html/)

~~~
ericlavigne
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.

<http://ericlavigne.net/>

A quick and dirty experiment showed that the following comparison of short
strings takes between 3.5 and 5.9 milliseconds for 10,000 runs.

(def partial-password "abra")

(def guess1 "abrab")

(time (dotimes [i 10000] (= partial-password guess1)))

Whereas a similar comparison of longer strings takes between 5.8 milliseconds
and 6.0 milliseconds.

(def password "abrakadabra")

(def guess2 "abrakadabl")

(time (dotimes [i 10000] (= partial-password guess1)))

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.

------
unoti
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?

Still, really impressed with the whole setup.

~~~
cgrand-net
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.

~~~
unoti
Aha! Thanks for letting me know! Fwiw, Enlive looks brilliant, seriously.

------
scottjad
I did a rough translation of the templating part to slice
(<http://github.com/scottjad/slice>)

<http://pastie.org/1444730>

Normally of course I'd split it out in to many smaller functions/slices.

~~~
nickik
I think the whole slice thing is great too. I didn't have time to look at
slice or enlive but I will evaluate both of them for my next project.

------
michaelty
Someone should deploy this.

~~~
macmac
And write a post about how the did the deployment (incl. server setup)

~~~
pjscott
Here's an article I think you'll like:

[http://jeroenvloothuis.blogspot.com/2010/07/deploying-
clojur...](http://jeroenvloothuis.blogspot.com/2010/07/deploying-clojure-web-
application.html)

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.

~~~
weavejester
The lein-ring plugin provides a slightly easier way of generating war files
from Ring handlers:

<https://github.com/weavejester/lein-ring>

~~~
pjscott
Nice! That looks like the Right Thing.

------
lhnn
Damnit, stop making it look easy.

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.

~~~
ericlavigne
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.

