SQL Prepared Statement Error on my Search form - php

I am finding it difficult to write a SQL prepared statement for my search form, can I get help on fixing it? Everything works great without a SQL prepared bind statement but am sure it's not so secure.
Here is my CODE:
<?php
// Define Database connection parameters
$dbserver = "localhost";
$username = "root";
$password = "";
$dbname = "student";
// Lets Connect to theDatabase Table, But if there is an Error lets tell before its too late to figured
$conn = mysqli_connect ( $dbserver, $username, $password, $dbname ) or die ( ' I can not connect to the database ' );
// Its time to Capture the varibles and user inpute from the form , also we need to sanitize the input to avoid SQL Injection
$study_group = mysqli_real_escape_string ( $conn, $_POST['matric_number']);
/* Lets try to use bind Statement to reduce further hacking
I am also avoiding using "LIKE" Clause because IVariable direct Exact results so will be using the Direct Varible
*/
$sql = $conn->prepare (" SELECT * FROM study_circle WHERE matric = ? ") ;
$sql->bind_param('s', $study_group);
$sql ->execute();
$results = mysqli_query ($conn, $sql);
$mysqlResults = mysqli_num_rows ($results);
if ( $mysqlResults > 0 )
{
while ( $row = mysqli_fetch_assoc ( $results ))
{
// Display results in table form
echo " <div>
<h4> ".$row['full_name']."</h4>
</div>";
}
} else {
echo " Please Ensure your Matric Number is correct, We can not find anything relting to your data";
}

if you use prepared statement you should not use mysqli_real_escape_string
Try comment the mysqli_real_escape_string row and use $_POST['matric_number'] directly in bind_param
// $study_group = mysqli_real_escape_string ( $conn, $_POST['matric_number']);
/* Lets try to use bind Statement to reduce further hacking
I am also avoiding using "LIKE" Clause because IVariable direct Exact results so will be using the Direct Varible
*/
$sql = $conn->prepare (" SELECT * FROM study_circle WHERE matric = ? ") ;
$sql->bind_param('s', $_POST['matric_number']);
$sql ->execute();
The binding param and prepared statement prevents SQL injection so you don't need mysqli_real_escape_string operation

Related

How to authenticate users with credentials in MySQL database

