1 (edited by trond 2004-08-05 20:05)

Topic: Why include a HTTP_REFERER check?

I know there are threads about the HTTP_REFERER check in the troubleshooting-forum, but since this is not a problem (per se), and none answer my question -  which is...

why the HTTP_REFERER check?

It's not secure, only annoying. I know it's easily removed, but it's annoying to have to do so, seeing that there is no security reasons for having it there in the first place. I'm not trying to say that you should remove it because I feel that it's annoying. I just don't understand why it's included.

If I wanted to hack a punBB forum, I would most likely be smart enough to know how to spoof the HTTP_REFERER... It really doesn't add a fraction of application-level security.

Re: Why include a HTTP_REFERER check?

I'll explain why. Lets say I'm a malicious user and I want to hack your forums. I would then create a page with a hidden form that autosubmits when you visit it (easily done with JavaScript). I could e.g. mimic the "change status" form in the user profile so that when an administrator from your forums visits the page, the form will submit back to your forums and make me an admin, all completely transparent. However, since all admin and moderator actions are verified agains HTTP_REFERER, the forum wouldn't allow such an action. The referrer check is there to prevent that admins and moderators are tricked into taking action that can cause security problems.

"Programming is like sex: one mistake and you have to support it for the rest of your life."

3

Re: Why include a HTTP_REFERER check?

Yeah, but the page that submitted the form could (via for instance a php-script) easily spoof the http_referer so that the punBB script THOUGHT that it came from "itself".

4 (edited by trond 2004-08-06 14:57)

Re: Why include a HTTP_REFERER check?

Ok, not sure I made too much sense in the above "one-liner".

If the page with the javascript submits the data to http://evil.example.com/evil-script.php, then evil-script.php might include code for sending the data to the punBB-board + spoofing the HTTP_REFERER. After all, the HTTP_REFERER is just a string / HTTP header. If I know the board URL, I know what to include in my spoof-scripts. A HTTP_REFERER check only gives a false feeling of security.

"The most common use of this header is to track how users are finding your site. (...) this information should only be used to satisfy your curiosity (...) it should never be relied upon for any sort of security." - Chris Shiflett, HTTP Developer's Handbook


Wouldn't it be better to include some kind of shared secret between the form and the admin-scripts. One could for instance include a hidden-field in the form - with its value set to some kind of "dynamic"/"secret" content, and then validate the post-data in the admin-scripts afterwards.

Example:
First, generate the value:

<?php $secret = md5(date("Ymdh") . "some kind of secret string"); ?>

(It would probably have to be better than the use of date() above, but it serves as an example of content that you would be able to check later on)
Then, insert it into the form

<input type="hidden" name="secret" value="<?= $secret ?>" />

And finally, in the admin-scripts, you check that a $newly_calculated_value_of_secret == $_POST['secret'].

Make sense?

It's of course not bulletproof, but this way you at least require more effort from the user (to figure out what the $secret is / is calculated from), plus: an evil form wouldn't be valid/useful for long...

Re: Why include a HTTP_REFERER check?

The procedure you described with evil-script.php is not possible because evil-script.php doesn't have the nessecary cookie information from the admin user and does therefore not have permission to perform any admin/mod actions. You can construct a script that receives the post information and then resubmits that information with a spoofed referrer, but the forum wouldn't accept it due to the script not being identified as an admin/mod user.

The only way to exploit the HTTP_REFERER check is to somehow get the users browser to provide the board with a fake referrer and that is, as far as I know, not possible. The only way would be to first install some kind of virus on the victims computer. You can easily spoof your own referrer address, but not the visiting users'.

If you still believe it's possible, create a proof-of-concept script and e-mail it to me :)

"Programming is like sex: one mistake and you have to support it for the rest of your life."

6 (edited by trond 2004-08-07 07:00)

Re: Why include a HTTP_REFERER check?

Yeah, you're 100% right - one would need the cookie-values in order to fake the request. Although not too likely, an evil script could get access to cookies, for instance via browsers' security holes: like when microsoft releases a new vulnerable browser, for instance internet explorer 6.0 (before SP1), + there are still users out there using older browsers. I would guess that that scenario is just as likely as someone making you visit an evil script while you're logged in as admin at your own board.

