-1

Good morning all,

I recently made a post on this website regarding a login page for a website. It was pointed out to me that I was very vulnerable to an SQL injection. I have spent the past weekend researching into SQL injections and I am getting a bit of a better idea about how they function, however I am still very new to PHP (I taught myself the basics in a day). I was wondering if anyone could help me with my code please.

I have read every link that people posted and researched it till my head exploded (no need to edit, its not literal), but I am still struggling as to the code itself.

Here is my code:

<?php
    session_start();
    // dBase file
    include "dbConfig.php";

    if ($_GET["op"] == "login")
    {
       if (!$_POST["username"] || !$_POST["password"])
       {
         die("You need to provide a username and password.");
       }

       // Create query
       $q = "SELECT * FROM `dbusers` "
       ."WHERE `username`='".$_POST["username"]."' "
       ."AND `password`=PASSWORD('".$_POST["password"]."') "
       ."LIMIT 1";
       // Run query
       $r = mysql_query($q);

      if ( $obj = @mysql_fetch_object($r) )
      {
        // Login good, create session variables
        $_SESSION["valid_id"] = $obj->id;
        $_SESSION["valid_user"] = $_POST["username"];
        $_SESSION["valid_time"] = time();

        // Redirect to member page
        Header("Location: members.php");
      }
      else
      {
        // Login not successful
        die("Sorry, could not log you in. Wrong login information.");
      }
   }
   else
   {
    //If all went right the Web form appears and users can log in
    echo "<form action=\"?op=login\" method=\"POST\">";
    echo "Username: <input name=\"username\" size=\"15\"><br />";
    echo "Password: <input type=\"password\" name=\"password\" size=\"8\"><br />";
    echo "<input type=\"submit\" value=\"Login\">";
    echo "</form>";
   }
 ?>

Now I know it needs validation AND sanitisation in PDO, am just struggling as to what to actually write in my code. I am hoping that someone could help rather than just link me to another page please

as an edit, if anyone has a link to a tutorial about logins which are SQLinjection safe that could help me/other people looking to protect against that would be much appreciated. Thanks

Marriott81
  • 275
  • 2
  • 16
  • I am asking about my code in specific not their code tho – Marriott81 Jan 13 '14 at 10:48
  • 1
    If you can't *even attempt* to apply the techniques described in the answers to that question, then you should probably hire a freelancer. Stackoverflow is not a code writing service. – Quentin Jan 13 '14 at 10:49
  • 1
    You are using [an unsuitable hashing algorithm](http://php.net/manual/en/faq.passwords.php) (in this case "no hashing algorithm at all) and need to [take better care](https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet) of your users' passwords. – Quentin Jan 13 '14 at 10:51
  • thank you, I realise that and will be include MD5 hash on the finished script. Also if I wanted to hire a freelancer I would have gone and done so, I know stackover flow is not a writing service, but if you notice none of the answers have done that, they all just posted things that I should be looking at in my code. – Marriott81 Jan 13 '14 at 11:01
  • 1
    Regarding your MD5 plan, read http://stackoverflow.com/questions/401656/secure-hash-and-salt-for-php-passwords – Markus Malkusch Jan 13 '14 at 11:05
  • Thanks Markus, will look into alternatives – Marriott81 Jan 13 '14 at 11:12
  • Well I'm sorry, but I posted you a solution depending on your code in mysqli? I explained each step. – Maarkoize Jan 13 '14 at 11:12
  • You did Marcel and I voted you as answer, cheers mate – Marriott81 Jan 13 '14 at 11:13

4 Answers4

1

Well you can use PDO or mysqli. The most interesting point is that you can use prepared statements with both.

If you used mysql before, as in your code, then mysqli is easier to understand for you.

The manual page of PHP has good examples for mysqli with prepared statements.

First of all you need a mysqli connection:

$mysqli = new mysqli("host", "user", "password", "database");

When you got your query, replace all external inputs with a ?.

$q = "SELECT * FROM `dbusers` "
       ."WHERE `username`=? "
       ."AND `password`=PASSWORD(?) "
       ."LIMIT 1";

And create a prepared statement:

$stmt = $mysqli->prepare($q);

Then you can easily bind your params. Because in your case both are strings, you have to use a s for each param.

$mysqli->bind_param('ss', $_POST['username'], $_POST['password']);

And then just execute the statement:

$stmt->execute();

With methods like fetch() you can get the result(s).

Maarkoize
  • 2,601
  • 2
  • 16
  • 34
0

As you're using the old mysql_* API, you could just use the mysql_real_escape_string function which does exactly what you need.

Use it like this :

    $q = "SELECT * FROM `dbusers` "
   ."WHERE `username`='".mysql_real_escape_string($_POST["username"])."' "
   ."AND `password`=PASSWORD('".mysql_real_escape_string($_POST["password"])."') "
   ."LIMIT 1";
Rom11
  • 33
  • 3
0

try this function to pass every POST variable

function mysql_string($str)
{
$str = stripslashes($str);
$str = mysql_real_escape_string($str);
return $str;
}

now use it as follows

$username = mysql_string($_POST["username"]);
$password = mysql_string($_POST["password"]);

$q = "SELECT * FROM `dbusers` "
       ."WHERE `username`='".$username."' "
       ."AND `password`=PASSWORD('".$password."') "
       ."LIMIT 1";

no use $username in your query to prevent mysql injection

Satish Sharma
  • 9,547
  • 6
  • 29
  • 51
0

Just as an example here is a PDO INSERT statement

$dbHost = "";
$dbName = "";
$dbUser = "";
$dbPass = "";

$dsn = 'mysql:host=' . $dbHost . ';dbname=' . $dbName;
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);

try {
$dbh = new PDO($dsn, $dbUser, $dbPass, $options);
$db = $dbh->prepare('INSERT INTO db_table (column_one, column_two, column_three)
VALUES (:column_one, :column_two, :column_three)');
$db->bindParam(':column_one', $dataForColumnOne);
$db->bindParam(':column_two', $dataForColumnTwo);
$db->bindParam(':column_three', $dataForColumnThree);
$db->execute();
} catch (PDOException $e) {
echo $e->getMessage();
}

An example here is a PDO multiple row fetch statement

try {
$dbh = new PDO($dsn, $dbUser, $dbPass, $options);
$db = $dbh->prepare('SELECT * FROM db_table');
$db->execute();
$rows = $db->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
print_r($row);
}
} catch (PDOException $e) {
echo $e->getMessage();
}

As a rule never trust user input, Notice that the data is added via "->bindParam" and not directly inserted into the "->prepare" statement

Please refer to PHP PDO

Pwner
  • 791
  • 5
  • 16