On my form page, I have two textboxes with the names name and password.
When the user hits submit, it sends that data into two columns in a MySQL database named 'name' and 'password'.
After the data is recorded (which is the part I understand and don't need help with), I want the user to be at the sign-in page and type in his/her name and password and only be allowed into the site if the name and password data already exist in the database (part that I don't understand).
Would I use the following query :
SELECT * FROM tablename WHERE name & password = "'$_POST[name]', $_POST[password]'
You should use AND or && instead of just a single ampersand (&), and separate the variables to be binded accordingly to their column name.
You should also consider sanitizing your variables before using them to your queries. You can use *_real_escape_string() to prevent SQL injections.
$name = mysql_real_escape_string($_POST["name"]);
$password = mysql_real_escape_string($_POST["password"]);
"SELECT * FROM tablename WHERE name = '".$name."' AND password = '".$password."'"
But the best recommendation that I can give to you is to use prepared statement rather than the deprecated mysql_*
if($stmt = $con->prepare("SELECT * FROM tablename WHERE name = ? AND password = ?")){ /* PREPARE THE QUERY; $con SHOULD BE ESTABLISHED FIRST USING ALSO mysqli */
$stmt->bind_param("ss",$_POST["name"],$_POST["password"]); /* BIND THESE VARIABLES TO YOUR QUERY; s STANDS FOR STRINGS */
$stmt->execute(); /* EXECUTE THE QUERY */
$noofrows = $stmt->num_rows; /* STORE THE NUMBER OF ROW RESULTS */
$stmt->close(); /* CLOSE THE STATEMENT */
} /* CLOSE THE PREPARED STATEMENT */
For securing password, you could also look at password_hash().
Please Always use Prepared statement to execute SQL code with Variable coming from outside your code. Concatenating variable from user input into SQL code is dangerous ( consider SQL injection ), you could use prepared statement with mysqli or PDO ( recommended ).
Mysqli example:
$mysqli = new mysqli("example.com", "user", "password", "database");
// error check you connection here
$query='select * from tablename where user =? AND password=?';
$stmt = $mysqli->prepare($query);
$stmt->bind_param("ss", $user,$password);
$stmt->execute();
if($stmt->num_rows!=1) {
// check failed
}else{
// check success
}
PDO example (recommended )
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
// error check you connection here
$query='select * from tablename where user =? AND password=?';
$stmt = $dbh->prepare($query);
$stmt->bindParam(1,$user);
$stmt->bindParam(2,$password);
$stmt->execute();
if($sth->fetchAll()) {
// check success
}else{
// check failure
}
Additionally you should also consider using some form of 1-way password encryption ( password hashing ) before storing it in your database and compare it to the hash( the most accepted way to do it is using Bcrypt).
You can use something like
SELECT count(*) FROM tablename WHERE name = "'.$_POST[name].' AND password = "'. $_POST[password].'"
You should expect count to be exactly 1 - indicating valid user, 0 - indicating invalid user
Anything greater than 1 should be invalid scenario indicating some kind of inconsistency in your database...
You should assign the variables to name & pass subsequently.
You can try this:
$con = mysqli_connect("localhost","YOURUSER","YOURPASS","YOURDB");
if (mysqli_connect_errno())
{
echo"The Connection was not established" . mysqli_connect_error();
$user
= mysqli_real_escape_string($con,$_POST['user']);
$pass = mysqli_real_escape_string($con,$_POST['password']);
$query = "select * from tablename where user ='$user' AND password='$pass' ";
$run = mysqli_query($con,$query);
$check = mysqli_num_rows($run );
if($check == 0)
{
echo "<script> alert('Password or Email is wrong,try again!')</script>";
}
else
{
//get a session for user
$_SESSION['user']=$user;
// head to index.php; you can just put index.php if you like
echo"<script>window.open('index.php?login=Welcome to Admin Area!','_self')</script>";
}

MySQL query not fetching results (PHP)

I have the following script with an SQL problem which is not working.
<?php
$servername = "localhost";
$username = "root";
$password = "root";
$dbname = "Freepaste";
$conn = mysqli_connect($servername, $username, $password,$dbname);
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
echo "Connected successfully";
$user = $_POST['user'];
$pass = $_POST['pass'];
echo $user." ".$pass;
$stmt = $conn->prepare("SELECT * FROM users where users.username= ? AND users.password = ?");
$stmt->bind_param('ss', $user, $pass);
$stmt->execute();
$result = $stmt->get_result();
printf("Errormessage: %s\n", $mysqli->error);;
if (mysqli_num_rows($result) > 0) {
// output data of each row
while($row = mysqli_fetch_assoc($result)) {
echo "<br>id: " . $row["username"]." Password ".$row["password"]. "<br>";
}
}
else {
echo "<br>0 results <br>";
printf("Errormessage: %s\n", $mysqli->error);
}
mysqli_close($conn);
?>
The statement without the "where" clause gets me all the results, so I know the keys are right. Also, I ran the query in MySQL and it is working fine. I tried adding "" to $user and $pass, still not working. I checked the names in HTML, they are correct too. What am I missing?
Here's the link to the HTML:
http://pastebin.com/CWLuafVq
You are missing the quotes (although you are saying you tried) i think it should have worked. Your query should be:
SELECT * FROM users where users.username='$user' AND users.password='$pass'
Your query is vulnerable to SQL injection and in order to avoid it (and avoid hassle like requiring quotes in SQL statement), you should use PreparedStatement.
For your example, you just need to put single quotes around $user and $pass in the query.
BUT!!!!!! Your query is open to SQL injection. You should change the way you write queries. Use bound parameters instead, then you can almost forget about that issue.
Example:
$stmt = $conn->prepare("SELECT * FROM users where users.username= ? AND users.password = ?");
$stmt->bind_param('ss', $user, $pass);
$stmt->execute();
$result = $stmt->get_result();
See here for more information
As it stands, when your variables are put into the sql query, it ends up looking like this WHERE users.username=goelakash AN.... Without quotes around username and password, mysql is going to think you're comparing two columns.
What your query needs to look like is this.
$sql = "SELECT * FROM users where users.username=\"$user\" AND users.password=\"$pass\"";
Do yourself a huge favor, and put mysqli_error() calls after your calls to mysqli_query(). These will tell you exactly what mysql is crying about.
It is also worth noting that your queries are open to sql injection and you should take a look at prepared statements to mitigate that.
make sure your database password is 'root'? If yes then follow the query string
$sql = "SELECT * FROM users WHERE users.username='$user' AND users.password='$pass'";
just replace it. I think it will work fine :)

