This question already has answers here:
How to bind LIKE values using the PDO extension?
(7 answers)
Closed 7 years ago.
i am going to prevent SQL injection using PDO but i Want to know can my code prevent SQL injection
Here is my code
connection.php
<?php
$hostname='localhost';
$username='root';
$password='root';
try {
$pdo_obj = new PDO("mysql:host=$hostname;dbname=dbname",$username,$password);
$pdo_obj->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo_obj->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
my function.php
<?php
function getdata($pdo_obj, $sql, $params=NULL) // pdo prepaired statements
{
$stmt = $pdo_obj->prepare($sql);
$stmt->execute($params);
return $stmt;
}
?>
and my page.php
<?php
$searchTerm = $_GET['term'];
$result=getdata($pdo_obj,"SELECT b_type FROM b_details WHERE b_type LIKE '%".$searchTerm."%'")->fetchAll();
// my work
?>
every thing working fine but i am not sure is this code prevent SQL Injection
Thanks in Advance
You aren't using your function's ability to protect from injection. To do so you have to send any data via parameters.
<?php
$searchTerm = '%'.$_GET['term'].'%';
$sql = "SELECT b_type FROM b_details WHERE b_type LIKE ?";
$result = getdata($pdo_obj, $sql, [$searchTerm])->fetchAll(PDO::FETCH_COLUMN);
BTW, I added a PDO::FETCH_COLUMN constant that will make the returned array more convenient, given only one column is selected.
Related
This question already has answers here:
Can I mix MySQL APIs in PHP?
(4 answers)
Reference - What does this error mean in PHP?
(38 answers)
Closed 5 years ago.
Below is my function listRecordsMatching($accNo) which connects to my mySQL server to match all records that have a specific account number. I know my problem lies in the way I write my SQL.
My table has the following structure: (int)id, (string)cheque-no, (double)amount, (date)cheque-date, (string)customer, (int)account.
NOTE: conn() is a global function in my config file that returns the mysqli object connected to my server.
EDIT: Since the conn() function is leading to some confusion:
EDIT2: I have found the answer. After doing $stmt->execute() I must bind the results to variables to use them. $stmt->bind_results($var1, $var2, ...)
// Create connection
$conn = new mysqli($servername, $username, $password);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$GLOBALS['conn'] = $conn;
function conn(){
return $GLOBALS['conn'];
}
function listRecordsMatching($accNo){
//prepare statement
$stmt = conn()->prepare("SELECT * FROM `mfs-cheque-app`.`cheques` WHERE `account` = ?");
$stmt->bind_param('i', $accNo);
$stmt->execute();
$row=$stmt->fetch(PDO::FETCH_ASSOC);
var_dump($row) // outputs NULL
echo "<form id='records'>1";
while(true){
if (!$row) break;
$c = new Cheque($row['cheque-no'],$row['amount'],$row['cheque-date'],$row['customer'],$row['account']);
echo $c->list(); // outputs formatted html
}
echo "2</form>";
}
OUT>>> NULL<form id="records">12</form>
You are using 2 different Variables $accNo and $account ...change one of them to match the other and it will probably start working.
I'm making a forum in php and MySql, so I need to insert and select data from my data base. I'm using mysqli to connect to my db. Something like this:
$link=mysqli_connect("fake_server", "fake_user", "fake_pass", "fake_db");
$user=mysqli_real_escape_string($link, $_POST['user']);
$pass=hash("sha256", mysqli_real_escape_string($link, $_POST['pass']));
$combo=mysqli_fetch_array(mysqli_query($link, "SELECT 1 FROM users WHERE user='$user' AND pwd='$pass'"));
if($combo==0){
// ERROR
} else {
// CORRECT
}
mysqli_close($link);
The problem is the next one:
Everybody say that mysqli_real_escape_string() is MUCH better than addslashes() for insert, but I want users can use single and double quotes in their topics. Myqsli_real_escape_string() removes them but addslashes() doesn't. What can I do in this context?
You should use prepared statements, http://php.net/manual/en/mysqli.quickstart.prepared-statements.php. In the future please provide your code in your question. Here's how you can use your current code with prepared statements:
$link=mysqli_connect("fake_server", "fake_user", "fake_pass", "fake_db");
$user=$_POST['user'];
$pass=hash("sha256", $_POST['pass']);
$stmt = $link->prepare("SELECT 1 FROM users WHERE user = ? AND pwd = ?");
$stmt->bind_param("ss", $user, $pass);
$combo=mysqli_fetch_array($stmt->execute());
if($combo==0){
// ERROR
} else {
// CORRECT
}
mysqli_close($link);
Further reading on the topic:
How can I prevent SQL injection in PHP?mysqli or PDO - what are the pros and cons?
https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet#Defense_Option_1:_Prepared_Statements_.28Parameterized_Queries.29http://php.net/manual/en/mysqlinfo.api.choosing.php
Use a parameterized query with PDO and forget worrying about escaping your queries.
Edit
Your test code:
$link=mysqli_connect("fake_server", "fake_user", "fake_pass", "fake_db");
$user=mysqli_real_escape_string($link, $_POST['user']);
$pass=hash("sha256", mysqli_real_escape_string($link, $_POST['pass']));
$combo=mysqli_fetch_array(mysqli_query($link, "SELECT 1 FROM users WHERE user='$user' AND pwd='$pass'"));
if($combo==0){
// ERROR
} else {
// CORRECT
}
mysqli_close($link);
The PDO version:
$pdo = new PDO('mysql:host=fake_server;dbname=fake_db', 'fake_user', 'fake_pass');
$query = $pdo->prepare("SELECT 1 FROM users WHERE user='?' AND pwd='?'");
$query->execute(array($_POST('user'), hash('sha256', $_POST('pass')));
if ($combo = $query->fetch ()) {
// CORRECT
// $combo would contain an array containing your select fields
} else {
// ERROR
}
I am starting to learn php PDO because I've read that it is more efficient and secure.
I could do the following with simple mysqli but am having trouble making it work with PDO.
PID stands for an id number.
fname stands for: first name.
lname stands for: last name.
age stands for ... age.
Basically I have an index.php that contains links from a test table called "persons" inside of the database drinks. When I click on the link which shows the fname of every row, it goes to insertcarbonated.php which is then supposed to $_GET['fname']; of the link and search up that specific row. However, my code in insertcarbonated.php is not working and I am not familiar enough with PDO to know exactly why, I would like some enlightenment on this because I literally begun learning PDO yesterday. :(
Here is my insertcarbonated.php:
<html>
<?php
/*** mysql hostname ***/
$hostname = 'localhost';
/*** mysql username ***/
$username = 'theusername';
/*** mysql ***/
$password = 'thepass';
try {
$dbh = new PDO("mysql:host=$hostname;dbname=drinks", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database';
/*** The SQL SELECT statement ***/
$fname = $_GET['fname'];
//is _GET even working with PDO?
$STH = $dbh-> prepare( "SELECT * FROM persons WHERE fname LIKE '$fname'" );
/***as Joachim suggested, I had actually two different variables here, however, it
did not solve the issue **EDITED** from ($DBH to $dbh)****/
$STH -> execute();
$result = $STH -> fetch(0);
//$result should print out the first column correct? which is the person's ID.
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
<head>
</head>
<body>
<p><?php print $result; ?></p>
//me trying to print out person's ID number here.
</body>
</html>
As previously mentioned, I'm not sure where my error is, I get fatal error:
Call to a member function prepare() on a non-object?
and If I try to not use that function, my page is simply blank and nothing prints out.
Basically I would just like to print out different bits of information from that row (that is from it's relevant link in index.php). I would like to know how to solve this using PDO.
Here is the previous question I asked, and it was solved but not with PDO.
Previous question
You could do something like this...
try {
$dbh = new PDO("mysql:host=$hostname;dbname=drinks", $username, $password);
$fname = $_GET['fname'];
$sth = $dbh->prepare("SELECT * FROM persons WHERE fname LIKE ?");
$sth->execute( array($fname) );
$result = $sth->fetch(PDO::FETCH_OBJ); // or try PDO::FETCH_ASSOC for an associative array
}
catch(PDOException $e)
{
die( $e->getMessage() );
}
In the HTML part you can do print_r($result) and you will see the exact structure of your results.
Comments: one of the best reasons to use PDO is the automatic escaping of the dynamic user inputs, like $fname here, so you should use it. Also, with $sth->fetch($param) the $param is not the column number but the type of the fetch method PDO will use (see PHP manual). Depending the method, you can get the PID of the result by $result->PID in case of PDO::FETCH_OBJ or by $result['PID'] when using PDO::FETCH_ASSOC. I hope this helps.
This question already has answers here:
Fatal error: Call to a member function fetch_assoc() on a non-object [duplicate]
(4 answers)
Closed 8 years ago.
ok i have been using the mysql format for quite a while but i figured its time to transfer my site over to the new mysqli format now rather then later. im trying to re write my functions to draw stats from the database but i am getting all sorts of errors.
I have looked at countless mysqli tuts but none are very descriptive and im not quite understanding the 2 parameter rule ect. below i posted my function and includes. if anyone can tell m what im doing wrong i would appreciate it.
Fatal error: Call to a member function fetch_assoc() on a non-object in C:\xampp\htdocs\includes\stat.php on line 7
stat.php
function getStat($stat) {
require_once 'includes/config.php';
$mysqli = new mysqli($dbhost, $dbuser, $dbpass, $dbname);
$sql = $mysqli->query("SELECT $stat FROM players WHERE username = '".$_SESSION['username']."'");
$row = $sql->fetch_assoc();
$result = $row['$stat'];
return $result;
}
?>
and here is the test page i am using to try and get this working.
test.php
<?php
include 'includes/login-check.php';
include 'includes/config.php';
include 'includes/database.php';
include 'includes/stat.php';
echo getStat('name');
?>
ow and please dont start posting a bunch of comments bashing on the code cause as stated before ive never used mysqli so ide rather read constructive criticism then flames like half the post around here.
Change that in your getStat function.
$result = $row[$stat];
Adapt the following code to best suit your current code...
if ($stmt = mysqli_prepare($link, "SELECT $stat FROM players WHERE username = ?")) {
/* bind parameters for markers */
mysqli_stmt_bind_param($stmt, "s", $_SESSION['username']);
/* execute query */
mysqli_stmt_execute($stmt);
/* bind result variables */
mysqli_stmt_bind_result($stmt, $district);
/* fetch value */
mysqli_stmt_fetch($stmt);
printf("%s is the current username.");
/* close statement */
mysqli_stmt_close($stmt);
}
I believe I have the syntax correct, at least according to my textbook. This is just a piece of the file as the other info is irrelevant to my problem. The table name is user, as well as the column name is user. I don't believe this to be the problem, as other sql statements work. Though it isn't the smartest thing to do I know :) Anyone see an error?
try {
$db=new PDO("mysql:host=$db_host;dbname=$db_name",
$db_user,$db_pass);
} catch (PDOException $e) {
exit("Error connecting to database: " . $e->getMessage());
}
$user=$_SESSION["user"];
$pickselect = "SELECT game1 FROM user WHERE user='$user' ";
$pickedyet = $db->prepare($pickselect);
$pickedyet->execute();
echo $pickselect;
if ($pickedyet == "0")
{
echo '<form method="post" action="makepicks.php">
<h2>Game 1</h2>......'
Since you're seemingly using prepared statements, I'd recommend using them to their fullest extent so that you can avoid traditional problems like SQL injection (this is when someone passes malicious SQL code to your application, it's partially avoided by cleansing user inputs and/or using bound prepared statements).
Beyond that, you've got to actually fetch the results of your query in order to display them (assuming that's your goal). PHP has very strong documentation with good examples. Here are some links: fetchAll; prepare; bindParam.
Here is an example:
try
{
$db = new PDO("mysql:host=$db_host;dbname=$db_name",
$db_user, $db_pass);
}
catch (PDOException $e)
{
exit('Error connecting to database: ' . $e->getMessage());
}
$user = $_SESSION['user'];
$pickedyet = $db->prepare('SELECT game1 FROM user WHERE user = :user');
/* Bind the parameter :user using bindParam - no need for quotes */
$pickedyet->bindParam(':user', $user);
$pickedyet->execute();
/* fetchAll used for example, you may want to just fetch one row (see fetch) */
$results = $pickedyet->fetchAll(PDO::FETCH_ASSOC);
/* Dump the $results variable, which should be a multi-dimensional array */
var_dump($results);
EDIT - I'm also assuming that there is a table called 'user' with a column called 'user' and another column called 'game1' (i.e. that your SQL statement is correct aside from the usage of bound parameters).
<?php
session_start();
$db_user = 'example';
$db_pass = 'xxxxx';
try
{
// nothing was wrong here - using braces is better since it remove any confusion as to what the variable name is
$db=new PDO( "mysql:host={$db_host}dbname={$db_name}", $db_user, $db_pass);
}
catch ( Exception $e ) // catch all exceptions here just in case
{
exit( "Error connecting to database: " . $e->getMessage() );
}
// this line is unecessary unless you're using it later.
//$user = $_SESSION["user"];
// no need for a new variable here, just send it directly to the prepare method
// $pickselect = '...';
// also, I changed it to a * to get the entire record.
$statement = $db->prepare( "SELECT * FROM user WHERE user=:user" );
// http://www.php.net/manual/en/pdostatement.bindvalue.php
$statement->bindValue( ':user', $_SESSION['user'], PDO::PARAM_STR );
$statement->execute();
// http://www.php.net/manual/en/pdostatement.fetch.php
// fetches an object representing the db row.
// PDO::FETCH_ASSOC is another possibility
$userRow = $statement->fetch( PDO::FETCH_OBJ );
var_dump( $userRow );
echo $userRow->game1;
Change this user=$user with this user='$user'. Please, note the single quotes.
Moreover, you are executing the query $pickedyet->execute(); but then you do echo $pickselect; which is nothing different from the string that contains the query.
Little hints:
You've to retrieve the result of the query execution.
You're using prepared statement which are very good but you're not really using they because you're not doing any binding.