I have an input field named "eventName". everytime I will put single quote (e.g uncle's birthday) it won't be inserted to the database. I mean no data at all will be posted to database. the system will just say that the event was saved but no data is being stored in the database.
You need to escape the single quote. The escape character used in this case of a '\', you can use inbuilt functions like mysqli_escape_string or add-slashes.
When you add a single quote in a variable and add it to a query, this will change your query by considering the single quote as a comment. e.g
Insert into Table ('name') values ('uncle's birthday');
Your query got ended at uncle and the part after that won't be considered, essentially this would result in failure. You should check what the error code as well depending on which database you are using.
Update:
$eventName = add_slashes($_POST['eventName']);
Rather than simply adding slashes, consider prepared statements, thus preventing SQL injection attacks. More details about this here: How can I prevent SQL injection in PHP?
It's good practice to escape values before writing them to your database.
$escapedName = mysqli_real_escape_string($_POST['eventName']);
Related
Do I need to use mysqli_real_escape_string when reusing data from a database for a query. The data was previously escaped so it can be safely inserted into the database. I am aware that when inserting data into a database, backslashes are removed.
Thanks.
Yes, you have to re-escape data that came from a DB when you're re-using it in another query. Consider escaping to be the equivalent of gift wrapping on a present. You "wrap" some data for the database in one query. It'll UNWRAP the data and put it in the data store. When you retrieve that data again later, the wrapping's gone and the data's "dangerous" again.
e.g. consider something like this:
$name = "Miles O'Brien";
$safe = mysql_real_escape_string($name); // name becomes Miles O\'Brien
$sql = "INSERT INTO people (names) VALUES '$safe'";
$result = mysql_query($sql) or die(mysql_error());
Now that name's in the database, but the escaping you performed is NOT PRESENT anymore - it was removed by the database as it processed the query, so if you do something like this:
$sql = "SELECT name FROM people"
$result = mysql_query($sql) or die(mysql_error());
while($row = mysql_fetch_asssoc($result)) {
$name = $row['name']; // get Miles O'Brien from the DB again
here you'll literally have retrieved Miles O'Brien with no escaping at all.
$other_sql = "UPDATE ... WHERE name=$name"; <---INJECTION HERE
}
Escaping is not something you do only with "outside" data... ANY data you insert into a query string is "outside" data, even if you just got that data from the database just a few lines of code ago.
TL;DR: You can easily inject yourself.
Yes, you need it. The escapes are only used to make the query syntactically valid, they're not part of the data that's stored in the table. Any time you're interpolating strings into a query, you need to escape it.
As an example, suppose you have a table of full names, and there's someone with the last name O'Reilly. You perform a query to get this name into $lname, and then you want to use that variable in another query, e.g.
$query = "SELECT username WHERE last_name = '$lname'";
If you don't escape the string, the resulting query will be:
SELECT username WHERE last_name = 'O'Reilly'
As you can see, the quotes are not properly balanced. You need to escape it so that it will be:
SELECT username WHERE last_name = 'O\'Reilly'
However, if you use prepared queries with placeholders for these parameters, you don't need to worry about this much at all (in fact, it would be wrong to escape a variable that's bound to a placeholder, as you will then store the backslashes). This is generally preferred.
Also, consider NOT extracting and re-storing the data at all, but moving data around using SQL itself:
INSERT INTO Table1 (last_name)
SELECT last_name
FROM Table2
WHERE ...
This is also likely to be more efficient, since the data doesn't have to move between the database and the application.
That's not what escaping means.
Escaping text means inserting escape characters so that it can be inserted into a SQL string and be interpreted as the original text.
It has no effect on the actual value, unless you use the wrong escape characters.
You need to correctly escape your text every time you concatenate it into any kind of structured language.
When using SQL, you should ideally use parameters instead of concatenation.
There are a lot of misunderstanding on the topic.
People keep using improper words, and a real danger coming from such a confusion.
escaping being confused with safety
data being confused with strings
formatting being confused with trusting
One have to sort these matters out.
Otherwise we still have an accepted answer implying that using mysql_real_escape_string does produce a "safe" variable. While it is not.
Just remember to validate properly all user inputted data that you plan on using and don't allow html or javascript code to be inserted. You also need to keep in mind XSS attacks, not just MySQL Injections. A good way to prevent xss is using htmlspecialchars() to convert HTML characters into HTML entities.
I'm familiar with prepared statements and I know that they are best practice when it comes to protecting against MySQL injection. But I'm wondering how this PHP/MySQL statement could be at risk of an injection attack:
$result = mysqli_query($db,"SELECT name FROM users WHERE id = '".$_POST['name']."';");
It seems to me like the input from the user would be contained inside the single quotes. Can you execute more than one query in one mysqli_query statement?
Also, is making the above safe just as easy as this...
$result = mysqli_query($db,"SELECT name FROM users WHERE id = '".mysqli_real_escape_string($_POST['name'])."';");
It seems to me like the input from the user would be contained inside the single quotes
It would unless you include single quotes in the posted name, which would allow you to break out of the quotes. Example, post the name as:
' or 1 or '
The WHERE clause becomes:
WHERE id = '' or 1 or '';
This would match and retrieve all rows in the table because of the or 1 part. As you can see, it breaks out of the quotes to inject some SQL, then it goes back into the quotes to make the query valid.
Can you execute more than one query in one mysqli_query statement?
No, but if it was executed with mysqli_multi_query then yes you could add multiple queries on to the end.
is making the above safe just as easy as mysqli_real_escape_string?
Generally yes but a Prepared Statement would be better. Using escaping, the WHERE clause would become (using my example above):
WHERE id = '\' or 1 or \'';
This is no longer vulnerable because the quotes can't be broken out of, and would only match rows if the name literally matches ' or 1 or ' which is obviously unlikely.
It seems to me like the input from the user would be contained inside the single quotes
All the attacker has to do is put a single quote inside the name POST data, and it won't be any more.
name=' OR 1=1
Also, is making the above safe just as easy as this
That looks OK … but it hurts my eyes. Use prepared statements. They are much easier to read then SQL built by concatenating strings together.
Basic explaination:
If you simply insert $_POST['name'] into the query as per your first example, the resulting SQL string will be invalid if the name variable contains a single quote character.
This will immediately annoy anyone named O'Brien, or similar.
But this can then be exploited by a hacker, who could modify his "name" to include valid SQL code after the single quote. This could be any valid SQL, allowing the hacker to do anything to your DB or query anything from it. Exactly what he can do would depend on other factors in your code, but suffice to say that even in the best case scenario, he could do some pretty devastating things.
To answer your second question: Yes. Escaping using mysqli_real_escape_string() will mitigate this problem.
However, to take things one step further, you might also want to investigate using Prepared Queries, which is a feature of the mysqli extension. This can make your code a lot neater as it avoids having to use that nasty long mysqli_real_escape_string() function name all over the place. It also has other benefits such as improved query caching.
Hope that helps answer the question.
What if I passed the following value for $_POST['name']?
'; DELETE FROM users WHERE name <> '
I would be closing the first single quote, then introducing the damaging query which just has a single open quote at the end, which would be closed by the single quote in your original query.
You second query is fine. Though you really ought to consider use of prepared statements (which are supported by mysqli)
If you're using mysqli you should always be using the SQL placeholder method for doing this. The escaping functions are the hard way.
$stmt = $db->prepare("SELECT name FROM users WHERE id = ?");
$stmt->bind_param('i', $_POST['name']);
$stmt->execute();
If you don't understand the risk here, you really need to read up on SQL injection attacks in general, and read what automated hacking tools can do to those that aren't cautious enough.
How to prevent in codeigniter to not insert single quotes around in our query?
When we write query in codeigniter it inserts automatically single quotes, like this:
$this->db->select('id, ifnull(name,\'\') as name');
$this->db->from('table');
which creates database error.
$this->db->select('id, ifnull("name",\'\') as name', false);
$this->db->from('table');
Is what you're after. The quotes are escaping to stop sql injection, be sure not to mix unsanitized input from the user.
I guess I should also note that using this false parameter will stop double quote encapsulation, if you're using postgres you'll probably need to encapsulate any kew words used as column names yourself. (see difference between name and "name")
Active Record - Selecting Data
I have a query that looks at a list of files inside a folder and enters the names of everything into a database so I can control the sort when showing the images.
Now I had an image today which had a name of image123('2).jpg. The single quote caused my query from crashing so how can I get around this? To make things simpler I have made example scenario
I have list of 4 variables which have the following strings
$myVAR1 -- "MyName IS Leo";
$myVAR2 -- "MyName IS 'Tiger";
I am running a SQL query to enter them into a database
$sql = "INSERT INTO `names` (`StringID`, `StringValue`) VALUES (NULL, ' $myVAR1');";
$sql2 = "INSERT INTO `names` (`StringID`, `StringValue`) VALUES (NULL, ' $myVAR2');";
So how can I detect that the single quote is inside the string $myVar2 and how can I ignore it when entrying into the database?
You need to escape your data. Use prepared queries with PDO so you don't have to worry about this.
You are currently wide open to SQL injection.
At a minimum, use mysql_real_escape_string(), assuming you are using the standard MySQL library in PHP. It takes care of quotes, among many other things, escaping them properly so they will be inserted into your database.
Is the any difference between writing
{$_GET['id']}
and
'".$_GET['id']."'
in a sql statement? both works the same
Its always a bad idea to put data from a get request directly into SQL, and there are many easy ways to prevent SQL injection.
For the simple case where you know you want a numeric ID, then you can simply force the value to be numeric and then there is no chance of SQL injection. One way might be okoman's usage of sprintf(), maybe something like this:
$sql = "INSERT INTO table VALUES(".sprintf("%d",$_GET['id']) .")";
though I think its ugly and bad form. Something like this is nicer:
$sql = "INSERT INTO table VALUES(".(int)$_GET['id']) .")";
Which simply casts the value to an int - if its not a number that can be cast to int - you'll get a "0" which may or may not be what you want.
Other alternatives (and for when your data is not supposed to be a number) include using escaping functions such as add_slashes() or the above mentioned mysql_real_escape_string().
IMHO, the best way to use database access from within PHP and very easily protect from SQL injection is to use the new PHP PDO library ( http://php.net/PDO ). This allows you to write SQL strings that contain no data whatsoever, and have the data added later inside the database server itself. In this form there is absolutely no way to do SQL injection.
Here is some example code:
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
$stmt = $dbh->prepare("INSERT INTO table VALUES (?)");
$stmt->bindParam(1, $_GET['id']);
$stml->execute();
As you can see, the data is not added to the SQL query itself and so no need for escaping.
Using either of these directly in a SQL statement is a VERY BAD IDEA. It allows for SQL injections. Be sure to sanitize your inputs using something like mysql_real_escape_string.
The main difference between the two is that the top can only be used inside a string that uses double quotes. The bottom, however, can be used with either double or single quotes.
As far as I know there's no difference, but should you be doing that? You're allowing unsanitised input into your sql query which means if your website is internet facing you're leaving it wide open to sql injection attacks.
Here's a Q&A you should read before going any further:
How can I prevent SQL injection in PHP?
If you use a variable - especially an associative array - in a string, you can be quite sure that it will lead to errors. It's just bad style.
I - personally - don't like the second alternative either.
sprintf( '... %d ...', $_GET[ 'id' ] );
That's my favorite way of putting a variable into a string.