1

I began to learn code only three months ago, so it's possible for all the mystery to be just a beginner's mistake. Let's summarize the problem:

I made a CMS that still run well on localhost (wampserver with PHP 7.3) but suddenly stopped to run well on my domain (OVH hoster). What is mysterious is that the problem occurred when, after having relocated the CMS on a subdomain (it still worked then), I regenerated the LetsEncrypt SSL certificates (at this point it stopped working).

I contacted the hoster: apparently the SSL certificates are fine. The pages that stopped working all use session variables : captcha, forgot, login, logout, registration.

So I checked many session variables problems threads here, but it still didn't help for my situation.

For example: I tried to var_dump some session variables on the subdomain: nothing strange, it shows exactly what is expected. I then wondered if it was a CHMOD problem so I checked if all the files were actually CHMOD 644 : they are. I tried to revert back to PHP 7.2 : changed nothing. I even removed some .htaccess files to check if they were so poorly setted it caused the problem: changed nothing (I put them back since).

My hosting plan won't allow me to access php.ini to compare the server version with my local version. So I'm kind of stuck.

Update

I have a new hypothesis: the server doesn't handle my POST methods as it handled them before. In the developer tools, the echoed POST method file was just "/".

I added the following condition to my ifItIsMethod function (the function is described at the end of this post):

if(empty($_SERVER['CONTENT_TYPE'])) {
$_SERVER['CONTENT_TYPE'] = "application/x-www-form-urlencoded";
}

and now the POST method file returns "index", which sounds like a progress. I'll edit tomorrow my .htaccess files to set the post_max_size, but the new hypothesis is HTTP (or IIS) messing up with POST.


Day 7:

  • setting the attribute "name" to "submit" in the input field doesn't change the result

  • editing the post_max_size in .htaccess is forbidden by the hoster (it returns a 500 Internal Server Error)

  • var_dump($_POST) echoes what is normally expected (nothing from the form is missing)

So I var_dumped each variable of my (very basic) login_user function:

function login_user($username, $password)

{
    global $connection;
    $username = escape($username);
    $password = escape($password);

    $query = "SELECT * FROM users WHERE user_name = '{$username}' ";
    $select_user_query = mysqli_query($connection, $query);
    if (!$select_user_query) {
        die("QUERY FAILED");
    }

    while($row = mysqli_fetch_assoc($select_user_query)) {
        $db_id = $row['user_id'];
        $db_name = $row['user_name'];
        $db_password = $row['user_password'];
        $db_firstname = $row['user_firstname'];
        $db_lastname = $row['user_lastname'];
        $db_email = $row['user_email'];
        $db_role = $row['user_role'];
    }
    $password_verify = password_verify($password, $db_password);
    if($username === $db_name && $password_verify === true) {
        $_SESSION['user_id'] = $db_id;
        $_SESSION['user_name'] = $db_name;
        $_SESSION['user_firstname'] = $db_firstname;
        $_SESSION['user_lastname'] = $db_lastname;
        $_SESSION['user_email'] = $db_email;
        $_SESSION['user_role'] = $db_role;
        redirect("admin");
    } else {
        redirect("index");
    }
}

$row has all the expected informations

$_SESSION has nothing...

... but it's because password_verify() returns "false"

The new hypothesis was then: maybe a change in the server messed up with the password decryption, let's just try to change it.

But the forgot page is also broken! And this functionnality doesn't use password_verify.

Its PHP part is as follows:

