1

I Have some php scripts that i'm working on to create a log-in page, using cookies, sessions & csrf token. The scripts are Object oriented & using Classes, but The CSRF Token, which is a hidden input with-in my form is blocking the submit button from rendering. I have been staring at this and fiddleing around with it for months but I cannot figure out where the error is or why it is blocking rendering of the button, I have error reporting on but no errors are being shown. I'm also using the spl_autoload_register() function to load my classes but I don't believe this is where the issue is. Any help would be greatly appreciated

Register.php

<?php require_once 'Core/init.php';   
      include 'Core/head.php';

      if(!Usr){                                       // Not doing anything.....
          echo '<span style="color:white;">You must be logged in to view properties</span>';
      }
?>
<h1 style="color:white;">Let Living Be Life</h1>
<h2 style="color:white;">Property Rentals</h2>

<a href="index.php">Home</a><br>
<a href="profile.php">Profile</a><br>
<a href="register.php">Register</a><br>
<a href="login.php">Login</a><br>
<a href="logout.php">Logout</a><br>
<a href="changepassword.php">Change Password</a><br>
<a href="info.php">Info</a><br>

<input type="radio" name="theme-switch"><span style="color:white;">Theme</span>

<form action="" method="post">
    <input id="usrname" type="text" name="usrname"
           placeholder="Username" autocomplete="off" required="true">
    <input id="psw" type="password" name="psw"
           placeholder="password" autocomplete="off" required="true">
    <input type="checkbox" name="remember" id="remember"> <span style="color:white;">Remember me.</span>
    <!-- This is not being rendered either !!!!!!!!!!!!!!!! -->
    <input type="hidden" name="csrf_tokenz" value="<?php echo Token::gen_csrf_token(); ?>"><br>   <!-- Added '' around the echo, but it is not generating a valid token, button is back though...-->
<!-- Note, Something is blocking the button from rendering              ???????????????????? -->
    <button id="Submit_btn" type="submit">Submit</button>
</form>


<a href="index.php">Home</a>
<a href="profile.php">Profile</a>
<a href="register.php">Register</a>
<a href="login.php">Login</a>
<a href="logout.php">Logout</a>
<a href="changepassword.php">Change Password</a>
<a href="info.php">Info</a>

<?php
  // $_SESSION['user-type'] = guest; << need to set this at top of loggin page. aswell as other checks.

    if(Input::inp_exists()){
        if(Token::check_token(Input::post_or_get_inp('csrf_tokenz'))){
            $validate = new Validate();
            $validation = $validate->check_val($_POST, array(
                             'usrname' => array('required' => true),
                             'psw'     => array('required' => true)
            ));
            if($validation->vali_passed()){
              // Log Usr in..
                $usr = new Usr();

                $remember = (Input::post_or_get_inp('remember') === 'on') ? true : false;
                $login = $usr->login_usr(Input::post_or_get_inp('usrname'), Input::post_or_get_inp('psw'), $remember);

                if($login){
                    Redirect::r_to('index.php');
                    echo 'Success';
                }else{
                    echo '<p>Sorry Login Failed</p>';
                }
            }else{
                foreach($validation->vali_errors() as $error){
                   echo $error, '<br>';
                }
            }
        }
    }
?>

Token.class.php

<?php                                                           // Check all Syntax::>> 

  class Token{
    public static function gen_csrf_token(){                                  // Csrf Token 1.
        return Session::sesh_put(Config::get_conf('session/token_name'), bin2hex(random_bytes(28)).openssl_random_pseudo_bytes(7));   // md5(uniqid()) md5(random_bytes(164))<< this is the old version which is deprecated...
        }
    public static function gen_csrf_token2(){                                 // Csrf Token 2.
        return Session::sesh_put(Config::get_conf('session/token2_name'), bin2hex(random_bytes(28)).openssl_random_pseudo_bytes(7));  // ::>> Brackets maybe wrong way round in here.            
        }
    public static function genchilli_token(){                                 // Use this to Build a Pepper, Salt is in the Hash Class. Abstract Away.. 
          $Chilli = bin2hex(128).=openssl_random_psuedo_bytes(48).=md5('x12ii21ii12x');
          return $Chilli;           // <<:: Test me?
          }
    public static function check_token($token){
                                                                                // echo 'I have been run line 15 Token Class';
        $token_name = Config::get_conf('session/token_name');         // ::>> index=12
                                                                                // echo 'I have been run line 16 Token Class';
        if(Session::sesh_exists($token_name)&& $token === Session::get_sesh($token_name)){
            Session::del_sesh($token_name);
            return true;
        }
        return false;
    }
  }

The Token Class Rely's Both on the Session & The Conig Classes to work. Namely the Functions: Session::sesh_put() & Config::conf_get() but I can't find any errors in here either, and no errors are being displayed.

