How do I handle single quotes inside a SQL query in PHP? - php

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

Related

How would someone use sql injection on this query

So I have this query in php
SELECT a.sifra,a.slika,a.slika2,a.imeProizvoda,a.opis,b.cijena,b.cijena2
FROM proizvodi a
inner join stanje b
on a.sifra = b.sifra
WHERE a.imeProizvoda LIKE '%$search%'
I tried making sql injection with DROP TABLE proizvodi in every way i found on internet but couldn't make it work
How would someone make that query in search so my database proizvodi is deleted
To avoid SQL injection in PHP, you should absolutely use prepared statements, which make it pretty much impossible to do any SQL injection. For an answer to your question, we can try the following:
$search = "'; DROP TABLE proizvodi; SELECT * FROM dual WHERE '1' LIKE '";
This would result in the following being executed:
SELECT a.sifra, a.slika, a.slika2, a.imeProizvoda, a.opis, b.cijena, b.cijena2
FROM proizvodi a
INNER JOIN stanje b
ON a.sifra = b.sifra
WHERE a.imeProizvoda LIKE '%';
DROP TABLE proizvodi;
SELECT * FROM dual WHERE '1' LIKE '%'
The basic idea is to trip up PHP/MySQL by ending the original valid statement, and then injecting some other (malicious) statement afterwards. Note that DROP and DELETE are not the only damaging things which could happen. For example, doing a SELECT * on a customer table containing credit card numbers could be the most damaging thing to happen.
Disclaimer: I don't live in my parents' basement and spend all my time injecting websites. But, I knew enough to guess at an answer to your question.

WHERE NOT EXISTS syntax error

I have this code that does not work, and im not sure why...
if(isset($_GET['id'], $_SESSION['username'])){
$id = $_GET['id'];
$user = $_SESSION['username'];
$query = $handler->query("INSERT INTO photolikes('User', 'Photo')
SELECT '$user', '$id'
WHERE NOT EXISTS (SELECT Id FROM photolikes WHERE User='$user' AND Photo=$id)");
}else{
}
Is just supposed to insert user and photo into a table if there is no such in there before... thanks for any help!
The SELECT is missing the FROM clause which is required when a WHERE clause is used.
That's the problem.
There's a couple of ways to fix it.
For a quick fix, you can add FROM DUAL before the WHERE.
If you don't like your MySQL queries looking like they are Oracle queries, you can use an inline view as a rowsource.
In place of FROM DUAL you could use FROM (SELECT 1) i.
That's the less-Oracle-more-MySQL-like way of fixing it. That's how I would do it.
You could also reference any table or view that you are guaranteed returns exactly one row. (It can't be zero rows, and it can't be two rows.
A couple other notes:
In MySQL, identifiers (for example column names) can be escaped with backtick characters, but not single quotes. Identifiers only need to be escaped if they contain characters that aren't allowed (in unescaped identifiers) or if the identifier conflicts with a reserved word.
INSERT INTO photolikes(`User`, `Photo`)
^ ^ ^ ^
Also, the code appears to be vulnerable to SQL Injection. Potentially unsafe values that are incorporated into the text of a SQL statement should be properly escaped. But an even better pattern is to use prepared statements with bind placeholders.
INSERT INTO photolikes(`User`, `Photo`)
SELECT '$user', '$id'
FROM <someTable>
^^^^ you miss the FROM
WHERE NOT EXISTS (SELECT Id
FROM photolikes -- Here you didnt forget.
WHERE User='$user' AND Photo=$id)")

MySQL error 1064: SQL syntax error in SELECT statement

I am relatively new to somewhat advanced MySQL querying. I had been trying to query the most recent order in an order table of a particular user using MySQL SELECT statement using the following MySQL query.
SELECT o1.* FROM order AS o1
WHERE o1.orderDateTime =
(
SELECT MAX(o2.orderDateTime) FROM order AS o2
WHERE o2.userId = '1'
)
But I had been constantly getting the following MySQL error #1064 related to MySQL syntax.
#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 AS o1 WHERE o1.orderDateTime = (SELECT MAX(o2.orderDateTime)FROM order AS ' at line 1
I got similar errors in relation with INSERT statements but I managed to fix it up using the methods specified in MySQL 1064: You have an error in your SQL syntax
I made every effort to fix the query in the current case but I was still unsuccessful.
I would be grateful to you if someone can help me out with fixing this MySQL syntax error for SELECT clause specified above. It would be great if someone could specify me the exact reason for the occurrence of this issue, as well.
order is a reserved word and its a bad choice for table name. You need to escape using backticks in the query
SELECT o1.* FROM `order` AS o1
WHERE o1.orderDateTime = (
SELECT MAX(o2.orderDateTime) FROM `order` AS o2
WHERE o2.userId = '1'
)
http://dev.mysql.com/doc/mysqld-version-reference/en/mysqld-version-reference-reservedwords-5-5.html
As per #Abhik, order is a MySQL keyword.
And you should avoid collapse with two methods:
Use backticks (`) (#Abhik has already explained this.)
Prepend Database name before Table Name e.g.
DataBase_Name.order.
But, still #Abhik's approach is preferable as in case of database name change, you need to change DataBase name in your query.
First of all you could follow #Abhik Chakraborty suggestion to include back ticks around order table name. order is a reserved word in mysql. My suggestion was to improve your sql query. YOu could acomplish the same using:
SELECT o1.* FROM `order` o1
WHERE o1.userId = '1' order by orderDateTime desc limit 1
the subquery seems unnecessary.

Escape table name MySQL

I have a little problem with escaping table name. I was so stupid that i choose "show" for the name of table. When I use mysqli connection the escaping works fine, but its not working with classical mysql connection. Any advise?
Sorry for my English, I am not native speaker.
SELECT SQL_CALC_FOUND_ROWS year, nameShow
FROM `show`
LIMIT 0, 10
I get error as
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 'show' at line 2 –
Query
$sQuery = "
SELECT SQL_CALC_FOUND_ROWS year, nameShow
FROM `show`
$sWhere
$sOrder
$sLimit
";
Section 9.3 of MySQL 5.1 Reference Manual says back ticks (`) or double quotes ("), however, I'd go with Fahim Parkar's comment above and just rename the table.
Also worth noting, you must use ANSI_QUOTES SQL mode if using double quotes per Section 9.2:
If the ANSI_QUOTES SQL mode is enabled, it is also permissible to
quote identifiers within double quotation marks
The problem is with YEAR not with SHOW. YEAR is a MySQL function.
Best practice is to quote column and tables names all the time, makes things easy to read also.
Should be:
SELECT SQL_CALC_FOUND_ROWS `year`, `nameShow`
FROM `show`
LIMIT 0, 10
Backticks should work fine
try putting a comma after SQL_CALC_FOUND_ROWS,
SELECT SQL_CALC_FOUND_ROWS, year, nameShow
FROM `show`
LIMIT 0, 10

SQL injection even when the variable is escaped [duplicate]

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.

Categories