My point is that I for one wouldn't count on the HTTP_REFERER to add any extra security. To me, vBulletin's separate session cookie for the admin-panel seems preferable over a HTTP_REFERER check: if you're an admin, you're not _always_ logged in as admin-admin (plus: it favors usability)....

But, it's your forum (and I'm pleased with it so far) smile

Re: Why include a HTTP_REFERER check?

trond wrote:

Although not too likely, an evil script could get access to cookies, for instance via browsers' security holes: like when microsoft releases a new vulnerable browser, for instance internet explorer 6.0 (before SP1), + there are still users out there using older browsers.

I wasn't aware Internet Explorer 6.0 had an issue with disclosing cookie data. Where can I read more about that? Are you perhaps referring to the address bar spoofing problem? In that case, I doubt it can be used to trick the browser into disclosing cookie data.

trond wrote:

My point is that I for one wouldn't count on the HTTP_REFERER to add any extra security. To me, vBulletin's separate session cookie for the admin-panel seems preferable over a HTTP_REFERER check: if you're an admin, you're not _always_ logged in as admin-admin (plus: it favors usability)....

I agree. A separate admin sessions would probably be a more solid solution, but it will also add a lot of overhead. Then again, moderator actions do not require a separate login, so I guess vBulletin is vulnerable in that respect.

"Programming is like sex: one mistake and you have to support it for the rest of your life."

8 (edited by trond 2004-08-07 12:37)

Re: Why include a HTTP_REFERER check?

Rickard wrote:

Where can I read more about that?

http://www.securityfocus.com/bid/4754/discussion/
http://www.securityfocus.com/bid/3546/discussion/

If you click the "Info"-tab, you'll see a list of the vulnerable versions of ie.

Rickard wrote:

A separate admin sessions would probably be a more solid solution, but it will also add a lot of overhead.

Yeah, but one doesn't have to do admin stuff that often, really.

Rickard wrote:

Then again, moderator actions do not require a separate login, so I guess vBulletin is vulnerable in that respect.

Agree.

9 (edited by zaher 2004-08-07 18:08)

Re: Why include a HTTP_REFERER check?

1-  Your are admin in your forum
2- You are a user in my forum
3- you have the same password

I can hack your forum, easy with small tools (i can build one in delphi).

so i try to add an idea (dont hate me if i not understand you, read my sign)

adding to config.php

$login_key = 'any string';//every forum must define it and be secrete;

and modify some files (i am not test it just for an idea)

//line 54 in login.php
//after 
    $form_password_hash = pun_hash($form_password);
//add
    $cookie_form_password_hash = pun_hash($login_key.$form_password_hash) //hash the saved  hashed password

//in line 75
    setcookie($cookie_name, serialize(array($db_username, $form_password_hash)), $expire, $cookie_path, $cookie_domain, $cookie_secure);
//change
    $form_password_hash 
    to 
    $cookie_form_password_hash


//in function.php
//line 42
    $result = $db->query('SELECT * FROM '.$db->prefix.'users WHERE username=\''.addslashes($cookie['username']).'\' AND password=\''.addslashes($cookie['password_hash']).'\'') or error('Unable to fetch user information', __FILE__, __LINE__, $db->error());
    $cur_user = $db->fetch_assoc($result);

//remove the condition 
    AND password=\''.addslashes($cookie['password_hash']).'\''

