Forum OpenACS Q&A: Ben's scary authentication bug.

Posted by Adam Farkas on
Ben brought up a pretty scary authentication issue during his OSDEM talk. I don't know how wide-spread this issue is with all web services, but it can cause some interesting headaches for those who are unaware of it.

Go to

for a description of the problem, and an actual example of the problem in action. (the "test post.. please ignore" thread should pique your interest..)

cheers, adam

[going back to pen and paper for his financial service needs...]

Posted by Ben Adida on
For the record, calling it "ben's bug" gives me significantly too
much credit. This issue was originally reported a few months
back by the Zope folks, I believe.
Posted by Mike Slack on
The financial sites I've used (maybe 2-3) have what I used to think was an annoyingly fast expiration of authentication cookies (only a minute or two).  Now I can see that I'm glad they do that.  Even so, this doesn't completely eliminate the problem by itself.  They do all also have a "sign out" (similar to the ACS "Logout" link) button, which I assume wipes out the cookie completely.
Posted by Adam Farkas on
Well, i will give you credit for pointing out the seriousness of this problem. Most people at the conference didn't get it until you walked them through it slowly.

The next question is -- what to do about it.  ACS is hardly the only system that suffers from this problem...

Posted by Patrick Giagnocavo on
OK, but checking the referer field (which page refered us to the
current page?) would help, wouldn't it?
Posted by Don Baccus on
For starters, turn off Javascript ...

Another tactic to take, as a user, is to always log out after completing a financial transaction, and when you're doing something like buying an airline ticket, log in and take an unwavering path through the site until you're done, then log out.  No diversions to or whatever.

On the server side, totally off the top of my head ... the site could always check the referrer.  If your user has left your site, i.e. you see a referrer from elsewhere, flag the fact in a cookie.  Later, when the user tries to complete the transaction, ask for reauthentication.  Explain why and tell the user to avoid competitor sites that don't ask for reauthentication in such cases...

If you only checked when the user was trying to post data, as in Adam's forum example, you could still provide hyperlinks to forums etc  from a personal page.  You'd only be prevented from posting from an offsite page.

I'm sure the Zope folk thought of something like this very quickly, too.  Probably means it is full of holes and a worthless idea.

Posted by Adam Farkas on
What worries me about it is that most web services that exist today are built for the "lowest common denominator".

That is, convenience is king. Security isn't that important. Don't make the user lift a finger unless absolutely necessary.

Look at the race for "1-click" capabilities at e-commerce sites as an example -- I'd be really surprised if the majority of these systems had properly implemented security.

My sense is that many of these systems would be vulnerable to this type of bug. [in fact, how is amazon 1-click done, anyway?]

What scares me is not so much that these bugs exist, but that i don't know which systems they impact....

Posted by Don Baccus on
What you should *really* worry about are the security holes that you don't know exist, because you can't effectively fend them off.

The web site for the large investment house that holds my 401K requires Java to use the site.  That annoys me.  While client-side Java is thought to be secure, the use is gratuitous.  And of course it  limits the users who can make use of their site - why the heck do they want to limit their potential customer base?  It also makes it ultra annoying to use over a dial-up modem.  Someone's not thinking.  They wouldn't broadcast an ad with all the voices pitched about 15,000 Hz thereby ensuring a large percentage of the population would hear nothing but silence.

As I recall checking the referer was an adequate solution, but (?)
caused problems with older browsers. An off-the-top-of-my-head
fix this problem would be to add a list of callers to
ad_page_contract and then if the referer didn't match put up a
"do you really want to do this?" screen. (then of course people
spoof the "really want to do this screen") Another option is to add
a secret hash into submissions -- this goes along with the
doubleclick stuff people were talking about.

But all of this is more along the lines of ACS4 fixes -- there's no
easy way to close the hole for past versions.

Posted by Dirk Gomez on
Amazon requires you to type in your password before you order - even
with one-click shopping (IIRC).
Posted by Ian Baker on
Sending a secret hash with the link or form, to be returned with the request seems like the best solution. Generation and checking of the hash could be made really simple with a few procs.

What to make the hash from, then. Concatenating the session_id and a secret that's stored on the server (perhaps randomly generated every few hours), and SHA1ing it seems like it'd be a good bet. You wouldn't need to hit the database for it or anything. Code would look something like this:

proc make_hash  { } {
    return [sha1 "[ad_conn session_id][ad_conn server_secret]" ]

proc check_hash { input_hash } {
    if { [ string equal $input_hash [sha1 "[ad_conn session_id][ad_conn server_secret]"] } {
        return 1
    } else {
        return 0
The value returned by [ad_conn server_secret] would be some random number, generated every few hours (however long a session lasts would be a good number, probably), stored in the database, and memoized. It might be worthwhile to keep the previous server_secret around and check against that one too, but only issue the new one (overlapping the two). Otherwise, when the secret changed, all the links that were just issued would become invalid.

The output of [make_hash] would be included in whatever forms were to be secured, and the scripts accepting those forms would check for it.

In a real implementation, make_hash could be wrapped into ad_conn, and get_hash could be a page_contract filter.

Adding the session_id makes the hash unique for each user, so that the malicious site maintainer can't just go fetch the new hash every hour. The server secret makes it impossible for the malicious user to write javascript to generate a correct hash for the session_id cookie.

Possible vulnerabilities:

  • Since part of the hashed value (the session id) is known, heavy-duty cryptanalysis could possibly be used to determine the second part (the secret). This risk is mitigated by using a fairly long random number for the secret, and refreshing it often.
  • The evil hax0r could write some JavaScript that would go fetch a document from the secure ACS site, extract the current hash for that user, and generate a new request with it. I don't think this is possible with JS (fetching and parsing documents), but if it is, then this whole idea is bunk...

(disclaimer: I don't develop with OpenACS, so I don't know if I'm using the right procedure names here and stuff.)