This question already has answers here:
Can you omit PDO prepare if there's no placeholder/dynamic data in a query?
(3 answers)
Closed 4 years ago.
$sql = "select col1, col2, col3 from t1 order by date desc limit 500"
There is no place for binding anything, so do I need (and how) to make a prepared statement?
Another example:
$sql = "select col1 from t1 where col1 = 'val1' order by date desc"
If this code is placed before html output (while loading the page, without any user input values), do I need the prepared statement?
I suppose sql injection is not possible if there is no yet any interaction with users.
You don't need prepared statements if the query isn't expecting user supplied arguments.
Related
This question already has answers here:
MySQL query finding values in a comma separated string
(11 answers)
Closed 2 years ago.
I have a simple comma separated string like so:
$thisusersfavorites = "12,13,34,65,11";
I have a simple query like so:
"SELECT * FROM recipes WHERE id = '$thisusersfavorites' ORDER BY name ASC";
But the result is only yielding the first ID result, not the rest.
In MySQL, you can use handy string function find_in_set() to search for a value within a comma-separated string:
select * from recipes where find_in_set(id, ?) order by name
Note that I rewrote your statement as a parameterized query rather than munging values inside the query string. You do want to use these to make your code more efficient and safer.
Also, please keep in mind that this is rather inefficient way to proceed. It would be far beter to split your list into individual values, and to use in:
where id in (12, 13, 34, 65, 11)
As a parameterized query:
where id in (?, ?, ?, ?, ?)
This question already has answers here:
How to include a PHP variable inside a MySQL statement
(5 answers)
Closed 1 year ago.
I have a problem with my php code when i try to choose a string in my database.
Well, I have a table "news" and a field "category" (TINYTEXT type) there. And I try to display a string from this table by using "where clause":
$Sql = 'SELECT * FROM `news` WHERE `category` = '.$Param['category'].' ORDER BY `id` DESC';
I must say that I received "$Param['category']" by using URL Path: 1
So, if my "category" value of any string in table has any string type value like "games" 2, 3 - string from my table isn't displayed with this error "Fatal error: Uncaught mysqli_sql_exception: Unknown column 'games' in 'where clause'"
But, if I change the "category" value of string in the database into anything numeral value - the string from my table is displayed correctly!4, 5
What's wrong with my code? Thank you in advance! Sorry for the mistakes.
You need to use prepared queries, both for the sake of SQL injection protection, and because it will fix your bug. I believe the issue is that you don't have any quotes at all around your parameters. As a result you're building queries like this:
SELECT * FROM `news` WHERE `category` = games ORDER BY `id` DESC
SELECT * FROM `news` WHERE `category` = 1 ORDER BY `id` DESC
The latter is a valid query: mysql looks for records where the category is 1. The former is not: the query tries to find records where the column category matches the column games. The latter doesn't exist so you get an error. You want to build these queries:
SELECT * FROM `news` WHERE `category` = 'games' ORDER BY `id` DESC
SELECT * FROM `news` WHERE `category` = '1' ORDER BY `id` DESC
Which you would do with this code:
$Sql = "SELECT * FROM `news` WHERE `category` = '".$Param['category']."' ORDER BY `id` DESC";
(note that I switched to double quotes and included single quotes around the input parameter). BUT THIS IS STILL WRONG as it leaves you extremely vulnerable to SQL Injection, which would allow an attacker to potentially download or modify your entire database. Take the time to read up and learn how to use prepared queries, which is both more secure and also would have prevented this bug in the first place.
Others have suggested you use parameterized queries. That's good advice, but they didn't show you what it looks like (not that it's hard to find examples).
Here's a quick example using PDO:
$Sql = 'SELECT * FROM `news` WHERE `category` = ? ORDER BY `id` DESC';
$stmt = $pdo->prepare($Sql);
$stmt->execute([ $Param['category' ]);
This executes the query as if you had put $Param['category'] into the SQL, but it does it completely safely, even if the value contains special characters.
You don't put quotes around the ? placeholder. It's implied that the query will treat it as a single scalar value, not a column name. In fact, you can use parameters only for values — not for column names, or expressions, or SQL keywords or anything else.
Writing code using query parameters is easier than not using parameters, because it makes your code easier to write and easier to read.
You have to put quotes around any string in the query if it is not a field in the table. Try this:
$Sql = "SELECT * FROM `news` WHERE `category` = '".$Param['category']."' ORDER BY `id` DESC";
As was mentioned if you are pulling in that string from a source where you have to word about code injection you should use prepared statements or PDO.
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 8 years ago.
I've written a $_GET query that passes strings on from a URL to a select query used to find information in MySQL.
The problem is, unless the URL query includes quotation marks, it won't work.
Is there any way to pass a string without the quotation marks ?
Here's the relevant code:
$query = $_GET['query'];
connect to database code..
$sql = "SELECT * FROM table1 WHERE col1 RLIKE $query";
result code ...
$sql = "SELECT * FROM table1 WHERE col1 LIKE '".addslashes($_GET['query'])."'";
This question already has answers here:
How do I set ORDER BY params using prepared PDO statement?
(7 answers)
Closed 9 years ago.
I have this code
$query_search = $this->db->prepare("SELECT* FROM table1 LEFT JOIN table2 ON (table1.id=table2.id) WHERE table1.nome LIKE ? ORDER BY ? DESC");
if($query_search->execute(array($cliente_procura."%",'table2.'.$ordem)))
{
//code
}
But I'm having some problems with the ORDER BY clause.
How can I use PDO and make sure my tables are in the order I want?
Binding the column names is not possible with prepared statements.
You need to use the age-old method of binding them in strings like this:
$query_search = $this->db->prepare(" SELECT *
FROM table1
LEFT JOIN table2
ON (table1.id=table2.id)
WHERE table1.nome
LIKE ?
ORDER BY table2." . $ordem . " DESC");
if( $query_search->execute( array($cliente_procura."%") ) )
From the Stackoverflow PDO tag wiki - https://stackoverflow.com/tags/pdo/info
PDO Prepared statements and identifiers.
PDO has no placeholder for identifiers, so a developer must manually
format them. To properly format an identifier, follow these two rules:
*Enclose identifier in backticks.
*Escape backticks inside by doubling them.
see - Can PHP PDO Statements accept the table or column name as parameter?
or - Which tokens can be parameterized in PDO prepared statements?
see also this comment/example from the php manual - http://us3.php.net/manual/en/book.pdo.php#69304
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 2 years ago.
The sql injection will work only when my query looks like below sample
SELECT * FROM login WHERE id = $my_id_va;
Assume if my query is
SELECT * FROM login WHERE id = $my_id_va ORDER BY id DESC
Than I will get following error
#1064 - You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'order by id desc' at line 1
So, this 1 or 1=1; SHOW TABLES will not work, correct?
My site was hacked successively many times.
I want one quick answer: When my query looks like the following one, what ways or which types of query can they use to hack my site?
SELECT * FROM login WHERE id = $my_id_va ORDER BY id DESC
What are the ways to execute the show table in the following query
SELECT * FROM login WHERE id = $my_id_va ORDER BY id DESC
I am also using escaping function to handle the query string values, like mysql_real_escape_string($my_id_va). Yes, obviously this for single related hack, but not sure.
Added some more
SELECT EventActuallyCharged, EventDate FROM tblevent WHERE EventDate between '2011-07-21 or 1=1; SHOW TABLES --' and '2011-07-31' ORDER BY EventDate DESC
but show table not worked
If you are using PHP5, use parametarized query, use PDO.
Int cast
If id is a number, you can int-cast your variable as well. Integers are safe to use:
$x = (int)$yourInputVar;
$s = "select * from Table where id = $x";
mysql_real_escape_string
If you want to pass a string, you can, and should, use mysql_real_escape_string, but this function escapes only those characters that are inside the string. You will still need to add quotes around the string, so:
$x = mysql_real_escape_string('hello');
$s = "select * from Table where id = $x";
.. will result in the query: select * from Table where id = hello. This is obiously not a valid query, since hello should be in quotes.
Change the query to:
$x = mysql_real_escape_string('hello');
$s = "select * from Table where id = '$x'";
.. and everything works fine. You add the quotes around, and mysql_real_escape_string takes care of special characters inside the string, if any.
Parameters
Another solution is to use parameterized queries. This can by done using MySQLi or PDO. The advantage is that you only tell your database where a variable should be inserted, and the database takes care of the escaping yourself.
It also may add a performance benefit, because these queries could be cached without their parameters, make a more efficient use of the query cache. This doesn't really work yet in current versions of MySQL, though.
You are right that 1 or 1=1; SHOW TABLES will give a syntax error but this will work:
1 or 1=1 --
The -- comments out the rest of the query.
In your case the value is an integer so instead of using mysql_real_escape_string you can use intval.
If you set $my_id_va to:
1 or 1=1; SHOW TABLES --
The -- will comment out the rest of the command, effectively terminating it.
I'm not sure what effect mysql_real_escape_string will have on the query. What you should be doing is parameterized queries.
1. First query somehow secured
$sql = sprintf('SELECT * FROM login WHERE id = %d ORDER BY id DESC', mysql_real_escape_string($my_id_va));
2. Second query somehow secured
$sql = sprintf("SELECT EventActuallyCharged, EventDate FROM tblevent WHERE EventDate BETWEEN '%s' AND '%s' ORDER BY EventDate DESC",
mysql_real_escape_string($start_date),
mysql_real_escape_string($end_date));
Read the docs about sprintf if you don't understand it.
However, as others have said, it would be very very secure if you would use parameterized queries with a class such as PDO or MySQLi.