What is the best way to escape unwanted characters in order to avoid further database syntax errors when executing insert/update queries when submitting forms?
eg. $note = $this->db->escape( $data['note'] );
INSERT query renders a further syntax error.
ie.
$this->db->query("INSERT INTO notes (note_id, note) VALUES ('$note_id','$note')");
as it mentioned in Codeignitier documentation when using query builder class
All values are escaped automatically producing safer queries.
so its safer to use query builder class for both error handling and security
Escaping Queries
It’s a very good security practice to escape your data before submitting it into your database. CodeIgniter has three methods that help you do this:
$this->db->escape() This function determines the data type so that it can escape only string data. It also automatically adds single quotes around the data so you don’t have to:
$sql = "INSERT INTO table (title) VALUES(".$this->db->escape($title).")";
$this->db->escape_str() This function escapes the data passed to it, regardless of type. Most of the time you’ll use the above function rather than this one. Use the function like this:
$sql = "INSERT INTO table (title) VALUES('".$this->db->escape_str($title)."')";
$this->db->escape_like_str() This method should be used when strings are to be used in LIKE conditions so that LIKE wildcards (‘%’, ‘_’) in the string are also properly escaped.
$search = '20% raise';
$sql = "SELECT id FROM table WHERE column LIKE '%" .
$this->db->escape_like_str($search)."%' ESCAPE '!'";
Note:
The escape_like_str() method uses ‘!’ (exclamation mark) to escape special characters for LIKE conditions. Because this method escapes partial strings that you would wrap in quotes yourself, it cannot automatically add the ESCAPE '!' the condition for you, and so you’ll have to manually do that.
Related
I wrote a script to insert record in my DB. The only issue I am getting is when I try to store data which contains ' character then the script does not work and it does not store anything in the DB. For example John's Birthday , Amy's Home etc . Any solution to this problem which allows special character like ' to store in the DB and retrieving them without any harm to security?
mysqli_query($con,"INSERT INTO Story (desc)
VALUES ('$mytext')");
PHP's mysqli_real_escape_string is made specifically for this purpose. You problem is that quotes are being interpreted by MySQL as part of the query instead of values. You need to escape characters like this so they won't affect your query - this is what SQL injection is.
$mytext = mysqli_real_escape_string($con, $mytext);
// continue with your query
Manual: http://php.net/manual/en/mysqli.real-escape-string.php
Filter the variable part of the query through mysqli_real_escape_string.
The table has company names which are not escaped.
My qry looks like
$sql = "SELECT id FROM contact_supplier WHERE name = '$addy' LIMIT 1";
The problem comes in where the company name values in the table are sometimes things like "Acme Int'l S/L".
(FYI: values of the $addy match the DB)
Clearly, the values were not escaped when stored.
How do I find my matches?
[EDIT]
Ahah!
I think I'm we're on to something.
The source of the $addy value is a file
$addresses = file('files/addresses.csv');
I then do a
foreach ($addresses as $addy) {}
Well, when I escape the $addy string, it's escaping the new line chars and including "\r\n" to the end of the comparison string.
Unless someone suggests a more graceful way, I guess I'll prob strip those with a str_replace().
:)
[\EDIT]
Why do you think the data already stored in the table should be escaped?
You should escape data only right before it is written directly into a text-based language, e.g. as a part of an SQL query, or into an HTML page, or in a JavaScript code block.
When the query is executed, there's nothing espaced. MySQL transforms it and inserts, otherwise it wouldn't insert and gives error because of syntax or we escape them for security like sql injection.
So your query with escaped values will be working fine with the data in your database.
If the values were not escaped when stored then they would have caused SQL errors when you tried to enter them.
The problem is that the data is not being escaped when you make the query.
Quick hack: Use mysql_real_escape_string
Proper solution: Don't build SQL by mashing together strings. Use prepared statements and parameterized queries
Another option would be to change your query to this...
$sql = "SELECT id FROM contact_supplier WHERE name = \"$addy\" LIMIT 1";
Use mysql_real_escape_string:
$addy = mysql_real_escape_string($addy);
Or try using parameterized queries (PDO).
Regarding this statement:
Clearly, the values were not escaped when stored.
This is incorrect logic. If the values weren't escaped in the original INSERT statement, the statement would have failed. Without escaping you'd get an error along the lines of syntax error near "l S/L' LIMIT 1". The fact that the data is correctly stored in the database proves that whoever inserted it managed to do it correctly (either by escaping or by using parameterized queries).
If you are doing things correctly then the data should not stored in the database in the escaped form.
The issue turned out to be new-line characters
The source of the $addy value starts out like this
$addresses = file('files/addresses.csv');
I then goes through
foreach ($addresses as $addy) {}
When I escape the $addy string, it's escaping the new line chars and inserting "\r\n" on the end of the comparison string.
As soon as I dropped those chars with string_replace() after escaping, everything went swimmingly
Thanks-a-BUNCH for the help
i use mysql_real_escape_string php function for escape data recieved from a form. my code for recieve form data is :
$std_id = mysql_real_escape_string($_POST['std_id']);
$name = mysql_real_escape_string($_POST['name']);
$family = mysql_real_escape_string($_POST['family']);
for example if enter O'reilly string in name form field , this function work fine and my query done too.but when i go to mysql and my table , see that this string is inserted like O'reilly and not O\'reilly.
my query is :
$sql = "insert into student set
std_id = $std_id,
name = '$name',
family = '$family',
";
this happens when use addslashes() function too.
This is exactly what is supposed to happen. You want to insert the string O'reilly into the database, not O\'reilly, right?
The slashes merely tell MySQL that the next ' is supposed to be a literal apostrophe, and not the apostrophe/single quote denoting the end of the string.
PS: You might want to consider using PDO and prepared statements, which offer a much cleaner syntax.
That's the point. mysql_real_escape_string is only there to make sure the query syntax is correct. This query syntax would be incorrect:
INSERT INTO ... name = 'O'Reilly'
The string terminator ' is ambiguous/misplaced.
Escaped, this becomes:
INSERT INTO ... name = 'O\'Reilly'
Now the syntax is unambiguous, the ' after O is not the string terminator, it's a literal value. That's all mysql_real_escape_string is supposed to do. You do not want the value as "O\'Reilly" in your database, because that's garbage.
You should read The Great Escapism (Or: What You Need To Know To Work With Text Within Text).
I have a TextArea on my website which I write the input into my database.
I want to filter this TextArea input, but without removing any HTML tags or other stuff.
In short, I want to sanetize and securize the input before I write it into my database, but I want the entry to be intact and unmodified when I take back the entry from the database and write it on the website.
How can I achieve this?
If you want to preserve the data character for character when it's written back to the website try:
$stringToSave = mysql_real_escape_string($inputString);
Then when retrieving it from the database:
$stringToPutOnPage = htmlentities($databaseString);
If you want the html to actually be read as html (be careful about XSS) you can just use:
$stringToSave = mysql_real_escape_string($inputString);
Edit: It would seem that best practice is to sanitize the string for html after retrieving it from the database and not before. Thanks for the comments, I will have to change my method.
If you mean you simply want to make it safe to store in your database all you need to do is use the database specific escaping method, for example mysql_real_escape_string. Of course, that doesn't secure you from XSS attacks, but if you want to retrieve and display it unmodified you don't have a choice.
It's really simple:
To avoid SQL injection, mysql_real_escape_string your values before concatenating them into an SQL query, or use parameterized queries that don't suffer from malformed strings in the first place.
To avoid XSS problems and/or messed up HTML, HTML escape your values before plugging them into an HTML context.
JSON escape them in a JSON context, CSV escape them in a CSV context, etc pp.
All are the same problem, really. As a very simple example, to produce the string "test" (I want the quotes to be part of the string), I can't write the string literal $foo = ""test"". I have to escape the quotes within the quotes to make clear which quotes are supposed to end the string and which are part of the string: $foo = "\"test\"".
SQL injection, XSS problems and messed up HTML are all just a variation on this.
To plug a value that contains quotes into a query, you have the same problem as above:
$comment = "\"foo\""; // comment is "foo", including quotes
$query = 'INSERT INTO `db` (`comment`) VALUES ("' . $comment . '")';
// INSERT INTO `db` (`comment`) VALUES (""foo"")
That produces invalid syntax at best, SQL injection attacks at worst. Using mysql_real_escape_string avoids this:
$query = 'INSERT INTO `db` (`comment`) VALUES ("' . mysql_real_escape_string($comment) . '")';
// INSERT INTO `db` (`comment`) VALUES ("\"foo\"")
HTML escaping is exactly the same, just with different syntax issues.
You only need to escape your values in the right context using the right method. To escape values for HTML, use htmlentities. Do that at the time it's necessary. Don't prematurely or over-escape your values, only apply the appropriate escape function in the right context at the right time.
$myq = sprintf("select user from table where user='%s'", $_POST["user"]);
I would like to know if the above query can be exploited using SQL injection. Is there any advanced SQL injection technique that could break sprintf for this particular query?
I don't think it needs to be particularly advanced... try an input of
' OR 1 = 1 OR user='
In other words, you'll get SQL of:
select user from table where user='' OR 1 = 1 OR user=''
Does that look like a query you really want to execute? (Now consider the possibility of it dropping tables instead, or something similar.)
The bottom line is that you should be using a parameterised query.
Yes, I'd say you have a potential problem there :)
You need to escape: \x00, \n, \r, \, ', " and \x1a. sprintf() does not do that, sprintf() does no modification to strings, it just expands whatever variadic arguments that you give it into the buffer that you provide according to the format that you specify.
If the strings ARE being transformed, its likely due to magic quotes (as Rob noted in Comments), not sprintf(). If that is the case, I highly recommend disabling them.
Using sprintf doesn’t give you any more protection than using simple string concatenation. The advantage of sprintf is just having it a little more readable than when to using simple PHP’s string concatenation. But sprintf doesn’t do any more than simple string concatenation when using the %s format:
$str = implode('', range("\x00", "\xFF")); // string of characters from 0x00 – 0xFF
var_dump(sprintf("'%s'", $str) === "'".$str."'"); // true
You need to use functions that escape the contextual special characters you want to insert your data into (in this case a string declaration in MySQL, supposing you’re using MySQL) like **mysql_real_escape_string** does:
$myq = sprintf("select user from table where user='%s'", mysql_real_escape_string($_POST["user"]));
when $_POST["user"] would equal "';SHUTDOWN;" - what would happen?
Actually, turn off magic quotes.
In PHP, where it's appropriate, use filters:
$inUser = $_POST['user'];
$outUser = filter_var($inUser, FILTER_SANITIZE_STRING);
Filters strip out HTML tags and escape various characters.
In addition, you can let your database escape it for you:
$inUser = $_POST['user'];
$outUser = mysqli_real_escape_string($conn, $inUser);
This escapes MySQL specific special characters like double quotes, single quotes, etc.
Finally, you should use parameterized queries:
$sql = "SELECT user FROM table WHERE user = ?";
$stmt = $pdo->prepare($sql);
$params = array($outUser);
$stmt->execute($params);
Parameterized queries automatically add the quotes around strings, etc., and have further restrictions that make SQL injections even more difficult.
I use all three, in that order.
Ahh here I come with the magic answer! :)
magic quotes do escaping for you!
So, you have to turn magic_quotes_gpc ini directive off
and then use mysql_real_escape_string as suggested.
Yes.
If somebody put in the following as the user in your form:
'; delete * from table
$_POST["user"] = "' or 1=1 or user='"