Topic: "Unable to confirm security token"

Hello

I'm getting the following error message from PunBB after including the familiar two lines in a script, after the user has already been authenticated by PunBB and received the forum_cookie_baf83f cookie:

Unable to confirm security token. A likely cause for this is that some time passed between when you first entered the page and when you submitted a form or clicked a link. If that is the case and you would like to continue with your action, please click the Confirm button. Otherwise, you should click the Cancel button to return to where you were.

This is actually a very simple play, with the following characters:

  • /blog/index.php

  • /blog/action.php

  • /punbb/login.php

A picture being worth a thousand words, here's the plan:

http://img838.imageshack.us/img838/8666 … nlogin.png

In other words, /blog/index.php uses PunBB's code to check if the user is logged on: If not, it calls /punbb/login.php, which, once the use is logged on, redirects the user back to /blog/index.php. So far, so good.

Next, /blog/index.php sees that the user is logged on, and displays a form with a single button "Subscribe/Unsubscribe"; The form calls /blog/action.php which includes just the two lines from PunBB:

define('FORUM_ROOT', '/var/www/nginx-default/punbb/');
require FORUM_ROOT.'include/common.php';

Here's the full code of index.php and action.php.

As you can see in the following HTTP log, when the user clicks on the Subscribe/Unsubscribe button to call action.php, for some reason, PunBB isn't happy and sends another cookie with Set-Cookie:

http://pastebin.com/jHJ4MprR

Does someone more experienced with web applications have an idea what the problem could be?

Thank you for any hint.

Re: "Unable to confirm security token"

Found something: After the user is logged on, calling /blog/action.php directly works fine. So the problem is when /blog/index.php calls action.php through the button in the form. No idea what it makes a difference hmm

3 (edited by Grez 2010-08-02 20:10)

Re: "Unable to confirm security token"

You have to include common.php before you send any input to browser  wink

BTW what program did you use for this image? Looks cool  smile

Eraversum - scifi browser-based online webgame

Re: "Unable to confirm security token"

Grez wrote:

You have to include common.php before you send any input to browser

Thanks for the tip, but I just tried and no go :-/

The first step (authentication) works fine, but I still the error message in the second step where I click on a form button to call action.php in the same directory (calling action.php manually by typing its URL works OK):

index.php

<?php

define('FORUM_ROOT', '/var/www/punbb/');
require FORUM_ROOT . 'include/common.php';

$forum_page['redirect_url'] = "/blog/test/index.php";
$forum_page['form_action'] = forum_link($forum_url['login']);
$forum_page['hidden_fields'] = array(
    'form_sent'    => '<input type="hidden" name="form_sent" value="1" />',
    'redirect_url'    => '<input type="hidden" name="redirect_url" value="'.forum_htmlencode($forum_page['redirect_url']).'" />',
    'csrf_token'    => '<input type="hidden" name="csrf_token" value="'.generate_form_token($forum_page['form_action']).'" />'
);

//!guest = authenticated
if(!$forum_user['is_guest']) {
    ?>
      <form method="post" action="action.php">
        <input type="submit" name="subscribe" value="Subscribe" />
        </form>
    <?php

} else {
      ?>
      <form method="post" action="<?php echo $forum_page['form_action'] ?>">
                <?php echo implode("\n\t\t", $forum_page['hidden_fields'])."\n" ?>
    
                User: <input type="text" id="fld1" name="req_username" value="" /> <br />
    
                Password: <input type="password" id="fld2" name="req_password" value="" /> <br />
    
              <input type="submit" name="login" id="login" value="Login" />
      </form>
      <?php
}

?>

action.php:

<?php
/*
Unable to confirm security token. A likely cause for this is that some time passed between when you first entered the page and when you submitted a form or clicked a link. If that is the case and you would like to continue with your action, please click the Confirm button. Otherwise, you should click the Cancel button to return to where you were.
*/

define('FORUM_ROOT', '/var/www/nginx-default/punbb/');
require FORUM_ROOT . 'include/common.php';

if(!$forum_user['is_guest']) {
    print $forum_user['username'] . "<p>";
} else {
    print "Not logged on!<p>";
}
?>
Grez wrote:

BTW what program did you use for this image?

It's a neat little application called Balsamiq Mockups. There are others, including the open-source Pencil, but it doesn't seem to have much traction (not enough icons).

Thank you.

Re: "Unable to confirm security token"

If we can't find the cause for this error, as a work-around, is there a way for my script to somehow check...

1) that the user has been authenticated

2) read his username?

What about either reading some infos from $_SESSION[] or directly in the PunBB database?

6 (edited by Grez 2010-08-03 10:28)

Re: "Unable to confirm security token"

Ok, I checked PunBB code and your code and finally found the error  big_smile

Each time, when you send $_POST punBB will check, whether you send right CSFR token, which is sha1 hash of target url address. (./includes/common.php: line 124-6)

So your code should be like this. (Check line 7)  wink

littlebigfred wrote:

It's a neat little application called Balsamiq Mockups. There are others, including the open-source Pencil, but it doesn't seem to have much traction (not enough icons).

Thx, I'll try it out smile

Eraversum - scifi browser-based online webgame

Re: "Unable to confirm security token"

Grez wrote:

Ok, I checked PunBB code and your code and finally found the error

