PHP – Is $_SESSION[] a reliable way to secure php content?

I’ve tried to be as specific as possible, but I’m sorry that the subject of my question may be broad.

I got used to a habit of sending variables using the $_GET[‘variable’], for instance, let’s say I’m using ajax to get some information from a database, I would probably do something like this:

xmlhttp.open(“GET”,”read.php?option=someoption”,true);

And then I would set the PHP page in a way that behave differently according to the $_GET[‘option’] it would receive.
I then realised that any logged-in user could type the URL and directly modify the database, so I’ve set some additional $_SESSION[‘redirect’] variables before each redirection to help prevent access to php pages from URL. By doing a quick ajax call to a “prevent.php” page that would do something like so:

$_SESSION['redirect'] = "true";
header("Location: page.php");

And then having it set this way in the page.php for instance:

if ($_SESSION['redirect']==true) {
    // access the database
}
else {
   // deny access
} 

Is this a reliable way of doing things, or is there a more professional way to sort it out?

No it’s not a secure way of doing it.

Here’s an example of how you could achieve a secure user system in the simplest of forms:

login.php

<?php
session_start();

$user = isset($_POST['username']) ? $_POST['username'] : false;
$pass = isset($_POST['password']) ? $_POST['password'] : false; 

# Check credentials
if (validCredentials($user, $pass)) {
    # Credentials are valid

    # Set isAdmin session for the user 'admin'
    # This is hardcoded for simplicity but 
    # you could read a value from a database
    # and set this session dynamically.
    if ($user === 'admin') {
        $_SESSION['isAdmin'] = true;
    }

    # Generate CSRF token (see appendix)
    # heads up: random_bytes() is a PHP7 function.
    $_SESSION['token'] = bin2hex(random_bytes(32));

    # Set logged in session for every user
    $_SESSION['user'] = $user;

    echo 'Successfully logged in!<br />';
    echo '<a target="_blank" rel="nofollow" href="user-page.php">Go to the user page.</a>';
}

admin-page.php:

<?php
session_start();

if (isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true) {
    echo 'Only the admin can see this.';
} else {
    echo 'You are either not logged in or you don/'t have the permission to view this page.';
}

user-page.php:

<?php
session_start();

if (isset($_SESSION['user'])) {
    $token = $_SESSION['token'];

    echo 'Only logged in users can see this. <br />';
    echo '<a target="_blank" rel="nofollow" href="safe-logout.php?token='.$token.'">Log me out</a>.';
} else {
    echo 'You are not logged in.';
}

Appendix:

Make sure that you protect yourself against CSRF attacks:

For example an insecure way of logging an user out would be:

logout.php:

<?php
session_start();

if (isset($_SESSION['user'])) {
    session_destroy();
}

Maybe you ask yourself why this is not secure.

The reason is because for every user the logout link is the same (example.com/logout.php).

So it’s not hard at all to guess the logout link (well, we don’t even have to guess, we already know for sure).

An attacker could disguise the logout link and as soon as you click on it you would be logged out.

It’s very important to understand that the logout is just one example.

Think of a more severe action like deleting a user etc.

So this concept applies to every action an authenticated user can do.

To be safe, you can generate a token as soon as the user has logged in.

For every action taken you then check if the token in the request matches the one you generated.

This way the logout link is unique for every user (example.com/loogut.php?token=random_token_generated_at_login) and is only hardly guessable by an attacker.

safe-logout.php:

<?php
session_start();

if (isset($_SESSION['user'])) {
    # Check if the user specified token matches ours
    $token = isset($_GET['token']) ? $_GET['token'] : false;

    if ($_SESSION['token'] === $token) {
        session_destroy();

        echo 'Successfully logged out!';
    } else {
        # We dont logout because the token was not valid
    }
}

And NO: a POST request is just as susceptible as a GET request.

So make sure you check the token for every action, regardless of the HTTP method used.