0

I need to implement for current project some secure login in php. I wrote something with pdo prepared statements with old code having in mind. I need advices to implement more secure maybe, or to examine is it proof to sql inj, attacks.

 <form action="validate.php" method=post>
    <table class="loginForm">
       <thead></thead>
       <tbody>
          <tr>
            <td>UserName:</td>
            <td><input name=user_name></td>
          </tr>
          <tr>
           <td>Pass:</td>
           <td><input type=password name=password></td>
          </tr>
          <tr>
           <td><input class=loginBtn type=submit value='Log me in' name=login></td>
         </tr>
       </tbody>
    </table>
</form>

Validate.php

session_start();    
try {
    $host = 'localhost';
    $dbName = 'xxx';
    $dbUser = 'xxx';
    $dbPass = 'xxx';
    # MySQL with PDO_MYSQL  
    $DBH = new PDO("mysql:host=$host;dbname=$dbName", $dbUser, $dbPass);
    $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    echo "I'm afraid I can't do that.";
    file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
}

$STH = $DBH->prepare("SELECT * FROM `Admins` WHERE `username` = '$user_name' AND password='$password'");
$STH->execute();

$STH->setFetchMode(PDO::FETCH_ASSOC);
$affected_rows = $STH->fetchColumn();

if($affected_rows == 1) {
    //add the user to our session variables
    $_SESSION['username'] = $user_name;
    header("Location: http://www.mysite.com/administration/index.php");
        exit;
        //print 'allowed';
        }
    else {
        print 'access is not allowed !!!';
    }

Updated: Thanks to accepted answer bellow my query is coded now like this

$STH = $DBH->prepare('SELECT * FROM Admins 
                      WHERE username = :user and password = :pass');
$STH->execute(array(':user' => $_POST['user_name'], 
                    ':pass' => $_POST['password']));

Which is fine. Now I just want to be sure is my authentication is good enough to use it on admin pages like this session_start();

try {
    $host = 'xx';
    $dbName = 'xxxx';
    $dbUser = 'xxxxx_first';
    $dbPass = 'xxx';
    # MySQL with PDO_MYSQL  
    $DBH = new PDO("mysql:host=$host;dbname=$dbName", $dbUser, $dbPass);
    $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    echo "I'm afraid I can't do that.";
    file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
}

if (empty($_SESSION['username'])) {
    die('To access pages you have to be loged in.
    <a href="/administration/login.php">log in</a> ');

}
BobRock
  • 3,337
  • 3
  • 28
  • 47
  • are you using https to send the form to the server? – Gordon Apr 01 '12 at 11:13
  • 1
    maybe this helps http://stackoverflow.com/questions/549/the-definitive-guide-to-forms-based-website-authentication – bescht Apr 01 '12 at 11:16
  • I think you're storing passwords in plain text - you should hash them, say with SHA1. – halfer Apr 01 '12 at 11:40
  • @halfer any code example or link to share – BobRock Apr 01 '12 at 11:43
  • 1
    Set $secret as a site-wide random string. Then store `sha1($username . $password . $secret)` when you do your user `INSERT` and when you retrieve your password, ensure that `sha1($username . $enteredPassword . $secret) == $databasePassword`. – halfer Apr 01 '12 at 12:18
  • Do a search for 'hashed passwords' or 'rainbow tables' if you want to know more. – halfer Apr 01 '12 at 12:19

2 Answers2

1

You can type query like this to avoid Sql Injection

$STH = $DBH->prepare('SELECT * FROM Admins 
                      WHERE username = :user and password = :pass');
$STH->execute(array(':user' => $_POST['user_name'], 
                    ':pass' => $_POST['password']));
safarov
  • 7,573
  • 1
  • 34
  • 51
0

Your code:

$DBH->prepare("SELECT * FROM `Admins` WHERE `username` = '$user_name' AND password='$password'");

Prepared statements (in-and-of-themselves) don't protect against SQL injections. You need to bind the parameters. Check out: http://php.net/manual/en/pdostatement.bindparam.php.

In your example above, SQL injection is entirely possible. I can't see where you define $user_name or $password, so I can't tell for sure whether or not it's safe.

MichaelRushton
  • 10,294
  • 3
  • 38
  • 59