how to securely use LIKE - php

I'm building a script where users can search a database. my understanding is that PDO doesn't let you set a parameter for the LIKE operand. So I have this code to make up for it
$sQuery = "SELECT * FROM table WHERE column LIKE '%" . $this->sQuery . "%' LIMIT 30";
$Statement = $this->Database->prepare($sQuery);
$Statement->execute();
I doubt this is secure against SQL injection. Is there any way to make it secure?

You're right, interpolating any value into an SQL string creates a risk for SQL injection vulnerability. It's better to use a SQL query parameter placeholder when you prepare(), and then supply the value as a parameter when you execute().
$pattern = "%" . $this->sQuery . "%";
$sQuery = "SELECT * FROM table WHERE column LIKE ? LIMIT 30";
$Statement = $this->Database->prepare($sQuery);
$Statement->execute(array($pattern));
Take that as pseudocode because I can't tell from your example which MySQL extension you're using. I'm assuming PDO, which allows parameters to be sent as an array argument to execute().
Some people use PDOStatement::bindParam(), but there's no advantage to doing so. Maybe in some other RDBMS brands the PDO::PARAM_STR matters, but in the MySQL driver, the parameter type is ignored.
PS: Aside from the security issue you asked about, you will find a search for wildcard-based patterns like you're doing don't perform well as your data grows larger. See my presentation Full Text Search Throwdown.

This should work:
$sQuery = "SELECT * FROM table WHERE column LIKE :query LIMIT 30";
$Statement = $this->Database->prepare($sQuery);
$Statement->execute(array(':query' => '%' . $this->sQuery . '%'));

Related

SQL LIKE literally not showing any results (at all)

I tried to make a search system which uses the LIKE operator to search results based on what the user typed. I'm using it with strings. The problem is that it doesn't show any result.
I hope this also helps people with the same confusion as me...
Code:
"SELECT * FROM table WHERE name LIKE ' . $input . ';";
input is a PHP variable from what the user typed.
EDIT: Don't worry about SQL injection, it's all offline.
for the proper use of like you should use wildchar eg :
SELECT * FROM table WHERE name LIKE concat('%', ? ,'%') ;
and you should not use var inside SQL code .. you are at risk for sqlinjectiomn
for avoid this you should take a look at you db driver for prepared statement and binding param
eg for PDO
$st = $conn->prepare("SELECT * FROM table WHERE name LIKE concat('%', ? ,'%')");
$st->bindParam(1, $input, PDO::PARAM_STR, 255);
$st->execute();
Try This
$string = "input";
$sql = "select * from table where name like '%$string%'"
Create a variable and store value what you want to search
$where = "AND name like '%$string%'";
and put it after table name
$sql = "select * from table_name $where";

How to access a table using a variable name in sql query

