2

I have two files: one is exposing a session-Token, the other one is answering a javascript-fetch. File one contains:

<?php
session_start();
unset($_SESSION['sessionToken']);
$_SESSION['sessionToken'] = vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex(random_bytes(16)), 4));
?><!DOCTYPE HTML>
<html>
...
    <meta content="<?php echo $_SESSION['sessionToken'] ?? '12345'; ?>" name="csrf-token" />

and further on I make in the same file a fetch request like this:

fetch('src/exposeDelivery.php', {      
           //mode: 'same-origin',
           credentials: 'same-origin',     //'same-origin'    'omit'     'include
           method: 'POST',
           body: JSON.stringify( jsonArr ),
           headers: {
            'x-csrf-token':  document.head.querySelector('meta[name="csrf-token"]').content,
            "Content-Type": "application/json",
            "Accept":       "application/json"
           }
      })
        .then(response => {
          if (!response.ok) {
            console.log("response: %s  | %o",response.statusText,response);
            throw new Error('Network response was not ok');
          }
          return response.json();
        })

The fetch-request runs in an interval like let ask = setInterval(makeRequest, 20000);

My second file, where the request goes to, looks like this:

    <?php
    session_start();
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Methods: GET, POST');
    header('Access-Control-Allow-Headers: Content-Type, X-Requested-With, x-csrf-token');
    $csrf = isset($_SERVER["HTTP_X_CSRF_TOKEN"])
          ? trim($_SERVER["HTTP_X_CSRF_TOKEN"])
          : 0;
    $response['t_token']= $csrf;
    $response['sessionToken'] = $_SESSION['sessionToken'] ? $_SESSION['sessionToken'] : "noSessionToken";

    header('HTTP/1.0 200 OK');
    header('Content-Type: application/json');

    echo json_encode($response);

Now I would like to check if $csrf == $_SESSION['sessionToken'].
This is the first time I call the fetch-request true. But the second time the request is called, it is differend. What is wrong here? Is File one with the fetch-request calling itself on every request? Can I solve it with maybe another request?

guyaloni
  • 4,972
  • 5
  • 52
  • 92
hamburger
  • 1,339
  • 4
  • 20
  • 41
  • If you are not sure what requests are actually happening, then use the network panel of your browser dev tools to find out. – CBroe Jan 25 '21 at 11:35
  • That what I did. In the first response $response['t_token'] == $response['sessionToken']. In the second call there are not equal anymore. – hamburger Jan 25 '21 at 11:40
  • Do you have any `session_destroy` ? also you can try to make no cache request with fetch like explain in this post : https://stackoverflow.com/questions/29246444/fetch-how-do-you-make-a-non-cached-request – Fky Jan 25 '21 at 11:44
  • of curse not an not any definition of $_SESSION['sessionToken'] in the second file. That why I assume that the first file ist called on every request. But I do not know it. – hamburger Jan 25 '21 at 11:46
  • Have you considered logging both values to see which of the two changes? – El_Vanja Jan 27 '21 at 12:37
  • the $_SESSION['sessionToken'] is changed once (with the second call) – hamburger Jan 27 '21 at 15:29
  • Unfortunately, I was unable to reproduce this issue locally. The token remains the same at all times, no matter how many calls are made. – El_Vanja Jan 28 '21 at 22:08
  • you unset unset($_SESSION['sessionToken']); so every request it's new value – bxN5 Jan 29 '21 at 18:38
  • can you upload your complete code to [repl.it PHP web server](https://repl.it/languages/php7) – uingtea Feb 02 '21 at 16:48
  • Although I don't understand why do you reset the `sessionToken` each time, your code should work. Please supply more information about the error you get and how to reproduce it. – guyaloni Feb 02 '21 at 19:22

2 Answers2

0

It appears you are unsetting $_SESSION['sessionToken'] variable, so it generates new value every time. Remove 3rd line in first file and you are good to go.

Tom
  • 71
  • 1
  • 11
-1

I could not reproduce the error you mention.
I think that the reason is that php code is executed on server-side, hence it is executed before the javascript code, which calls the server via POST. In this time, your server api call has the same token as the javascript code.

However, I don't understand why you generate the token each time. You might use this code instead:

if (!isset($_SESSION['sessionToken'])) {
    $token = vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex(random_bytes(16)), 4));
    $_SESSION['sessionToken'] = $token;
}

Another reason might be the comparison you do in order to verify the token.
Instead of using the === comparison, use hash_equals:

if (hash_equals($csrf, $_SESSION['sessionToken'])) {
     :
     :
}
guyaloni
  • 4,972
  • 5
  • 52
  • 92
  • 1
    @hamburger, please either accept the answer or comment what is missing. People put effort into it. – guyaloni Feb 08 '21 at 12:15
  • Sorry I was in hospital, so I could not response in time. Both two answers doesn't help. I have a rented server. After a while the code is still working as expected now. So all the people are right with saying that they can't reproduce the error. I think there was something strugggled with the server-vars. Thanks to all helpers. – hamburger Feb 12 '21 at 14:33