if(ifItIsMethod("post")) {
    if(isset($_POST['email'])) {
        $email = escape($_POST['email']);
        $length = 50;
        $token = bin2hex(openssl_random_pseudo_bytes($length));
        if(email_exists($email)) {
            $query = "UPDATE users SET token = ? WHERE user_email = ?";
            $stmt = mysqli_prepare($connection, $query);
            mysqli_stmt_bind_param($stmt, "ss", $token, $email);
            mysqli_stmt_execute($stmt);
            mysqli_stmt_close($stmt);
            $mail = new PHPMailer(true);
            $mail->isSMTP(true);
            $mail->Host       = SMTP_HOST;
            $mail->Username  = SMTP_USER;
            $mail->Password   = SMTP_PASSWORD;
            $mail->Port       = SMTP_PORT;
            $mail->SMTPAuth   = true;
            $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
            $mail->isHTML(true);
            $mail->CharSet = "UTF-8";
            $mail->setFrom('postmaster@raphaelbadawi.fr', 'RB Blog Postmaster');
            $mail->addAddress($email);
            $mail->Subject = "RB Blog - Réinitialisation de votre mot de passe utilisateur";
            $mail->Body = "<h4>Bonjour,</h4><p>Cliquez sur le lien suivant pour réinitialiser votre mot de passe : <a href='https://blog.raphaelbadawi.fr/reset.php?email=" . $email . "&token=". $token ."'>lien</a>.</p><small>L'équipe RB Blog</small>";
            if($mail->send(true)) {
                $emailSent = true;
            }
        } else {
            $msg = "Cette adresse ne correspond à aucun utilisateur connu";
        }
   }
}

And here is the ifItisMethod function:

function ifItIsMethod($method = null) {
    if(empty($_SERVER['CONTENT_TYPE'])) {
        $_SERVER['CONTENT_TYPE'] = "application/x-www-form-urlencoded";
    }
    if($_SERVER['REQUEST_METHOD'] == strtoupper($method)) {
        return true;
    } else {
        return false;
    }
}

I don't know what to do next.


Day 8 :

Checked the SQL tables just in case: token is text, password is varchar 255, seems fine.


Day 8.5 :

PROBLEM SOLVED! The database contained passwords that were hashed locally. Rehashing them using the remote server basically solved the login. The forgot function was buggy because of an obsolete $_GET check I forgot to mute at the top of the page (in the first version of this function, the token was passed through the URL).

