Re: Security of Pun's authentification

Normally you would check your code for errors. By reviewing the code. Simply but ( walk trough your code step by step to find out what it exactly does. And compare that to what it really should do.

Finding bugs like xss hacks and sql injections is some what difficult. Your first stop is to learn what xss hacks and sql injections are. You will find may resources on both of them. As soon as you understand what those bugs mean you also should know how to avoid them.

A good rule for developing php is.

never ever trust user input. Allways check the data you receive. Is it what you expected ?? Did it arrive from the location you expected. Make use of htmlspecialchars to filter our any html related code etc.

This is in no way complete for more info read as much as you can. If you read an article on php make sure you read the comments to. This will help you unterstand if the article is any good or not. Doesn't make sense to learn stuff the wrong way.

52 (edited by spec 2005-04-09 17:09)

Re: Security of Pun's authentification

So there what  we added and modified:
functions.php

////////////////////////////////////////////////////////////////////////////////////////////////////
// Check personal user data
////////////////////////////////////////////////////////////////////////////////////////////////////
function check_info(&$pun_user)
{
session_start();
global $db, $pun_config, $cookie_name, $cookie_seed;
$now = time();
    if (isset($_SESSION['user_id']) && $_SESSION['user_id'] > 1 && !empty($_SESSION['info']) && AuthHash() === $_SESSION["info"])
    {
        $result = $db->query('SELECT u.*, g.*, o.logged, o.idle FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON u.group_id=g.g_id LEFT JOIN '.$db->prefix.'online AS o ON o.user_id=u.id WHERE u.id='.intval($_SESSION['user_id'])) or error('Unable to fetch user information', __FILE__, __LINE__, $db->error());
        $pun_user = $db->fetch_assoc($result);
        
        // If user authorisation failed
        if (!isset($pun_user['id']) || $pun_user['password'] !== $_SESSION['password_hash'])
        {
            set_default_user();
            return;
        }

        // Set a default language if the user selected language no longer exists
        if (!@file_exists(PUN_ROOT.'lang/'.$pun_user['language']))
        $pun_user['language'] = $pun_config['o_default_lang'];

        // Set a default style if the user selected style no longer exists
        if (!@file_exists(PUN_ROOT.'style/'.$pun_user['style'].'.css'))
        $pun_user['style'] = $pun_config['o_default_style'];

        if (!$pun_user['disp_topics'])
        $pun_user['disp_topics'] = $pun_config['o_disp_topics_default'];
        if (!$pun_user['disp_posts'])
        $pun_user['disp_posts'] = $pun_config['o_disp_posts_default'];

        if ($pun_user['save_pass'] == '0')
        $expire = 0;
    
        // MOD: MARK TOPICS AS READ - 4 LINES NEW CODE FOLLOW
        if ($pun_user['read_topics'])
            $pun_user['read_topics'] = unserialize($pun_user['read_topics']);
        else
            $pun_user['read_topics'] = array();

        
        // Define this if you want this visit to affect the online list and the users last visit data
        //if (!defined('PUN_QUIET_VISIT')) echo 'YES';
        if (!defined('PUN_QUIET_VISIT'))
        
        {
            
            // Update the online list
            if (!$pun_user['logged'])
            $db->query('INSERT INTO '.$db->prefix.'online (user_id, ident, logged) VALUES('.$pun_user['id'].', \''.$db->escape($pun_user['username']).'\', '.$now.')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
            else
            {
                // Special case: We've timed out, but no other user has browsed the forums since we timed out
                if ($pun_user['logged'] < ($now-$pun_config['o_timeout_visit']))
                {
                    //$db->query('UPDATE '.$db->prefix.'users SET last_visit='.$pun_user['logged'].' WHERE id='.$pun_user['id']) or error('Unable to update user visit data', __FILE__, __LINE__, $db->error());
                    // MOD: MARK TOPICS AS READ - 1 LINE MODIFIED CODE FOLLOWS
                    $db->query('UPDATE '.$db->prefix.'users SET last_visit='.$pun_user['logged'].', read_topics=NULL WHERE id='.$pun_user['id']) or error('Unable to update user visit data', __FILE__, __LINE__, $db->error());

                    $pun_user['last_visit'] = $pun_user['logged'];
                }

                $idle_sql = ($pun_user['idle'] == '1') ? ', idle=0' : '';
                $db->query('UPDATE '.$db->prefix.'online SET logged='.$now.$idle_sql.' WHERE user_id='.$pun_user['id']) or error('Unable to update online list', __FILE__, __LINE__, $db->error());
            }
        }

        $pun_user['is_guest'] = false;
    }
    else
    set_default_user();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Return Hash of User's environment
////////////////////////////////////////////////////////////////////////////////////////////////////
function AuthHash()
{
   return md5(
        $_SERVER["REMOTE_ADDR"].
        (string)@$_SERVER["HTTP_USER_AGENT"].
        (string)@$_SERVER['HTTP_ACCEPT_ENCODING'].
        (string)@$_SERVER['HTTP_ACCEPT_LANGUAGE'].
        (string)@$_SERVER['HTTP_X_FORWARDED_FOR']
        );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Put personal user data into Session
////////////////////////////////////////////////////////////////////////////////////////////////////

function pun_start_session($user_id, $password_hash)
{
session_start();
$_SESSION['user_id']=$user_id;
$_SESSION['password_hash']=$password_hash;
$_SESSION['info']=AuthHash();

}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Destroy  The  Session
////////////////////////////////////////////////////////////////////////////////////////////////////

function pun_end_session()
{
$_SESSION = array();
session_destroy();
}

common.php: 115

//check_cookie($pun_user);
check_info($pun_user);

login.php:79

//pun_setcookie($user_id, $form_password_hash, $expire);
pun_start_session($user_id, $form_password_hash);

login.php:102

//pun_setcookie(1, random_pass(8), time() + 31536000);
pun_end_session();

53 (edited by Smartys 2005-04-09 18:58)

Re: Security of Pun's authentification

Erm, you have the Mark Topics as Read mod in there tongue
And some of the data in your AuthHash can change very easily (un-intentionally that is, like by a proxy server which only sometimes sends x_forwarded_for or a privacy nut who changes proxies every 10 seconds) wink

54

Re: Security of Pun's authentification

Smartys wrote:

Erm, you have the Mark Topics as Read mod in there tongue
And some of the data in your AuthHash can change very easily (un-intentionally that is, like by a proxy server which only sometimes sends x_forwarded_for or a privacy nut who changes proxies every 10 seconds) wink

as you can see....this will not affect on authentification wink
for example, what will if you change 'HTTP_X_FORWARDED_FOR'  ?.... smile

55 (edited by Smartys 2005-04-09 21:40)

Re: Security of Pun's authentification

Actually, it will
If my HTTP_X_FORWARDED_FOR (or any part of the auth) changes during the session, I'm logged out wink

56 (edited by rajivm 2005-04-10 03:19)

Re: Security of Pun's authentification

Rickard requested some info on the MD5/other one way hash challenge system I sugested.... sorry for the delay, but heres a brief overview:

This is basically how a MD5 challenge works:

1) Server sends client (prints it in the JavaScript/hidden form field) a random challenge value and stores it in session
2) User enters password on this page which has the random server challenge value
3) When user submits form, client JavaScript hashes the challenge value with the password and submits it
4) Since the server has the challenge value stored in the session it can hash the stored user pass w/ the challenge value and see if it matches the submitted hash

If the password stored on the server is hashed, it may require a double hash on the client's side.

Basically this prevents someone who intercepts the hash over the network from reusing it to authenticate w/ the server since the challenge value will be different every time.

edit: if the client does not have JavaScript support you can make it optional; it will only put that one user at a slightly higher risk and not affect the general security

57

Re: Security of Pun's authentification

Smartys wrote:

Actually, it will
If my HTTP_X_FORWARDED_FOR (or any part of the auth) changes during the session, I'm logged out wink

Do you really often do it? I don't think so.... smile
If yes, you can remove this option from the function wink

Re: Security of Pun's authentification

I don't have it often
I know people using the browser built into AOL have their IP change often (they use many different proxies) smile

Re: Security of Pun's authentification

Simple solution would be to use SSL for log in ?