Thanks for the tip, but changing that line isn't the solution since PunBB uses this link to direct the user to login.php for the initial authentication. If I change it like shown, I can no longer authenticate and I get the same error message that I get when calling action.php

Grez wrote:

Each time, when you send $_POST punBB will check, whether you send right CSFR token, which is sha1 hash of target url address. (./includes/common.php: line 124-6)

Mmm... In that case, could index.php or action.php simply hash a new CSRF variable so that PunBB is OK?

Work-arounds I checked but don't work:

  • Read "online" table from MySQL, but the "logged" column just shows the last time (Epoch)  the user sent a query. Even after a user logs out, the "logged" column isn't cleared

  • Switch to the session.name used by PunBB ("forum_cookie_baf83f"), and read the contents of $_SESSION[], but it's empty:

<?php

//Called after loggin on through PunBB

//default = PHPSESSID, while PunBB uses forum_cookie_baf83f
$previous_name = session_name("forum_cookie_baf83f");

session_start();

echo "Previous name was $previous_name<br />";
print sprintf("Current name is %s<p>",session_name());

//Expected $_SESSION[] to contain user data, but empty
foreach ($_SESSION as $key => $value){
  print sprintf("%s = %s<p>\n",$key,$value);
}
?>

Integrating unrelated web apps is a PITA ;-)

8 (edited by littlebigfred 2010-08-03 11:03)

Re: "Unable to confirm security token"

Next, I tried hashing URLs myself through generate_form_token(), but I still get the "Unable to confirm security token" error message:

//Authenticated
if(!$forum_user['is_guest']) {

        //$csrf = generate_form_token(get_current_url());
        //BAD $csrf = generate_form_token("/blog/test2/index.php");
        //BAD $csrf = generate_form_token("/nlog/test2/action.php");
        ?>

    <form method="post" action="action.php">
      <input type="hidden" name="csrf_token" value="<?php echo $csrf; ?>">
      <input type="hidden" name="event" value="<?php echo $var_url['idpost']; ?>" />
      <input type="submit" name="subscribe" value="<?php echo $value; ?>" />
        </form>
        <?php

Re: "Unable to confirm security token"

Would it be a big security risk if I just tell PunBB to ignore this, and use:

define('FORUM_SKIP_CSRF_CONFIRM');

?

10

Re: "Unable to confirm security token"

This should work smile
- you set csfr_token for each form individually.

littlebigfred wrote:

I tried hashing URLs myself

If you want to do that, you have to use full url address (including "http://"...)

Eraversum - scifi browser-based online webgame

Re: "Unable to confirm security token"

Thanks. I was about to paste the same solution, but you beat me to it smile

index.php

<?php
//http://phpro.org/examples/Get-Full-URL.html
function getURLBaseName()
{
  $protocol = $_SERVER['HTTPS'] == 'on' ? 'https' : 'http';
  //return $protocol.'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
  $fullpath = $protocol.'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
  //return basename($fullpath);
  return $fullpath;
}
     
[...]
//Authenticated
if(!$forum_user['is_guest']) {
    //Strip filename from full URL
    $path_parts = pathinfo(getURLBaseName());
    $fullpath = $path_parts['dirname']. "/action.php";
    $csrf = generate_form_token($fullpath);
    ?>
    <form method="post" action="action.php">
            <input type="hidden" name="csrf_token" value="<?php echo $csrf; ?>">
            <input type="hidden" name="event" value="<?php echo $var_url['idpost']; ?>" />
            <input type="submit" name="subscribe" value="<?php echo $value; ?>" />
    </form>
    <?php
} else {
    ?>
    Authentication required<p>
  <form method="post" action="<?php echo $forum_page['form_action'] ?>">
            <?php echo implode("\n\t\t", $forum_page['hidden_fields'])."\n" ?>

            User: <input type="text" id="fld1" name="req_username" value="" /> <br />

            Password: <input type="password" id="fld2" name="req_password" value="" /> <br />

          <input type="submit" name="login" id="login" value="Login" />
     </form>
    <?php
}
?>

action.php

<?php

define('FORUM_ROOT', '/var/www/nginx-default/punbb/');
require FORUM_ROOT.'include/common.php';

print $forum_user['username'] . "<p>";

//Why is nothing printed on screen?
foreach ($_SESSION as $key => $value){
  print sprintf("%s = %s<p>\n",$key,$value);
}
?>

A couple of questions:

  • Do I really need to include "implode("\n\t\t", $forum_page['hidden_fields)" in the form once the user is authenticated? I didn't use it, and it seems to work OK

  • In action.php, why is $_SESSION[] empty?

Thank you.

12

Re: "Unable to confirm security token"

Do I really need to include "implode("\n\t\t", $forum_page['hidden_fields)" in the form once the user is authenticated? I didn't use it, and it seems to work OK

I believe so. You don't need the whole array, but for each $_POST you have to use csfr_token...

In action.php, why is $_SESSION[] empty?

Well, actually it seems like PunBB doesn't use sessions at all *.*

Eraversum - scifi browser-based online webgame

Re: "Unable to confirm security token"

Grez wrote:

Well, actually it seems like PunBB doesn't use sessions at all *.*

Really? If there's a PHP expert in the audience, I'd like to know why they didn't. Since PunBB uses its own cookie instead of PHPSESSID, I assume it's a safe-guard against some other application also putting its data in $_SESSION[], which would make sense.