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.
Related
I have a search feature that onkeydown gives out suggestions. Currently, the query only fetches from one row of the table customer_name, and I'm trying to have the id row as well to be searched for the suggestions.
so my query syntax looks likes this:
$query = "SELECT * FROM customers WHERE customer_name OR id like'%".$search."%' LIMIT 5";
But the above query will only fetches from the second table name i.e., id but not both.
What am I doing wrong here?
I could be wrong, but WHERE customer_name will always evaluate to true and thus include all records. You need to specify what customer_name should be compared to.
Correct query:
SELECT * FROM customers
WHERE customer_name LIKE '%".$search."%'
OR id LIKE '%".$search."%'
LIMIT 5;
As an important security tip, you should look into prepared statements instead of mixing data with your queries. Doing so leaves you vulnerable to SQL injection attacks.
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.
I have this code for a news feed and it's combined with a code for a "load more" function. The updates table is where the updates in the newsfeed exist. The username_poster is the username of the person posting an update into which displays in the newsfeed. $last_msg_id represents the id of the last post in the newsfeed to represent what to load next.
The problem I'm having is whenever my code calls to this script, it never loads it. The script works fine when I have the
username_poster IN
(SELECT user_id FROM scuela_following WHERE follower_id = '".$_SESSION['username']."')`
out of the code, but as soon as I add it in, it stops working. Any help would be greatly appreciated.
<?php
$last_msg_id=$_GET['last_msg_id'];
$sql=mysql_query("SELECT * FROM updates_table WHERE id < '$last_msg_id' AND username_poster IN
(SELECT user_id FROM scuela_following WHERE follower_id = '".$_SESSION['username']."')
ORDER BY id DESC LIMIT 5");
$last_msg_id="";
while($row=mysql_fetch_array($sql))
{
}
?>
In this SQL it looks like you're looking for a "username_poster" in your subquery, when you're only selecting "user_id."
AND username_poster IN
(SELECT user_id
FROM scuela_following
Alter the SQL to look for "user_id" instead of "username_poster", or return "username_poster" instead of "user_id" in the subquery.
And as mentioned above, you should really use queries with parameters to prevent SQL injection.
I see that you miss the session_start(); at the very top of your script.
I suspect that there is a problem here:
"... WHERE follower_id = '".$_SESSION['username']."' ..."
Firstly you are not properly escaping and may have an SQL injection vulnerability. You should use mysql_real_escape_string or parameterized queries.
Secondly, it looks like you are comparing a username (e.g. "foobar") to an ID (e.g. 10042). You probably need to join with another table that relates usernames to user IDs.
I am using a particular query for inserting records. It is going well. I am even fetching records with a select query. But my problem is that, if the record contains single quotes ' ', then it gives me this error:
> NOTE: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 'B''' at line 1
The SELECT query is:
$result= mysql_query("SELECT s.name,
s.sid as sid,
s.category,
p.name as pname
FROM poet p
INNER JOIN song s
ON p.pid = s.pid
WHERE s.name= '$sid'") or die(mysql_error());
What should I do to skip quotes problem in this. When I want quotes to insert in my records.
Your problem is much worse than this -- what if someone enters the value '; DROP TABLE poet; --? You need to use either mysql_real_escape_string() to escape the value, or use parametrized queries (with PDO, for example).
It's 2011, for crying out loud. Why is SQL injection still a widespread problem?
You have to escape the data
$sid = mysql_real_escape_string($sid);
use http://www.php.net/manual/en/function.mysql-real-escape-string.php function on your string to quote "'" and other special symbols
Other way to prevent injection - use different connections (login-passwords) with different rights for inserting and selecting. In this case mysql_real_escape_string wi9ll work good
Im trying to get this query to work but i get this error:
Unknown column 'zips.city' in 'having clause'
`$query = "SELECT
zips.*
FROM
zips
HAVING
zips.city LIKE '%$city%'
AND
zips.stateabbr LIKE '%$state%'
LIMIT 1";
$result = mysql_query($query) or die (mysql_error());`
my zips table has a city column, so im not sure what the problem is, i know im accessing the database because i can run this query with no errors:
$zip1query = "SELECT
zips.*
FROM
zips
WHERE
zips.zip = '$zip'
";
any advice would be much appreciated! thanks!
The having clause doesn't mean the same thing as the where clause : when running a simple query, you should use where -- which is what you did in your second query, that works.
having is used when the condition has to be applied on the result of a group by clause.
Which means that, here, your query should be build this way :
$query = "SELECT zips.*
FROM zips
where zips.city LIKE '%$city%'
AND zips.stateabbr LIKE '%$state%'
LIMIT 1";
With that, if you still have an error about a non-existing or not-found column (at least for city and/or stateabbr), it'll be because that column doesn't exist in your table.
In this case, there is not much we can do : you'll have to check the structure of your table, to determine which columns it contains.
You can check that structure using a web-based tool like phpMyAdmin, or using an SQL instruction such as :
desc zips;
For reference, quoting MySQL's manual page for select :
The SQL standard requires that HAVING
must reference only columns in the
GROUP BY clause or columns used in
aggregate functions. ...
Do not use HAVING for items that
should be in the WHERE clause.
For example, do not write the
following:
SELECT col_name FROM tbl_name HAVING col_name > 0;
Write this instead:
SELECT col_name FROM tbl_name WHERE col_name > 0;
...
The HAVING clause can refer to
aggregate functions, which the WHERE
clause cannot
Try using WHERE instead of HAVING.
The proper way to do it is by using a WHERE clause.
$query = "SELECT
zips.*
FROM
zips
WHERE
zips.city LIKE '%$city%'
AND
zips.stateabbr LIKE '%$state%'
LIMIT 1";
HAVING is to be used when you are GROUPing, see here for an explanation
o jeez sorry guys i figured out the problem, apparently i put a space before city when i named the columns in my table. so i renamed the column and it works thanks anyway chaps! but using the where function instead of having must speed things up alot, thanks guys!