0

I'm making a website and I want to prevent SQL injections from happening. I have code that takes the POST data, makes a MYSQL query to check it. It then runs the mysqli_num_rows() function and then it does a password_verify().

Here is my code:

<?php
$Username = $_POST['Username'];
$Password = $_POST['Password'];
$Connect = mysqli_connect('localhost', 'user', 'pass', 'DB');
$sql = "SELECT * FROM table WHERE Username = '$Username'";
$output = mysqli_query($Connect, $sql);
if (mysqli_num_rows($output) > 0) {
    while($row = mysqli_fetch_assoc($output)) {
        if (password_verify($Password, $row['Password'])) {
            $_SESSION = $row;
            header('Location: Account.php');
        } else {
            echo 'Invalid Username or Password';
        }
    }
} else {
    echo 'Invalid Username or Password';
}

?>

I was wondering if there is any way to bypass the password_verify() function with an SQL injection?

Thanks

Nick Evans
  • 23
  • 6

2 Answers2

0

I was wondering if there is any way to bypass the password_verify() function with an SQL injection?

Yes, after a fashion. It is possible to inject crafted data into the results of the query using an input along the lines of:

$Username = "' UNION SELECT 1, 'username', 'fake password hash', …, '";

resulting in the query

SELECT * FROM table WHERE username = ''
UNION SELECT 1, 'username', 'fake password hash', …, ''

This can be used to inject a fake row containing results with a password hash whose password is known to the attacker.

password_verify() does not protect you against SQL injection. Use prepared statements.

0

Your code is somewhat suspect. Why would you allow duplicate usernames? This may seem like a comment, but its rather important to the question you asked. The code you've shown us is vulnerable to injection. and only fixing the problem if you know that it can be exploitable is not the right approach.

In addition to the brute forcing a check of every password stored in your database by submitting anything' OR 'A'='A the attacker could send a username and chosen hashed password in a UNION - consider:

 SELECT * FROM table 
 WHERE Username = 'xxx'
 UNION SELECT 'root' AS username, 
 '$6$ErsDojKr$7wXeObXJSXeSRzCWFi0ANfqTPndUGlEp0y1NkhzVl5lWaLibhkEucBklU6j43/JeUPEtLlpRFsFcSOqtEfqRe0' 
 AS Password'

While properly escaping the data, either using mysqli_real_escape_string() or parameter binding fixes both issues, you still should ensure that your usernames are unique and only test one row maximum for each authetnication attempt.

symcbean
  • 47,736
  • 6
  • 59
  • 94