I just found out because someone had a ' in their last name and it caused the script to not update anything after that. What's the best way to make their last name safe of any potental damaging characters?
You should probably be using prepared statements if you're embedding the SQL to insert records into the DB in your logic. Among other things they will properly escape data values for you (as long as you use them consistently.)
You should use
print htmlentities("O'Brian",ENT_QUOTES);
before inserting into database, it will convert string to
O'Brian
so it is safe to store to database. Keep in mind that this function also escapes double quotes.
More info on escaping string.
Related
I'm trying to update an old program that uses regular MySql queries, runs all the inputs through addslashes() prior to inserting them, and runs the retrieved data through stripslashes() before returning it. I'm trying to update the program to run with Mysqli and use prepared statements, but I'm not sure how to make the transition with the existing data in the database.
My first thought was to write a function to test if slashes have been added, but the general consensus in the answers to similar questions I found was that this isn't doable.
I'm trying to avoid doing a mass update to the database, because it's an open source program and this seems likely to potentially cause problems for existing users when they try to upgrade.
If I continue to use addslashes() prior to inserting using MySqli and prepared statements would this work? What would be the reasons for not doing it this way and instead going the full database upgrade route?
Edit:
Based on a comment that appears to be deleted now, I went and looked at the database directly. All I could find was an ' that had been converted to ' and no slashes. When I pulled out the data it came out fine without running stripslashes(). So do the added slashes just tell mysql to escape the data when it's inserted? Will all the data come out find if I remove the stripslashes()? If so what's the point of stripslashes()?
You have several questions:
If I continue to use addslashes() prior to inserting using mysqli_ and prepared statements would this work?
No, it would not: the added backslashes would then be stored in your database, which is not what you want. In prepared statements the provided arguments are taken literally as you pass them, as in that mechanism there is no more need to escape quotes.
What would be the reasons for not doing it this way and instead going the full database upgrade route?
See above.
So do the added slashes just tell MySql to escape the data when it's inserted?
The added slashes are interpreted when you embed a string literal in your SQL, as that necessarily is wrapped in quotes. For example:
$text = "My friend's wedding";
$sql = "INSERT INTO mytable VALUES ('$text')";
$result = mysqli_query($con, $sql);
The mysqli_query will fail, as the SQL statement that is passed to it looks like this:
INSERT INTO mytable VALUES ('My friend's wedding')
This is not valid SQL, as the middle quote ends the string literal, and so the s that follows is not considered part of the string any more. As the SQL engine does not understand the s (nor wedding and the dangling quote after it), it produces a syntax error. You can even see something is wrong in the way the syntax is highlighted in the above line.
So that is where addslashes() is (somewhat) useful:
$text = "My friend's wedding";
$text = addslashes($text);
$sql = "INSERT INTO mytable VALUES ('$text')";
$result = mysqli_query($con, $sql);
This will work because now the SQL statement sent to MySql looks like this:
INSERT INTO mytable VALUES ('My friend\'s wedding')
The backslash tells MySql that the quote that follows it has to be taken as a literal one, and not as the end of the string. MySql will not store the backslash itself, because it is only there to escape the quote (see list of escape sequences in the documentation).
So in your table you will get this content inserted:
My friend's wedding
Then:
Will all the data come out fine if I remove the stripslashes()?
Yes. In fact, it should never have been in your code in the first place, as it will negatively effect what you get when there truly are (intended!) backslashes in your data. You are maybe lucky that a backslash is a rare character in normal text. Apparently you have not found any backslash in your database data, so it probably did not badly affect you until now. It is an error to think that the addslashes() call during the saving of data had to be countered with a stripslashes() call while reading the data, because, again, MySql had already removed them while writing the data into the database.
If so what's the point of stripslashes()?
There is no point in the context of what you are doing. It only is useful if you have received somehow a string in which there are characters that have a backslash before them, and have the meaning to escape the next character when the string is used in some context. But since you only briefly have such strings (after calling addslashes()) and MySql interprets these escapes by removing the backslashes in the written data, you never again see that string with the additional backslashes.
Situations where you would need stripslashes() are very rare and very specific. For your scenario you don't need it.
I'm trying to sanitize a string to be saved in a db.
First step I took was to use addslashes(), but then I realized it didn't solve many security issues, so I added htmlspecialchars(), and now I have this line of code:
$val=htmlspecialchars(addslashes(trim($val)));
But then I was wondering if it makes any sense at all to use addslashes() on a string that will be processed by htmlspecialchars(), since the latter will "remove" any element that would cause problems, if I'm not mistaken.
In particular, I was wondering if that makes the server work twice without any real need.
You are wrong alltogether. addslashes() is no database escaping function, use the one that comes with your database access extension, like mysqli_real_escape_string().
htmlspecialchars() completey does not makes sense here. Only use it if you want to place a string within HTML - that should be when you output stuff, not when storing it in the database.
I wouldn't use either of those when saving the string to the database.
addslashes() escapes only quote characters and the backslash character (\). It's not adequate for avoiding SQL injection, because the DBMS may use other special characters which would have to be escaped as well. The best way to avoid SQL injection is to use PHP data objects and its support for bind parameters, which let you keep the parameter values out of the SQL string entirely. If PDO isn't an option for some reason, you should at least use a database-specific escaping function, e.g. mysqli_real_escape_string if you're using MySQL, to ensure that all the necessary characters are escaped.
htmlspecialchars() is for use when incorporating a non-HTML string into an HTML page; it escapes characters that are significant to a web browser, such as angle brackets, and has nothing to do with databases. Assuming that you're not generating and storing complete HTML documents in your database, you shouldn't be calling this function on values before putting them into the database. Store what the user actually entered, and call htmlspecialchars() when you retrieve the value from the database and you're about to actually put it into some HTML output.
When I use mysqli->real_escape_string and add a string value to the db such as "who's", it adds the string without modifying the quote in any way. When I check the db, the value within it is "who's".
When I do not use mysqli->real_escape_string and add a string with a single quote like "who's", it just doesn't get added to the database. It is nowhere to be found.
This isn't normal, is it?
Yes, it is. It's a little difficult to answer this question in any more detailed a way than that.
real_escape_string() only escapes the data so it can be safely used in a query, it doesn't modify it in any way. When you don't escape it, the query has a syntax error in it so it fails - and the data is not inserted.
However the safest way to escape your data is to use prepared statements.
It is normal, and correct. the real_escape_string allows your string to be added to the database (including the quote). Without it, the apostrophe is interfering with the SQL, thus likely throwing an error, and that's why it's "nowhere to be found".
What real_escape_string does is, it escapes necessary characters only while adding these in the database. So it's like escaping the same type of quote in a string in PHP, for example:
$str = 'We escape single quotes like in O\'Connor';
And the single quote (apostrophe) there is to prevent the code from breaking, but the string value does not actually contain it. Likewise…
INSERT INTO table (`name`) VALUES ('O\'Connor')
in this example the backslash will not be inserted in the row. This is for security reasons, of course. Check Hackipedia's page to see some possible cases.
Hoping this was what you were asking.
I have some pages that are stored in databases. For security purposes, all the pages is escaped before saved into the DB, but then when i print the page, the HTML-tags are still escaped. Like this
Link
Obviously, that doesn't work very well, so how do i unescape the pages?
I've tried with html_entity_decode without any success.
While data should be escaped before inserting it into the database, it shouldn't still be escaped when you take it out. The root cause of your problem is that it is being escaped twice between collection and examining it after it comes out of the database.
You should track down why it is being escaped twice and fix that.
That may leave the existing data broken though (it depends on if the data is being escaped twice on the way in or if it is being escaped on the way out of the database with magic_quotes_runtime). If so, you will need to clean it up. That form of escaping has nothing to do with HTML and can be reversed with stripslashes.
The clean up will look something like:
SELECT * from database_table
Create a prepared UPDATE statement to update a row
foreach row stripslashes on the data that was double escaped, pass the data to the prepared statement
Use stripslashes(): http://uk3.php.net/manual/en/function.stripslashes.php
Use stripslashes($str) for retrieve the content and remove slashes added during insert content into database.
thanks
mysql database input strings should always be escaped using mysql_real_escape_string() and when they come out, they should be unescaped using stripslashes().
for numbers like id's, those should be converted to integers using int() and then range checked: for instance, AUTO_INCREMENT columns like id's by default start with 1. so for a validation check on anything you get from $_GET[] or $_POST[], check that your int()'ed number is >= 1.
filter all your integers through int().
filter all your real numbers through doubleval(), unless you are working with monetary values and you have your own decimal number class - floating point can mangle money.
I usually escape user input by doing the following:
htmlspecialchars($str,ENT_QUOTES,"UTF-8");
as well as mysql_real_escape_string($str) whenever a mysql connection is available.
How can this be improved? I have not had any problems with this so far, but I am unsure about it.
Thank you.
Data should be escaped (sanitized) for storage and encoded for display. Data should never be encoded for storage. You want to store only the raw data. Note that escaping does not alter raw data at all as escape characters are not stored; they are only used to properly signal the difference between raw data and command syntax.
In short, you want to do the following:
$data = $_POST['raw data'];
//Shorthand used; you all know what a query looks like.
mysql_query("INSERT " . mysql_real_escape_string($data));
$show = mysql_query("SELECT ...");
echo htmlentities($show);
// Note that htmlentities() is usually overzealous.
// htmlspecialchars() is enough the majority of the time.
// You also don't have to use ENT_QUOTES unless you are using single
// quotes to delimit input (or someone please correct me on this).
You may also need to strip slashes from user input if magic quotes is enabled. stripslashes() is enough.
As for why you should not encode for storage, take the following example:
Say that you have a DB field that is char(5). The html input is also maxlength="5". If a user enters "&&&&&", which may be perfectly valid, this is stored as "&&." When it's retrieved and displayed back to the user, if you do not encode, they will see "&&," which is incorrect. If you do encode, they see "&&," which is also incorrect. You are not storing the data that the user intended to store. You need to store the raw data.
This also becomes an issue in a case where a user wants to store special characters. How do you handle the storage of these? You don't. Store it raw.
To defend against sql injection, at the very least escape input with mysql_real_escape_string, but it is recommended to use prepared statements with a DB wrapper like PDO. Figure out which one works best, or write your own (and test it thoroughly).
To defend against XSS (cross-site-scripting), encode user input before it is displayed back to them.
If you only use mysql_real_escape_string($str) to avoid sql injection, make sure you always add single quotes around it in your query.
The htmlspecialchars is fine when parsing unsafe output to the screen.
For the database switch to PDO.
It's much easier and does the escaping for you.
http://php.net/pdo