Session.class.php

<?php
  class Session{
        public static function get_sesh($name){
            // echo 'Debug Only >> Session::Get Ran';
            return $_SESSION[$name];                                            // ::<< these relate to Token Name in Token.class.php

        }
        public static function sesh_put($name, $value){
            // echo 'Debug Only >> Session::put Ran';
            return $_SESSION[$name] = $value;

        }
        public static function sesh_exists($name){
            // echo 'Debug Only >> Session::exists Ran';
            return (isset($_SESSION[$name])) ? true : false;
        }
        public static function del_sesh($name){
            if(self::sesh_exists($name)){
                unset($_SESSION[$name]);
            }
        }
        public static function sesh_flash($name, $string = ''){                      // Used for flashing a msg to user.
            if(self::sesh_exists($name)){                                            // Flash eps 13            // Not returning any messages for some reason..
                $session = self::get_sesh($name);
                self::del_sesh($name);                                            // This deletes the session
                return $session;
            } else {
                self::sesh_put($name, $string);
              }
        }
  }
  
  // After done upload to code review
?>

Config.php

<?php                      // ::>> This File Has no Errors.        Upto eps 8 No errors spotted so far..

  class Config{                                     // ::>> Need to build in here a check for Faulty Paths then Exit script. destroy session, log user out. 
      public static function get_conf($path = null){
          if($path){
              $config = $GLOBALS['config'];
              $path = explode('/', $path);
              
              foreach($path as $bit){
                  if(isset($config[$bit])){
                      $config = $config[$bit];
                  }
              }return $config;
          }return false;
      }
  }

init.php

<?php
    session_start();
    error_reporting(E_ALL & E_NOTICE); 
       ini_set('display_errors', 1);
       ini_set('display_startup_errors', 1);

    $GLOBALS['config'] = array(
        'mysql' => array(
            'host'    => 'localhost', // ::> 127.0.0.1 
            'charset' => 'redacted',
            'db-usr'  => 'redacted',
            'db-psw'  => 'redacted',
            'db'      => 'redacted',
            'ssh'     => 'false',                   // ::<< I added these last three for later Updates to Determine access via these three methods.
            'cli'     => 'false',                   // <<::   Need very strong Authentication If I every choose to use these.
            'cgi'     => 'false'                    // ::>>        Set-up two factor Authentication at some point.
             ),
        'remember' => array(
            'cookie_name'   => 'hashish_cookie',
            'cookie_expiry' => '784828'
            // 'preferences'   => array(            // <<:: I added this for later functionality.
            //           'usr_pref' => 'has_cat',
            //           'needs'    => 'null'
            //            ),
             ),
        'session' => array(                        // Add different Session types in here ie. Guest, Admin, Mod, ExtMod, RootAd, HasCat.
            'session_name' => 'usr_session',
            'token_name'   => 'csrf_tokenz',
            'token2_name'  => 'csrf_tokenz2',
            'hacker_bait'  => 'redacted',
            'has_cat'      => '0'
             )
    );                                          // Closing Tag for Globals Array
    spl_autoload_register(function($class) {
        require_once 'Classes/' . $class . '.class.php';
    });
    require_once 'Functions/sanitize.php';
    
    if(Cookie::cookie_exists(Config::get_conf('remember/cookie_name')) && !Session::sesh_exists(Config::get_conf('session/session_name'))){
        echo 'User Asked to Be remembered!';
        $hash = Cookie::get_cookie(Config::get_conf('remember/cookie_name'));
        $hashCheck = DB::getInstance()->get_dbr('usr_session', array('hash', '=', $hash));   // <<:: Check if this is xx >> usr_session << Correct one < or usrs_session..
        
        if($hashCheck->count_dbr()){
            echo 'Hash matches, log usr in';
        } // Unsure if this is dbr_count or count_dbr or a built in pdo version of count?

    }
?>

Any help or pointers would be greatly appreciated, as I can't find the error and its bugging me. Will Update the question and include config.php in a minute when i've logged back into my hosting site.. I have already tried using md5, uniqid, random_bytes, ssl_random_pseudo_bytes and multiple different combinations but can't get this to work properly. I know that there are multiple other questions on how to securely generate a CSRF token, but none of the ones I have found are using classes or object oriented program, nor do they address my specific issue. I have read multiple different ones, some of which have helped my understanding but not fixing this issue.

The Image shows what is being rendered and where it stops or breaks. Having used Ctrl + U as Mike suggested in the comments.

enter image description here

Update, Just added a ~ to E_NOTICE error reporting after reading the post that Mike Shared: Error Reporting and it has generated a new Notice that wasn't showing before, so that might help to fix these issues. Picture included below: enter image description here

Fixed: commenting out the innards of the chilli function....

