I have a website that uses a db to store information for site users. All the mysql db calls are SELECT. I use $_GET to pass variables from page to page that are then used in the mysql SELECT calls. I don't use UPDATE or INSERT in any of my code.
Do I have to worry about sql injection attacks?
Do I have to protect the db from some other type of attack?
I'm willing to read and learn. I just don't know if it's necessary in this case.
My db queries all take the form of:
$leadstory = "-1";
if (isset($_GET['leadstory'])) {
$leadstory = $_GET['leadstory'];
}
$query_News = "SELECT * FROM news WHERE lead_story = $leadstory";
$News = mysql_query($query_News, $HDAdave) or die(mysql_error());
$row_News = mysql_fetch_assoc($News);
$totalRows_News = mysql_num_rows($News);
Are the first three lines replaced with:
$statement = $db_connection->prepare("SELECT * FROM news WHERE lead_story = ?;';");
$statement->bind_param("s", $leadstory);
$statement->execute();
$row_News = $statement->fetchAll();
What is the replacement for $totalRows_News?
Do I also have to clean the $leadstory?
Thanks for your help.
That would a be "yes", I think.
SELECT * FROM users WHERE name='hacker' or name='Admin' and '1'='1'
With the supplied name being hacker' or name='Admin' and '1'='1
Yes, you do have to worry about SQL injection attacks.
Use PDO and prepared statements to protect your queries.
$stmt = $pdo->prepare('SELECT * FROM table WHERE id = ?');
$stmt->bindParam(1, $_GET['id']);
$stmt->execute();
$rows = $stmt->fetchAll();
Simple answer, yes. If any part of your sql statement comes from a request or form submission by the client, you need to sanitize/escape it.
Use PDO and prepared statements, or mysql_real_escape_string()
Related
This is my first time to try PDO and still learning it. I am more familiar in using mysql or mysqli in developing php system.
After deep searching and searching I still can't seem to understand how to query using PDO
In my code I used mysqli inside a function to be called in index.php
function getUsery(){
$ip = getIPAddress();
$query = mysqli_query("select userID from tblUsers where logged='1' AND ip='$ip'");
$row = mysqli_fetch_array($query);
$emp = $row['userID'];
$logged = $row['logged'];
$userlvl = $row['userLevel'];
$_SESSION['logged'] = $logged;
$_SESSION['userLevel'] = $userlvl;
return $emp;
}
I don't really know how to select sql query using PDO with 'where' statement. Most of what I found is using array with no 'where' statement
How can I select the userID where logged is equal to '1' and ip is equal to the computer's ip address and return and display the result to the index.php
There's SQL statement with WHERE in PDO
$sql = "SELECT * FROM Users
WHERE userID = ?";
$result = $pdo->prepare($sql);
$result->execute([$id]);
Assuming that you know how to connect database using PDO, here is how to select SQL with PDO.
$stmt = $db->prepare("select userID from tblUsers where logged = '1' AND ip = :ip");
$stmt->execute(array('ip' => $ip));
$listArray = $stmt->fetchAll();
Notice the :ip at the end of SELECT. If you don't use ? as a parameters, the prefix : is mandatory and the word after that should be the same as the key in the execute function.
EDIT
In case that the above code is inside the function and $db is outside the function, declare $db as global variable inside the function.
This one is imo one of best guides on PDO and how to use it:
https://phpdelusions.net/pdo
WHERE is a part of query and queries in PDO are not much different from pure *sql queries, just there is going on a bit filtering on execution. Read the guide carefully and you will be able to execute any query you need to.
I have this code for selecting fname from the latest record on the user table.
$mysqli = new mysqli(HOST, USER, PASSWORD, DATABASE);
$sdt=$mysqli->('SELECT fname FROM user ORDER BY id DESC LIMIT 1');
$sdt->bind_result($code);
$sdt->fetch();
echo $code ;
I used prepared statement with bind_param earlier, but for now in the above code for first time I want to use prepared statement without binding parameters and I do not know how to select from table without using bind_param(). How to do that?
If, like in your case, there is nothing to bind, then just use query()
$res = $mysqli->query('SELECT fname FROM user ORDER BY id DESC LIMIT 1');
$fname = $res->fetch_row()[0] ?? false;
But if even a single variable is going to be used in the query, then you must substitute it with a placeholder and therefore prepare your query.
However, in 2022 and beyond, (starting PHP 8.1) you can indeed skip bind_param even for a prepared query, sending variables directly to execute(), in the form of array:
$query = "SELECT * FROM `customers` WHERE `Customer_ID`=?";
$stmt = $db->prepare($query);
$stmt->execute([$_POST['ID']]);
$result = $stmt->get_result();
$row = $result->fetch_assoc();
The answer ticked is open to SQL injection. What is the point of using a prepared statement and not correctly preparing the data. You should never just put a string in the query line. The point of a prepared statement is that it is prepared. Here is one example
$query = "SELECT `Customer_ID`,`CompanyName` FROM `customers` WHERE `Customer_ID`=?";
$stmt = $db->prepare($query);
$stmt->bind_param('i',$_POST['ID']);
$stmt->execute();
$stmt->bind_result($id,$CompanyName);
In Raffi's code you should do this
$bla = $_POST['something'];
$mysqli = new mysqli(HOST, USER, PASSWORD, DATABASE);
$stmt = $mysqli->prepare("SELECT `fname` FROM `user` WHERE `bla` = ? ORDER BY `id` DESC LIMIT 1");
$stmt->bind_param('s',$_POST['something']);
$stmt->execute();
$stmt->bind_result($code);
$stmt->fetch();
echo $code;
Please be aware I don't know if your post data is a string or an integer. If it was an integer you would put
$stmt->bind_param('i',$_POST['something']);
instead. I know you were saying without bind param, but trust me that is really really bad if you are taking in input from a page, and not preparing it correctly first.
I am trying to sanitize my $_GET input but for some reason, mysql doesn't retrieve the data from the DB. If I do this:
$user = mysqli_real_escape_string($connection, $_GET['id']);
//execute query to call user info
$query = "SELECT user
FROM company
WHERE user={$_GET['id']} ";
this will work and the results are displayed; however if I do this:
$user = mysqli_real_escape_string($connection, $_GET['id']);
//execute query to call user info
$query = "SELECT user
FROM company
WHERE user= '$user' ";
I don't get a database error, but nothing shows up.
Am I not sanitizing right? What's going on here? HELP, please!
Best way to avoid such situations is using prepared queries:
How can I prevent SQL injection in PHP?
It's very simple and effective:
$q = $db->prepare('SELECT user FROM company WHERE user=?');
$q->bind_param('i', $user);
$q->execute();
$result = $q->get_result();
while ($row = $result->fetch_assoc()) {
// do something with $row
}
It's cool because it's OOP and it's safe. Some links:
Connection to DB
Prepare statement
Bind parameters
I'm trying to sanitize a string going into my database. But with the code below, I don't get the update to my db.
First page posts this in an input form:
$note="Here is some example text";
Receiving page:
$note = $_POST['note'];
$note = mysql_real_escape_string($note);
$sql="UPDATE some_table SET notes='$note' WHERE id='$some_id'";
$result=mysql_query($sql);
When I take out the mysql_real_escape_string line it works, but not with it in there.
What am I missing?
Thanks!
I strongly recommend using Prepared Statement, mysql_real_escape_string() won't full protect you from SQL Injection.
Example for your update:
<?php
// connection
$conn = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass);
// query
$sql = "UPDATE some_table
SET notes=?
WHERE id=?";
$q = $conn->prepare($sql);
$q->execute(array($$_POST['note'], $some_id));
?>
More details: http://www.php.net/manual/en/intro.pdo.php
I know that I need prepared statements because I make more than one call to my database during one script.
I would like to get concrete examples about the following sentence
Look at typecasting, validating and sanitizing variables and using PDO with prepared statements.
I know what he mean by validating and sanitizing variables. However, I am not completely sure about prepared statements. How do we prepare statements? By filters, that is by sanitizing? Or by some PDO layer? What is the definition of the layer?
What do prepared statements mean in the statement? Please, use concrete examples.
What do prepared statements mean in
the statement?
From the documentation:
This feature allows commands that will be used repeatedly to be parsed and planned just once, rather than each time they are executed.
See pg_prepare
Example from the page linked above:
<?php
// Connect to a database named "mary"
$dbconn = pg_connect("dbname=mary");
// Prepare a query for execution
$result = pg_prepare($dbconn, "my_query", 'SELECT * FROM shops WHERE name = $1');
// Execute the prepared query. Note that it is not necessary to escape
// the string "Joe's Widgets" in any way
$result = pg_execute($dbconn, "my_query", array("Joe's Widgets"));
// Execute the same prepared query, this time with a different parameter
$result = pg_execute($dbconn, "my_query", array("Clothes Clothes Clothes"));
?>
The MySQL documentation for Prepared Statements nicely answers the following questions:
Why use prepared statements?
When should you use prepared
statements?
It means it will help you prevent SQL injection attacks by eliminating the need to manually quote the parameters.
Instead of placing a variable into the sql you use a named or question mark marker for which real values will be substituted when the statement is executed.
Definition of PDO from the PHP manual:
'The PHP Data Objects (PDO) extension defines a lightweight, consistent interface for accessing databases in PHP.'
See the php manual on PDO and PDO::prepare.
An example of a prepared statement with named markers:
<?php
$pdo = new PDO('pgsql:dbname=example;user=me;password=pass;host=localhost;port=5432');
$sql = "SELECT username, password
FROM users
WHERE username = :username
AND password = :pass";
$sth = $pdo->prepare($sql);
$sth->execute(array(':username' => $_POST['username'], ':pass' => $_POST['password']));
$result = $sth->fetchAll();
An example of a prepared statement with question mark markers:
<?php
$pdo = new PDO('pgsql:dbname=example;user=me;password=pass;host=localhost;port=5432');
$sql = "SELECT username, password
FROM users
WHERE username = ?
AND password = ?";
$sth = $pdo->prepare($sql);
$sth->execute(array($_POST['username'], $_POST['password']));
$result = $sth->fetchAll();
How do we prepare statements:
You define a query one time, and can called it as often as you like with different values. (eg. in a loop)
$result = pg_prepare($dbconn, "my_query", 'SELECT * FROM shops WHERE name = $1');
$result = pg_execute($dbconn, "my_query", array("Joe's Widgets"));
$result = pg_execute($dbconn, "my_query", array("row two"));
$result = pg_execute($dbconn, "my_query", array("row three"));
see: http://us2.php.net/manual/en/function.pg-execute.php
Reply to Karim79's answer
This
$result = pg_prepare($dbconn, "query1", 'SELECT passhash_md5 FROM users WHERE email = $1');
seems to be the same as this
$result = pg_prepare($dbconn, "query1", 'SELECT passhash_md5 FROM users WHERE email = ?');
Conclusion: the use of pg_prepare and pg_execute makes PHP much more efficient, since you do not need to consider sanitizing. It also helps you in the use of PDO.