//and add after
// for compare saved double hashed password look at $login_key here
 if ((pun_hash($login_key.$cur_user['password'] != $cookie['password_hash']))
    die error('Unable to fetch user information', __FILE__, __LINE__, null);
If your people come crazy, you will not need to your mind any more.

Re: Why include a HTTP_REFERER check?

zaher: It's not a bad idea, but it has one big problem. There is no way of upgrading everyones password so they would all have to be reset if upgrading.

"Programming is like sex: one mistake and you have to support it for the rest of your life."

11 (edited by zaher 2004-08-08 00:27)

Re: Why include a HTTP_REFERER check?

No, user just need relogin,
you must hash the hashed_password and put in cookie,  not the password in database, and when login we compare the "hashed password cookie" with hashed hashed_password 
[we need a new smile for that face  &-(   ]

that mean double hash for cookie password,
in other way, you must not save hased_password directly in cookiy as in database..

If your people come crazy, you will not need to your mind any more.

Re: Why include a HTTP_REFERER check?

Yes, but how will you keep track of whether a users hash is based on the salt ($login_key) or not?

"Programming is like sex: one mistake and you have to support it for the rest of your life."

13

Re: Why include a HTTP_REFERER check?

Why need track that?

there is new way, when login generate random value string for $login_key and save it in cookie with the double hashed password
and before compare with hashed password fetched form database

[this not real code just to explaining]

$login_key=randome key
$cookie_double_hashed_password=pun_hash($login_key.$hashed_password)
setcookie('password_hash',$cookie_double_hashed_password);
setcookie('login_key',$login_key);

now checking passowrds

$login_key=$_COOKIES['login_key'];
$database_double_hashed_password=pun_hash($login_key.$database_hashed_password)
if ($database_double_hashed_password!=$_COOKIES['password_hash'])
    login fail

If your people come crazy, you will not need to your mind any more.

Re: Why include a HTTP_REFERER check?

But with your code, everyone will be forced to use "Forget your password?" to request a new password so that a hash based on not only the password but the login key as well can be generated and stored in the database. I can't see how it would be possible to avoid.

"Programming is like sex: one mistake and you have to support it for the rest of your life."

15

Re: Why include a HTTP_REFERER check?

No Rickard,  we not modify the hashed password that stored in the database, we just change the hashed passowrd in cookie only by hashing it again with $login_key, it is easy, read carefully my first code.

If your people come crazy, you will not need to your mind any more.

Re: Why include a HTTP_REFERER check?

Ah, now I see what you mean. I'll investigate further!

"Programming is like sex: one mistake and you have to support it for the rest of your life."

Re: Why include a HTTP_REFERER check?

Done! Thanks for the excellent suggestion Zaher. It appears to be working just fine.

"Programming is like sex: one mistake and you have to support it for the rest of your life."

18 (edited by jop 2004-09-21 13:37)

Re: Why include a HTTP_REFERER check?

zaher wrote:

1-  Your are admin in your forum
2- You are a user in my forum
3- you have the same password

I can hack your forum, easy with small tools (i can build one in delphi).

so i try to add an idea (dont hate me if i not understand you, read my sign)

adding to config.php

$login_key = 'any string';//every forum must define it and be secrete;

and modify some files (i am not test it just for an idea)

//line 54 in login.php
//after 
    $form_password_hash = pun_hash($form_password);
//add
    $cookie_form_password_hash = pun_hash($login_key.$form_password_hash) //hash the saved  hashed password

//in line 75
    setcookie($cookie_name, serialize(array($db_username, $form_password_hash)), $expire, $cookie_path, $cookie_domain, $cookie_secure);
//change
    $form_password_hash 
    to 
    $cookie_form_password_hash


//in function.php
//line 42
    $result = $db->query('SELECT * FROM '.$db->prefix.'users WHERE username=\''.addslashes($cookie['username']).'\' AND password=\''.addslashes($cookie['password_hash']).'\'') or error('Unable to fetch user information', __FILE__, __LINE__, $db->error());
    $cur_user = $db->fetch_assoc($result);

//remove the condition 
    AND password=\''.addslashes($cookie['password_hash']).'\''

//and add after
// for compare saved double hashed password look at $login_key here
 if ((pun_hash($login_key.$cur_user['password'] != $cookie['password_hash']))
    die error('Unable to fetch user information', __FILE__, __LINE__, null);

Hmmm.. i dont think this method adds very much security. If you have a forum it's simple to retrieve the "real" password and not the hashed.
You just have to add some code in the login procedure.

This could add security if the attacker only has access to the Database or if an attacker manage to steal the victims cookie from your forum.




zaher wrote:

Why need track that?

there is new way, when login generate random value string for $login_key and save it in cookie with the double hashed password
and before compare with hashed password fetched form database

[this not real code just to explaining]

$login_key=randome key
$cookie_double_hashed_password=pun_hash($login_key.$hashed_password)
setcookie('password_hash',$cookie_double_hashed_password);
setcookie('login_key',$login_key);

now checking passowrds

$login_key=$_COOKIES['login_key'];
$database_double_hashed_password=pun_hash($login_key.$database_hashed_password)
if ($database_double_hashed_password!=$_COOKIES['password_hash'])
    login fail

Do you mean that the random key should be stored in the cookie?

In the scenario that you have access to the hashed pw. You could just create the double hashed pw with any number on you own. The only thing you need to know is how the pun_hash works.
This way anyone can create a valid cookie out of the pwhash in the db.

This method only gives security if the attacker has stolen the cookie from your forum.
But if he manage to steal the cookie from your forum he could probably steal the cookie from the victims own forum too. Then he could just use the cookie as it is.

I hope I made any sense and that i havent missunderstood anything.

EDIT: My suggestion would be to use the second method but store the random number in the DB. I see no reason why this should be stored in cookie.

Re: Why include a HTTP_REFERER check?

I wrote a huge post trying to explain my views on this, but I decided to scrap it. Here's the low-down:

The method zaver described doesn't prevent a malicious host from tampering with the scripts and grabbing the cleartext password. Preventing that is impossible. Once you enter your password in a form field somewhere, it's out of your control.

It does however increase security in two other aspects:

1. It makes is virtually impossible to determine the original cleartext password based on the cookie hash.
2. If you were to gain access to someones cookie hash from forum A, that hash is useless in forum B even if the user has the same password in both forums.

It works like this:

1. Upon installing the forum, a random seed of 8 bytes is generated. This seed is then stored in config.php.

2. When someone attempts to login, the cleartext password is hashed with pun_hash(). This will in most cases results in an SHA1 hash of the password (40 bytes). This hash is compared to the hash stored in the database. We'll call this the db hash.

3. Assuming the hashes matched up, the db hash and the seed from config.php (e.g. 'as123JhD') are concatenated and hashed once more (an MD5 hash this time).

4. This hash is then stored in the cookie.

"Programming is like sex: one mistake and you have to support it for the rest of your life."

Re: Why include a HTTP_REFERER check?

lol a MD5ed SHA1 sounds pretty invincible

21 (edited by jop 2004-09-21 21:35)

Re: Why include a HTTP_REFERER check?

Rickard wrote:

It does however increase security in two other aspects:

1. It makes is virtually impossible to determine the original cleartext password based on the cookie hash.

hmm isn't that what hash is. Do you mean that double hash is more safe than single?

2. If you were to gain access to someones cookie hash from forum A, that hash is useless in forum B even if the user has the same password in both forums.

Yeah big_smile that was my conclusion too (guess my post wasn't that clear after all).
I guess it increases security a little.

It works like this:

1. Upon installing the forum, a random seed of 8 bytes is generated. This seed is then stored in config.php.

2. When someone attempts to login, the cleartext password is hashed with pun_hash(). This will in most cases results in an SHA1 hash of the password (40 bytes). This hash is compared to the hash stored in the database. We'll call this the db hash.

3. Assuming the hashes matched up, the db hash and the seed from config.php (e.g. 'as123JhD') are concatenated and hashed once more (an MD5 hash this time).

4. This hash is then stored in the cookie.

Well then the random number isn't stored in the cookie(it's in config.php). I got the impression that that was the case.

Re: Why include a HTTP_REFERER check?

jop wrote:

hmm isn't that what hash is. Do you mean that double hash is more safe than single?

No, but hash(seed + hash(password)) is safer than hash(password).

Actually a "double hash" is more safe. It doesn't have any inherent improved security. A bad password is a bad password. But in reality, it makes it a lot harder to brute force seeing as there are, as far as I know, no brute force tools out there that calculate the hash twice.

"Programming is like sex: one mistake and you have to support it for the rest of your life."

23

Re: Why include a HTTP_REFERER check?

I see.