Secured registration script I created code for my registration form on my social network. I want to know if it is secured enough to release on the web as a public social network. Also, all of the code works. I just want to make sure it's all secure.

registration.php:

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

//check if form is submitted
if ( $_SERVER['REQUEST_METHOD'] != 'POST' || ! isset($_POST['Register'])) 
{
// looks like a hack, send to index.php
header('Location: index.php');
die();
}

include("connect.php");

            if(isset($_POST['Register'])) {

               if (empty($_POST["username"])) {
                echo"Fill in username to sign up";
                } else {

                if (empty($_POST["pw"])) {
                 echo"Fill in password to sign up";
                } else {

                if (empty($_POST["pw2"])) {
                echo"Confirm password to sign up";
                 } else {

                if (empty($_POST["email"])) {
                     echo"Fill in email to sign up";
                 } else {

                if ($_POST['pw'] == $_POST['pw2']) {
                 $username = mysqli_real_escape_string($conn, $_POST["username"]);
                 $pw= mysqli_real_escape_string($conn, $_POST["pw"]);
                 $pw2= mysqli_real_escape_string($conn, $_POST["pw2"]);
                 $email = mysqli_real_escape_string($conn, $_POST["email"]);

                 $result = mysqli_query($conn ,"SELECT * FROM users WHERE username='" . $username . "'");

                    if(mysqli_num_rows($result) &gt; 0)
                    {
                    echo "Username exists . &lt;a href= index.php&gt;Try again&lt;/a&gt;&lt;br /&gt; ";
                    } else {

                       $result2 = mysqli_query($conn ,"SELECT * FROM users WHERE email='" . $email. "'");

                       if(mysqli_num_rows($result2) &gt; 0)
                       {
                       echo "Email exist.  &lt;a href= index.php&gt;Try again&lt;/a&gt;&lt;br /&gt; ";
                       } else {

                       $pw = password_hash($pw, PASSWORD_BCRYPT, array('cost' =&gt; 14));          

                       $stmt = $conn-&gt;prepare("INSERT INTO users (username, pw, email) VALUES(?, ?, ?)");
                       $stmt-&gt;bind_param("sss", $username, $pw, $email);

                      $username = $username;
                      $pw = $pw;
                      $email = $email;
                      $stmt-&gt;execute();

                      echo"Registration successful &lt;a href= index.php&gt;Login here&lt;/a&gt;&lt;br /&gt;";


                    } } } else{
            echo "The passwords do not match.";  // and send them back to registration page
            }
}
}}}}


login.php:

error_reporting(E_ALL);
ini_set('display_errors', 1);

include("connect.php");

$_SESSION['username'] = $_POST['username'];

//check if form is submitted
if ( $_SERVER['REQUEST_METHOD'] != 'POST' || ! isset($_POST['signin'])) 
{
// looks like a hack, send to index.php
header('Location: index.php');
die();
}

if (empty($_POST["username"])) {
echo 'Fill in username to sign in. &lt;a href= index.php&gt;Try again&lt;/a&gt;&lt;br /&gt;';
die();
}

if (empty($_POST["pw"])) {
echo 'Fill in password to sign in. &lt;a href= index.php&gt;Try again&lt;/a&gt;&lt;br /&gt;';
die();
}

$sql = "SELECT pw FROM users WHERE username = ?";
$stmt = mysqli_prepare($conn, $sql);
if ( !$stmt ) {
echo mysqli_error($conn);
die();
}

$stmt-&gt;bind_param('s', $_POST['username']);
if ( !$stmt-&gt;execute() ) {
echo mysqli_error($conn);
die();
}
// we found a row with that username, 
// now we need to check the password is correct

// get the password from the row
$stmt-&gt;bind_result($hashed_pwd);
$stmt-&gt;fetch();

if ( password_verify($_POST['pw'], $hashed_pwd) ) {
// password verified
$_SESSION["username"] = $_POST['username'];
header('Location: profile.php');
} else {
echo 'Incorrect username or Password. &lt;a href= index.php&gt;Try again&lt;/a&gt;&lt;br /&gt;';
}
Correctness


  Also, all of the code works.


No, it doesn't, so let's start with that.


                 $username = mysqli_real_escape_string($conn, $_POST["username"]);

  
  ...

                 $result = mysqli_query($conn ,"SELECT * FROM users WHERE username='" . $username . "'");

                    if(mysqli_num_rows($result) &gt; 0)
                    {
                    echo "Username exists . &lt;a href= index.php&gt;Try again&lt;/a&gt;&lt;br /&gt; ";
                    } else {

  
  ...

                       $stmt = $conn-&gt;prepare("INSERT INTO users (username, pw, email) VALUES(?, ?, ?)");
                       $stmt-&gt;bind_param("sss", $username, $pw, $email);

                      $username = $username;
                      $pw = $pw;
                      $email = $email;
                      $stmt-&gt;execute();



If the supplied username is such that mysqli_real_escape_string is not a no-op, the check for an existing user and the insertion of the user use different usernames. This is an important bug. Quite how important depends on things you haven't shown us, in particular on the database schema.

Given the current mix of database access techniques, you should ditch the one which requires you to escape things yourself (dangerous, because it's easy to forget when you change the code) and use prepared statements for everything.



I also struggle to see how this can possibly work:


//check if form is submitted
if ( $_SERVER['REQUEST_METHOD'] != 'POST' || ! isset($_POST['Register'])) 
{
// looks like a hack, send to index.php
header('Location: index.php');
die();
}

  
  ...

                    } } } else{
            echo "The passwords do not match.";  // and send them back to registration page



If registration.php is the registration page then (a) it seems rather lacking in content; and (b) there seems to be a catch-22 with rendering it for the first time in order to submit data.



Maintainability

Maintainability is important in its own right, but also particularly relevant to  security because unmaintainable code is more likely to acquire bugs over time.

Fix the indentation. It currently appears to be at random, and is completely unreadable.



Avoid massive chains of if statements. The various checks here would be better refactored into a function which can take advantage of early return.



Avoid pointless code such as


                      $username = $username;
                      $pw = $pw;
                      $email = $email;





Security

This code leaks far too much information to a malicious caller.


ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);



is absolutely not something you want to do on a production system unless you're also using set_error_handler to log it to somewhere private and ensure that the end user never sees the error messages.

Similarly


echo mysqli_error($conn);





The registration form asks for an e-mail address. Why? If you don't use it, don't ask for it. If you do use it, does your security model not require it to be correct? So shouldn't there be an e-mail validation step in the registration process?