I have a html form for the user to login to the website but i want to check if the following query retun true or false, I am using the PDO so I cant use the method mysql_num_rows();
<?php
$view = new stdClass();
$view->login = 'Homepage';
if(isset($_POST['firstName']) && isset($_POST['password']) )
{
$_firstName = $_POST['firstName'];
$password= $_POST['password'];
$user = new UserPassword(); $user->getLogin($_firstName, $passWord);
}
require_once('Views/login.phtml');
public function getLogin($userName,$passWord) {
$sqlQuerys = "SELECT `id`, `username`, `password`, `firstname`, `surename` FROM `sta177users` WHERE username = ' $userName' AND password = '$password'";
echo $sqlQuerys;
$statement = $this->_dbHandle->prepare($sqlQuerys);
$statement->execute();
}
}
You are not actually executing any query. You are setting a variable, but not executing the code.
Also, by building SQL statements with outside variables, you are leaving yourself open to SQL injection attacks. Also, any input data with single quotes in it, like a name of "O'Malley", will blow up your SQL query. Please learn about using parametrized queries, preferably with the PDO module, to protect your web app. My site http://bobby-tables.com/php has examples to get you started, and this question has many examples in detail.
You execute the query and you fetch a row. If the result of that fetch is not empty, you have a valid user.
Very important: You need to salt and hash your passwords and use prepared statements to avoid sql injection.
try this solution
$query="SELECT `id`, `username`, `password`, `firstname`, `surename` FROM `sta177users` WHERE username = ' $_firstName' AND password = '$password'";
$query->execute();
$rows = $query->fetchColumn();
if($rows == 1){
return true;
}else{
return false;
}
You wanna do something like this:
function emptyQuery($db) // assume $db is your PDO object
{
// your prepared sql statement with PDO::prepare()
$sql = $db->prepare("SELECT `id`,
`username`,
`password`,
`firstname`,
`surename`
FROM
`sta177users`
WHERE
username = ' $_firstName'
AND password = '$password'
");
// execute it with PDO::execute()
$sql->execute();
// return all the rows with PDO::fetchAll(), and then see if the array is empty().
return empty($sql->fetchAll());
}
?>
This should implement your specification. You can use count() for a count, etc.
Of course, do not forsake the documentation:
http://us2.php.net/pdo
Hope that helps!
Related
I'm learning to create conditional event where sql checkout data where is exists before inserting data so they don't conflicted.
i've tried using mysql row check in php then check if query empty before i tried to validate the query executed properly.
also trying to close db connection when conditional satisfied but it worthless anyway.
$user = addslashes(strtolower($usr));
$mail = addslashes(strtolower($mail));
$pass = md5(addslashes($pwd));
$check = $db->query("SELECT EXISTS(SELECT *
FROM `users`
WHERE LOWER(`username`) = LOWER('$user')
OR LOWER(`email`) = LOWER('$mail'))");
if (!$check) {
$db->close();
return false;
} else {
$sql = "INSERT IGNORE INTO `users` (`username`, `password`, `email`)
VALUES ('$user', '$pass', '$mail')";
$query = $db->query($sql);
$db->close();
return true;
}
I'm expecting it execute my queries while data was empty and return false while data has been existed.
Your main issue is that $check will always be a truthy value, so long as the query never fails. If the query returns 0 rows, it is still a true object.
You should instead check if there were any values returned. You can also simplify the query quite a bit, given that MySQL is case-insensitive, and you don't need to check if the result exists. Using a prepared statement, the code would look like this
$stmt = $db->prepare("SELECT username FROM users WHERE username = ? OR email = ?");
$stmt->bind_param("ss", $usr, $mail);
$stmt->execute();
$check = $stmt->fetch();
$stmt->close();
// True if the user exists
if ($check) {
return false;
} else {
$stmt = $db->prepare(" INSERT INTO users (username, password, email) VALUES (?, ?, LOWER(?))");
$stmt->bind_param("sss", $usr, $pass, $mail);
$stmt->execute();
$stmt->close();
}
That said, you should not use md5() for passwords - use password_hash() with password_verify() instead.
you can change your code like this
$check = $db->query("SELECT EXISTS(SELECT * FROM `users`
WHERE LOWER(`username`) = LOWER('$user')
OR LOWER(`email`) = LOWER('$mail'))");
$check = $conn->query($sql);
$value = $check->fetch_row()[0];
if($value > 0 ){
echo "existed".$value; // you can change accordingly
}else{
echo "doesn't exist"; // this also
}
Because database respond the query in 1 for exist and 0 for non-exist so the num_row will be always 1 thats why we cant determine the existence with num_row so we have to fetch the value.
Well i learned how to parameterize queries in php but i just wanted to ask that is it now totally secure from sql injection or any other type of attacks and if it isnt what betternment can i do to secure it even more?
<?php
include 'db.php';
$name = "";
$pass = "";
if(isset($_POST['send'])) {
$name = $_POST['name'];
$sql_u = "SELECT * FROM users WHERE username='$name'";
$res_u = $connection->query($sql_u);
if (mysqli_num_rows($res_u) > 0) {
echo "Sorry Username already taken";
}
else {
$password = $_POST['pass'];
$hpass = password_hash($password, PASSWORD_DEFAULT);
$query=$connection->prepare("insert into users (username,password) values (?,?)");
$query->bind_param('ss',$name,$hpass);
if ($query->execute()) {
$query->close();
header('location:index.php');
} else {
header('location:not.php');
}
}
}
I want to know if their is a even more secure way than only parameterizing queries?
You're using parameters for the INSERT statement, but you skipped using parameters for the SELECT statement. Without parameterizing the SELECT, you still have an SQL injection vulnerability. You need to use parameters in all cases when you combine untrusted content with your SQL.
Parameters are a good way to prevent SQL injection when combining dynamic content as values in your SQL queries.
You asked if there were another way, so I will recommend that you use PDO if you're starting out with a new PHP project. It's a little bit easier than Mysqli. In my opinion, there's no reason to use Mysqli unless you're porting a legacy PHP application that had used the deprecated Mysql PHP extension.
Here's what it would look like using PDO:
$name = $_POST['name'];
$sql = "SELECT COUNT(*) FROM users WHERE username = ?";
$query = $connection->prepare($sql);
$query->execute([$name]);
$count = $query->fetchColumn();
if ($count > 0) {
echo "Sorry Username already taken";
}
else {
$password = $_POST['pass'];
$hpass = password_hash($password, PASSWORD_DEFAULT);
$sql = "insert into users (username, password) values (?, ?)";
$query = $connection->prepare($sql);
if ($query->execute([$name, $hpass])) {
header('location:index.php');
} else {
header('location:not.php');
}
}
I'm assuming that the PDO connection was made previously, and that it had been enabled with exceptions. If you don't enable exceptions, you should check return values from every prepare() and execute() call to make sure there are no errors.
The same is true for Mysqli, you can enable exceptions so you don't have to check for errors manually.
I also show in the example my preference to use SELECT COUNT(*) instead of SELECT *. It's probably a trivial optimization in this case, but if * refers to many columns or there are many rows matching username = $name then the fetch will need to transfer less data from the database.
I've got an HTML form into which a user can enter an SQL query.
The query needs to be entered into a field of my MYSql database. But for complex queries that include % _ , ; ' " $ < > etc... it fails.
How would i go about entering this info into the DB without error?
I know the below is not a very secure way to do it, for now, I just need it to work :)
// Get values from form
$username = $_SESSION['user'];
$appname = $_POST['appname'];
$sql2 = $_POST['sql'];
// Insert data into mysql
$sqlquery="INSERT INTO puresql (username,appnm, query)VALUES('$username','$appname', '$sql2')";
$result=mysqli_query($dbconn,$sqlquery);
For anyone else with this issue. the below works, using mysqli_real_escape_string
$date = date("Y/m/d");
echo "$date";
$appname = mysqli_real_escape_string($dbconn, $_POST['appname']);
$sql2 = mysqli_real_escape_string($dbconn, $_POST['sql']);
$username = mysqli_real_escape_string($dbconn, $_SESSION['user']);
// Insert data into mysql
$sqlquery="INSERT INTO livepurespark (username,appnm, query, date)VALUES('$username','$appname', '$sql2', '$date')";
$result=mysqli_query($dbconn,$sqlquery);
Another way of saving complex texts in database fields with added benefit of protection from sql injection is by using parameterized query statements (Prepared Statements).
$username = $_SESSION['user'];
$appname = $_POST['appname'];
$sql2 = $_POST['sql'];
$stmt = mysqli_prepare($dbconn, "INSERT INTO puresql (username,appnm, query)VALUES('?','?','?')");
mysqli_stmt_bind_param($stmt, "sss", $username, $appname, $sql2);
mysqli_stmt_execute($stmt);
bellow is my code.Error shown is like
fatal error: call to undefined function execute() on line 21,
how could i solve this problem?
<?php
include 'config/dbconfig.php';
include 'lib/function.php';
include 'helper/helper.php';
$db = new rootfunc();
$fm = new formate();
if(!empty($_POST['name']) or !empty($_POST['email']) or !empty($_POST['password1']) or !empty($_POST['dob']) or !empty($_POST['gender']) ){
$name = $fm->validation($_POST['name']);
$email = $fm->validation($_POST['email']);
$password = $fm->validation($_POST['password1']);
$dob = $_POST['dob'];
$gender = $fm->validation($_POST['gender']);
$query = $pdo->prepare("SELECT * FROM user_table WHERE name = ? AND email = ?");
$query = execute(array($name,$email));
$numRow = $query->rowCount();
if(!$numRow){
$query = "INSERT INTO user_table (name,email,password,dob,gender) VALUES (?,?,?,?,?)";
$query = $pdo->prepare($query);
$query->execute(array($name,$email,$password,$dob,$gender));
echo "Congrates, please login..";
}else{
echo "name and email exist..";
}
}
?>
In both cases you are overwriting $query:
$query = "INSERT INTO user_table (name,email,password,dob,gender) VALUES (?,?,?,?,?)";
$query = $pdo->prepare($query);
You need to give the execution a different variable to hold the object, for example:
$query = "INSERT INTO user_table (name,email,password,dob,gender) VALUES (?,?,?,?,?)";
$result = $pdo->prepare($query);
$result->execute(array($name,$email,$password,$dob,$gender));
In addition you should allow users to use the passwords / phrases they desire. Don't limit passwords.
While you're working with passwords never store them as plain text! Please use PHP's built-in functions to handle password security. If you're using a PHP version less than 5.5 you can use the password_hash() compatibility pack. Make sure that you don't escape passwords or use any other cleansing mechanism on them before hashing. Doing so changes the password and causes unnecessary additional coding.
I also noticed this in your code
$numRow = $query->rowCount();
Since the query is a SELECT query it will not work with rowCount()
From the docs:
PDOStatement::rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement executed by the corresponding PDOStatement object.
For SELECT when you are not doing a COUNT() query you can return the number of rows like this after you execute the query;
$rows = $result->fetchAll();
$num_rows = count($rows);
In your case it is not necessary to check the count though - just check to make sure the query executed which is enough to get into your conditional statements.
public function fetchUserData( $username, $noUpdate = false ) {
if ( DEBUG ) echo "DBInterface::fetchUserData( '$username' )\n";
$query = "SELECT * FROM logins WHERE username = '$username'";
$result = mysql_db_query( $this->database, $query, $this->dbc );
if ( $result && !$noUpdate ) {
mysql_db_query( $this->database, "UPDATE logins SET last_accessed = CURRENT_TIMESTAMP WHERE username = '$username' ", $this->dbc );
}
return $this->userData = mysql_fetch_assoc( $result );
}
public function verifyLogin( $username = null, $password = null ) {
if ( DEBUG ) echo "DBInterface::verifyLogin( '$username', '$password' )\n";
$success = ( $username && $password
&& $this->fetchUserData( $username )
&& $this->userData['password'] == $this->md5_base64( $password )
&& $this->setLoggedIn()
);
return $success;
}
Obviously, there's no escape function, so one might insert as ' or '1'='1 to make WHERE clause true, and fetchUserData will return all rows from the table. But verfiyLogin checks user input password with the query result from database which may not be same, hence authentication will fail. Attacker also cannot modify table since mysql_db_query executes only single sql statement. Am I right? Any thoughts?
Yes, it's very possible to do SQL injection with any SQL query that's built from user input.
You should use the escaping functions, or preferentially prepared statements to protect yourself from SQL injection. However, you can't use prepared statements if you're using the outdated and deprecated mysql_* functions. You need to switch to mysqli or PDO.
PDO example:
$myPDO = new PDO ('Connection options go here');
$stmt = $myPDO -> prepare ("SELECT * FROM table WHERE rowID = :rowID");
if ($stmt -> execute (array ('rowID' = $inputFromUntrustedSource))) {
while ($row = $stmt -> fetch ()) {
// do stuff with $row here
}
}
You can inject your own data into the result set using the UNION operation. So an attacker could supply his own $this->userData['password'] value that would be equal to the $this->md5_base64($password) value, for example:
' UNION SELECT 'admin', 'X03MO1qnZdYdgyfeuILPmQ==
So you should absolutely make sure you pass the values properly to your query.
Data validation is often confused with SQL formatting. This "escaping" you are talking about (whatever you mean under this vague term) belongs not to "injection" but to mere formatting. You need to escape strings not because of injections but because of string delimiters and some other reasons.
Data validation rules may change. SQL formatting rules are constant. You have to format any data you put in SQL string. Whatever you did to this data prior constructing the query - doesn't matter.