How to prevent weird user inputs from breaking things in queries?

Is there a good standard solution to deal with characters like ' and " from being used in user inputs on a web platform?
I'm using php for a webpage and if I have, for example, a search bar which have the following query behind it.
$sql = "select * from aTable where aColumn like '%".$searchedKeyword."%'";
If I search for like Greg's icecream the ' will break the script. Also, I'm guessing if I search for something like 1' or ID>0 my script will have a false effect.
What is the common solution here? Do you usually filter away undesired characters, or is there maybe some method or similiar built-in to php?
You can us PDO and prepared statements to prevent SQL injection.
http://php.net/manual/en/pdo.prepared-statements.php
$searchedKeyword = "mykeyword";
//Database details
$db = 'testdb';
$username = 'username';
$password = 'password';
//Connect to database using PDO (mysql)
try {
$dbh = new PDO('mysql:host=localhost;dbname='.$db, $username, $password);
} catch (PDOException $e) {
var_dump("error: $e");
}
//Prepared SQL with placeholder ":searchedKeyword"
$sql = "select * from aTable where aColumn like '%:searchedKeyword%'";
$sth = $dbh->prepare($sql);
//Bind parameter ":searchedKeyword" to variable $searchedKeyword
$sth->bindParam(':searchedKeyword', $searchedKeyword);
//Execute query
$sth->execute();
//Get results
$result = $sth->fetchAll(); //fetches all results where there's a match

would php code safe from sql inejction without using escape?

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.

how to use mysqli_fetch_array with prepared statements

so everyone told me to use prepared statements, but i have no idea what to do now.
$stmt = mysqli_prepare($con, "SELECT * FROM search WHERE `name2` LIKE '?' AND `approved`='approved'");
mysqli_stmt_bind_param($stmt, 's', $name);
/* execute prepared statement */
mysqli_stmt_execute($stmt);
That is my code, how do i make an array from it like
while ($row=mysqli_fetch_array($result))
from non-prepared
Glad to see you are deciding to use PDO!
//using MySQL
//refer here for reference http://www.php.net/manual/en/ref.pdo-mysql.php
$pdo = new PDO('mysql:host=xxx;port=xxx;dbname=xxx', $username, $password)
//write query
$sql = "SELECT * FROM search WHERE `name2` LIKE '?' AND `approved`='approved'";
//tell query what to replace ? marks with
$fill_array = array($name); // one item in array for the one ? in $sql above
//send query to DB for preparation
$prepare = $pdo->prepare($sql);
//send variables to DB, DB will bind them to the proper place and execute query
$prepare->execute($fill_array);
//get your array. I personally recommend PDO::FETCH_ASSOC but you are using ARRAY
$result = $prepare->fetchAll(PDO::FETCH_ARRAY);
echo '<pre>'.print_r($result, true).'</pre>';
Voila!
Please not that you will have to write code to escape $name and check for things like % signs and underscores because if someone literally types in % then the LIKE statement will return all records where approved='approved'

Categories