I wanted to thank you all for all the time and mind you put into this issue. It did help eliminate some hypothesis. Without you I would surely still be at it. Thanks!

  • 1
    Can you run a script to display phpinfo() on both servers? Even if you don't have access to php.ini phpinfo() should tell you everything you need. Also, just to clarify, are you accessing the live site with https rather than http ? – Mark_1 Jan 03 '20 at 12:30
  • Yes, I'm accessing the live site via https and forcing https with .htaccess. The problems remain unchanged when I disable .htaccess and access the site via port 80. I'll post the phpinfo() output both from localhost and the live site as soon as I can. Thanks :-) – raphaelbadawi Jan 03 '20 at 12:44
  • Here are bits of the phpinfo() executed from localhost: https://postimg.cc/21tzDkbZ And the same from the remote server: https://postimg.cc/WDSQMjg4 – raphaelbadawi Jan 03 '20 at 13:07
  • Do you have error logging on? When you say the pages don't work, what are the symptoms? Are there any messages in the error log? Does any part of the page display? – Mark_1 Jan 03 '20 at 14:23
  • Do you have PHP error logging on? https://stackoverflow.com/questions/1053424/how-do-i-get-php-errors-to-display?noredirect=1&lq=1 Your phpinfo() listing should tell you where the PHP error log file is. – Mark_1 Jan 03 '20 at 15:04
  • I will check that on monday, I will not be at home until then, but be sure I will then check the PHP error log file listed by phpinfo() :-) – raphaelbadawi Jan 03 '20 at 18:12
  • Hello again, I advanced a bit on this boggy situation. So, the full error reporting (E_ALL) allowed me to see a misconfiguration in my .htaccess : I was using a [F] flag which prevented access to my includes folder ; putting instead an Options -Indexes solved the captcha problem. But the login and registration functions still don't work! I var_dumped some login $_SESSION variables after trying to log in: they return null values. Nothing appears in the error_reporting concerning login and registration. – raphaelbadawi Jan 06 '20 at 09:24
  • N.B. : I replaced my "include" lines by "require" lines so I'm pretty sure my functions.php file is correctly included. – raphaelbadawi Jan 06 '20 at 09:28
  • I investigated a bit more with the browser's developer tools: when I try to login at 11AM the returned "last access" values of PHPSESSID and SERVERID are at... 10AM. Maybe a conflict between the server and the browser's time values? So I believe janmyszkier's hypothesis was right. But setting the session cookie lifetime didn't solve the problem. – raphaelbadawi Jan 06 '20 at 10:22
  • Is your live site behind a load balancer or similar front end processor? PHP session handling assumes that everything is on one server, if you go to a different server on your second page the session variables for the first page won't be available. You can code around this but first you have to realise that it is happening. – Mark_1 Jan 06 '20 at 11:34
  • I'm not sure I understand the question correctly. According to my OVH admin space, the domain and subdomains all run on the same server with the same DNS and the same PHP processor. The offer I subscribed to doesn't include a dedicated server. – raphaelbadawi Jan 06 '20 at 13:42
  • Just trying to eliminate possibilities. If you were running multiple servers behind a load balancer you might need a more sophisticated method of handling sessions, sounds like yours is a plain vanilla case though. – Mark_1 Jan 06 '20 at 14:57
  • Keeping fiddling around with this session issue. I tried again the ini_set("session.cookie_lifetime", 3600); and noticed the developer tool then returned an actual value for the expiration time. At 10:33AM it shows a creation date at 9:33AM and an expiration time at... 10:16AM. So, I adjusted the session.cookie_lifetime to 7200 (not optimal, more of a temporarily solution before solving this clock issue). Changed nothing. So, guessing a time ceiling, I set the session.gc_maxlifetime to 7200 and the session.cookie_lifetime to 0. Nothing changed, but I feel close to a solution! – raphaelbadawi Jan 07 '20 at 09:40
  • I made some additionnal tests (like changing my system clock from UTC+1 to UTC) : maybe the problem is totally unrelated to the clock since the browser seems to rely entirely on the server clock, which is intrinsically coherent. So, I may be not that close to a solution :-( – raphaelbadawi Jan 07 '20 at 09:46

1 Answers1

0

Sounds like the cookie issue. With PHP your session ID is kept in a cookie, but cookies can be restricted by it's domain, expiry time (which can be affected by the server and end up being time in the past) and the path. Please make sure those match the new server setup. This is the usual problem with cookies/sessions when migrating

Jan Myszkier
  • 2,517
  • 1
  • 12
  • 22
  • I forgot to mention in the previous post that I also tried to remigrate back the subdomain to the main domain, at the exact subfolder it were before when everything worked fine. No change, it was still broken. So I reverted back to the subdomain. The suggestion is relevant, so I tried to put in my header: `ini_set("session.cookie_lifetime", "3600");` `session_set_cookie_params(0, "/app", "mysubdomain.mydomain.com");` `session_save_path("/__CHV_ROOT_DIR__.'/tmp'");` and created the tmp folder in the subdomain's root Still the same :-( – raphaelbadawi Jan 03 '20 at 10:07
  • open your browser and open the domain. in the browser developer tools check the cookies your site creates. it will show you the cookie with expiry time in the past (if that's actually the problem) otherwise, post your cookie specs – Jan Myszkier Jan 03 '20 at 10:12
  • OK that's really weird it echoes "Session" at the expire line, here's a screen capture: https://postimg.cc/Fk4cs2Gg – raphaelbadawi Jan 03 '20 at 10:17
  • ini_set("session.cookie_lifetime", "3600"); will not be considered if you call the cookie creation explicitly with `setcookie` https://www.php.net/manual/en/function.setcookie.php Is that blog any software that widely available? (like wordpress) would help with code analysis :) – Jan Myszkier Jan 03 '20 at 10:34
  • There is no explicit cookie creation: the little blog uses just sessions. It's not build from an existing piece of software (except Bootstrap and JQuery), it was build from zero to learn procedural PHP :-) – raphaelbadawi Jan 03 '20 at 10:59