I have inherited an old php based website that keeps getting hacked. Per the information I found here: How can I prevent SQL injection in PHP?,
I updated the sql queries using PDO parameterized queries. We got hacked last week again and it looked like a sql injection attack.
All of the usernames were deleted from the user table and replaced with their own information. Then the hackers were able to get into the admin section of the
site and create all sorts of havoc.
How could this have happened with a parameterized query?
See my code below - what am I missing? I'm going to change the permissions of my db login used for this query so that only selects are allowed, but I really want to know why the query is vulnerable.
class pdoConnection
{
var $conn;
function pdoConnection()
{
$this->createConnection();
}
function createConnection()
{
try
{
$dbConnection = new PDO('mysql:host=mysqlhostname.com;dbname=mydbname;charset=utf8',
'dbusername', 'dbpassword',
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbConnection -> exec('SET NAMES utf8');
$dbConnection -> exec('SET CHARACTER SET utf8');
$this->conn =$dbConnection;
}
catch(PDOException $e)
{
die('Could not connect: ' .$e->getMessage(). "<br><br>");
}
}
// GET CONNECTION
// ---------------------------------------------------------------------
function getConnection()
{
return $this->conn;
}
}
$login = htmlspecialchars($_REQUEST['login'], ENT_QUOTES, 'UTF-8');
$pass = htmlspecialchars($_REQUEST['pass'], ENT_QUOTES, 'UTF-8');
$msg = '';
//check to see if there is a value
if($login == '' || $pass == '') {
$error = 1;
$msg = "Please enter a username and password.<br />";
}
else
{
//try to validate
$clsPDO = new pdoConnection();
$con = $clsPDO->getConnection();
$stmt = $con->prepare('SELECT * FROM users where userName = :login');
$stmt->execute(array(':login' => $login)) or die($con->errorInfo());
$row = $stmt->fetch();
if (isset($row))
{
if( $pass == $row['userPassword']) {
$required_login = $row['userName'];
$required_pass = $row['userPassword'];
$userLevel = $row['userLevelID'];
$userName = $row['userName'];
$userID = $row['userID'];
}
else
{
$error = 1;
$msg = "Your username/password did not match. Please check your entries and try again.";
}
}
else
{
//did not validate
$error = 1;
$msg = "Your username/password did not match. Please check your entries and try again.";
}
}