I have multiple tables in my database named teacher1, teacher2.... I am trying to access them using a variable $id.
I have written down the following code.
$query = "SELECT * FROM table.$id";
How could i access those different tables using a variable.
I'm not clear from the question text whether your $id variable contains the full table name, or some kind of number.
However, in either case you have to make a slight tweak to your $query variable.
If $id contains the full name of the table (i.e. teacher1):
$query = "SELECT * FROM " . $id;
If $id contains a number used to identify which teacher table it is (i.e. 1, 2, 3, etc):
$query = "SELECT * FROM teacher" . $id;
Learn to use parameters!
$stmt = $conn->prepare($query = "SELECT t.* FROM table t where t.id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
Don't munge query strings with parameter values! This introduces SQL injection risk, can introduce syntax errors that are hard to debug, and can degrade performance.

Securing PHP MySQL code

I have a PHP search suggestion script which uses MySQL as its back-end. I am aware there are many vunerabilities in my code, I was just wondering what I can do to make it more secure.
Here is my code:
<?php
$database=new mysqli('localhost','username','password','database');
if(isset($_POST['query'])){
$query=$database->real_escape_string($_POST['query']);
if(strlen($query)>0){
$suggestions=$database->query(
"SELECT * FROM search WHERE name LIKE '%" . $query .
"%' ORDER BY value DESC LIMIT 5");
if($suggestions){
while($result=$suggestions->fetch_object()){
echo '<a>'.$result->name.'</a>';
}
}
}
}
?>
Actually there aren't, considering you are escaping the only external value in the SQL
Anyway I suggest you to use PDO::prepare for queries. Go here for further infos
http://it.php.net/manual/en/pdo.prepare.php
Example:
$sth = $dbh->prepare('SELECT * FROM article WHERE id = ?');
$sth->execute(array(1));
$red = $sth->fetchAll();
Some tips from me:
use PDO,
don't concatenate query parameters, use prepared statements in PDO,
don't put "*" in SELECT statement, get only the columns you'll need,
use fetchAll() in PDO, don't fetch records in while() loop.

Search Multiple Items in Multiple columns

I have 6 select items in a form. I want to search those 6 in MYSQL DB. I can retrieve results if I use only one, like:
$result = mysql_query("SELECT * FROM wsinmuebles WHERE Property_Type LIKE '%{$_POST['Property_Type']}%'");
But when I try more, I get no results!
$result = mysql_query("SELECT * FROM wsinmuebles WHERE
Property_Type LIKE '%{$_POST['Property_Type']}%' AND
Estado LIKE '%{$_POST['Estado']}%' AND
Ciudad LIKE '%{$_POST['Ciudad']}%' AND
Urbanizacion LIKE '%{$_POST['Urbanizacion']}%' AND
Operacion LIKE '%{$_POST['Operacion']}%' AND
Precio_bsf LIKE '%{$_POST['Precio_bsf']}%'");
This comes from a form by the POST method.
What I need is to look for Property_Type, Estado, Ciudad, Urbanizacion, Operacion and Precio_bsf variables in MYSQL DB, and receive only the results that match all those values.
First, escape the post values using mysql_real_escape_string (Link) to avoid any SQL injection attacks and also issues with the data having ' characters.
Second echo the query and run it against the database and check the table data to see if the
query indeed should return some values or may be there are no matches when include the rest of criteria since you mentioned that you are expecting the results that match all those values.
Dont use And use Or between criteria, and after all you should know that concatenating strings and executing queries is giving possible SQL Injection, that is when instead of your search string I end your query and execute given action, for example "' and 1=1; delete wsinmuebles" if this is my serach query you will lose all your data.
$result = mysql_query("select * from tbl1 where Name='".mysql_escape_string ($_POST["value"]."'" );
If a field, say Urbanizacion is null, your query will not return it.
Urbanizacion LIKE '%%' => FALSE when Urbanizacion is Null
You will need to handle Nulls. I also strongly urge you to protect the code from SQL Injection using mysql_real_escape_string
$result = mysql_query("
SELECT * FROM wsinmuebles WHERE
IFNULL(Property_Type,'') LIKE '" . mysql_real_escape_string($_POST['Property_Type']) ."' AND
IFNULL(Estado,'') LIKE '" . mysql_real_escape_string($_POST['Estado']). "' AND
IFNULL(Ciudad,'') LIKE '" . mysql_real_escape_string($_POST['Ciudad']) ."' AND
IFNULL(Urbanizacion,'') LIKE '" . mysql_real_escape_string($_POST['Urbanizacion']) ."' AND
IFNULL(Operacion,'') LIKE '" . mysql_real_escape_string($_POST['Operacion']) ."' AND
IFNULL(Precio_bsf,'') LIKE '" . mysql_real_escape_string($_POST['Precio_bsf']) ."'");

LIKE statement and special characters in PDO / PHP

I've already checked answers to questions like this one (How do I create a PDO parameterized query with a LIKE statement in PHP).
I've ended up to this solution:
$sql = "SELECT count(*) ".
"FROM mytable ".
"WHERE num_certif LIKE CONCAT('%',:val,'%')";
$valeur = 'azert';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':val', $val);
This works, but here is my problem: how do I handle the '%' char? (i.e. $valeur = '%'; returns all the rows)?
You need to escape the % character,
$valeur = '\%';
Note for PostgreSQL users... instead of the CONCAT function you can use
SELECT count(*)
FROM mytable
WHERE num_certif LIKE '%' || :val || '%'
I achieved that using string comparison functions:
WHERE INSTR(LCASE(num_certif),LCASE(:val))>0
I suspect performance will suffer.
I have been using something very simple, like this:
$select_str = "SELECT * FROM table_x WHERE text_field LIKE '%".$value."%'";
$StHandler = $this->dbHandler->prepare($select_str);
$StHandler->execute();
You can use only one % depending on what you're looking for. For example, if you want it to start with your value and have any characters later, you will use '".$value."%'"
Hope this helps
In order to avoid having to do your own escaping, the stuff that needs to be escaped has to be part of the data that pdo protects, namely the bound arguments. It doesn't protect you from anything in the hard coded query.
$sql = "SELECT count(*) ".
"FROM avs_souscript ".
"WHERE num_certif =\"\" ".
"AND date_annul=\"\" ".
"AND user=:sess_user ".
"AND user!=\"\" ".
"AND num_certif LIKE :num_certif_search";
$valeur = 'azert'; //I assume this actually came from some user input
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':num_certif_search', '%'.$valeur.'%');
(or alternately you could put them in the $valuer = "%{$userInput}%"; assignment, either way, they should be in the bound argument, not in the sql.
Moving this bit of silly string concat from the sql out to the php is also good practice for making a scalable application. It's much easier to scale a farm of web servers than it is to scale the database server.

Categories