Ryan Stone
  • 228
  • 2
  • 15
  • When you say that when you output the CSRF token it blocks the submit button from rendering, this would indicate to me that an error message is being echoed and makes your page have invalid HTML and that's why it's not being rendered to the screen. Unless you are using some sort of output buffering and manipulating the page after it has been generated, there's no reason the submit button would not be there. You need to look at the actual output page source, not how the browser decides to render it to the screen. – Mike Jun 25 '20 at 02:17
  • Also, according to [this answer](https://stackoverflow.com/a/31683058), `bin2hex(random_bytes(32))` should be sufficient for generating a CSRF token. I recommend just sticking with that instead of convoluting things with different random number generators. – Mike Jun 25 '20 at 02:29
  • @Mike Thanks for your reply I have already checked the Source code within the devtools in Firefox developer edition but the Hidden input field is not being included, it should show up with the generated token greyed out & non editable but its not even showing, so theres an error somewhere in the php, ps i'm not using any buffer.. – Ryan Stone Jun 25 '20 at 02:39
  • You're still looking in the wrong place. The dev tools will not show you what you want because that is how the browser parses the HTML. You need to look at the actual source code of the page. Push Ctrl-U. – Mike Jun 25 '20 at 02:43
  • @Mike oh Thanks, never knew you could do that. You were right its outputting invalid html The Hidden input is highlighted red with a missing end " .... [ – Ryan Stone Jun 25 '20 at 02:52
  • @Mike Still stuck though, just changed it back to bin2hex(random_bytes(32)) – Ryan Stone Jun 25 '20 at 03:00
  • 1
    Does the output abruptly end after the code in your comment? If not, please post it in your question. If it does end like that, check your log files. It is likely producing some sort of error or exception that kills the script at that point. – Mike Jun 25 '20 at 03:01
  • @Mike Not 100% sure what you mean by that but I have added an image of the output/source & where it is breaking.. – Ryan Stone Jun 25 '20 at 04:33
  • If you can't find the log file that the errors are being written to, see https://stackoverflow.com/questions/1053424/how-do-i-get-php-errors-to-display – Mike Jun 25 '20 at 07:53
  • @Mike that is not the Issue mike, No errors are being generated. I have checked in the error file, in my custom errors file, in all the logs. That is why it is being so difficult to debug. as I can't find where the issue is originating. – Ryan Stone Jun 25 '20 at 07:58
  • @Mike Saying that though, adding a tilda['~'] to error_reporting(E_NOTICE) has helped so, I take that last statement back. Updating the Question with the new error code. – Ryan Stone Jun 25 '20 at 08:04
  • Please do not post screenshots of code. Post the code itself. – Mike Jun 25 '20 at 19:50

2 Answers2

1

The error message that you have was throwing me for a bit of a loop because the line number in the error is not the same line in the code that is producing the error, which means you must have updated your code between when you posted the question and when you posted the error message. It is important to make sure that the error message you post is the one that is actually produced by executing the code you have, or else nobody will be able to reproduce your error.

Your problem is this line:

$Chilli = bin2hex(128).=openssl_random_psuedo_bytes(48).=md5('x12ii21ii12x');

This is a syntax error and should instead be either this:

$Chilli = bin2hex(128) . openssl_random_psuedo_bytes(48). md5('x12ii21ii12x');

or this:

$Chilli = bin2hex(128);
$Chilli .= openssl_random_psuedo_bytes(48);
$Chilli .= md5('x12ii21ii12x');
Mike
  • 20,721
  • 13
  • 66
  • 79
  • The Error Code that is displayed at the very bottom of the question, is the code that came up just after I added the tilda ~ to the E_NOTICE section of error reporting and I only screen shotted the code that was displayed by pressing Ctrl + U as you suggested. – Ryan Stone Jun 26 '20 at 06:47
  • @RyanStone See https://meta.stackoverflow.com/questions/285551/why-not-upload-images-of-code-on-so-when-asking-a-question/ for the reasons why you shouldn't post screenshots of code. – Mike Jun 26 '20 at 19:44
  • I only posted that screen shot in response to you saying press Ctrl+U so people could see what the result was.. – Ryan Stone Jun 28 '20 at 06:24
  • @RyanStone That text can be copied and pasted as well. – Mike Jun 29 '20 at 18:55
0

Have you tried using <?php echo Token::gen_csrf_token(); ?> to display the generated token in plain text?

If you have tried, is it the token string you are after and usable for a "hidden" tag?

  • Just tried this, but there is an error somewhere within my Token class, The Session class or my Config file but it can't for the life of me find where it is, wish php error reporting was more robust or in depth. Absolutely no errors on screen, in my log file or error file... Just gotta keep routing about till i find it.. This echo doesn't output anything, just blank – Ryan Stone Jun 25 '20 at 05:52