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.
Related
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.
For wont of avoiding SQL injection attacks, I'm looking to cleanse all of the text (and most other data) entered by the user of my website before sending it into the database for storage.
I was under the impression that the function inserted backslashes ( \ ) before all characters capable of being malicious ( \n , ' , " , etc ), and expected that the returned string would contain the newly added backslashes.
I performed a simple test on a made up string containing such potentially malicious characters and echo'd it to the document, seeing exactly what I expected: the string with backslashes escaping these characters.
So, I proceeded to add the cleansing function to the data before storing into the database. I inserted it (mysqli_real_escape_string( $link , $string)) into the query I build for data storage. Testing the script, I was surprised (a bit to my chagrin) to notice that the data stored in the database did not seem to contain the backslashes. I tested and tested and tested, but all to no avail, and I'm at a loss...
Any suggestions? Am I missing something? I was expecting to then have to remove the backslashes with the stripslashes($string) function, but there doesn't seem to be anything to strip...
When you view your data in the database after a successful insert, having escaped it with mysql_real_escape_string(), you will not see the backslashes in the database. This is because the escaping backslashes are only needed in the SQL query statement. mysql_real_escape_string() sanitizes it for insert (or update, or other query input) but doesn't result in a permanently modified version of the data when it is stored.
In general, you do not want to store modified or sanitized data in your database, but instead should be storing the data in its original version. For example, it is best practice to store complete HTML strings, rather than to store HTML that has been encoded with PHP's htmlspecialchars().
When you retrieve it back out from the database, there is no need for stripslashes() or other similar unescaping. There are some legacy (mis-)features of PHP like magic_quotes_gpc that had been designed to protect programmers from themselves by automatically adding backslashes to quoted strings, requiring `stripslashes() to be used on output, but those features have been deprecated and now mostly removed.
MySQL stores the data without the slashes (although it is passed to the RDBMS with the slashes). So you don't need to use stripslashes() later on.
You can be sure that the string was escaped, cause otherwise, the query would have failed.
I'm looking to cleanse all of the text (and most other data) entered by the user of my website
This is what you are doing wrong.
mysqli_real_escape_string does not "cleanse" anything. There is no word "cleanse" in it's name.
You should format, not "cleanse" your data. And different data require different formatting.
You should format ALL the data, not only data entered by the user of my website
In the current form you are leaving your site highly vulnerable to attacks and errors.
I was under the impression that the function inserted backslashes ( \ ) before all characters capable of being malicious ( \n , ' , " , etc ),
To let you know, there is nothing malicious in any character. There are some service characters, that can be misinterpreted in some circumstances.
But adding backslashes doesn't make your data automatically "safe". Some injections doesn't require any special characters. So, you need to properly format your data, not just use a some sort of magic that will make you magically safe
Do I need to escape/filter data that is coming from the database? Even if said data has already been "escaped" once (at the point in time where it was inserted into the database).
For example, say I allow users to submit blog posts via a form that has a title input and a textarea input.
A malicious user submits the blog post
title: Attackposttitle');DROP TABLE posts;--
textarea: Hahaha nuked ur site noobzors!
Now as this is being inserted into my database, I am going to escape it with mysql_real_escape_string, but once it is in the database I will later reference this data in my php blog application with something like this:
sql="SELECT posttitle FROM posts WHERE id=50";
$posttitlearray = mysql_fetch_array(mysql_query($sql));
This is where my concern is, what if I, for example, run the following query to get the post content:
sql="SELECT postcontent FROM posts WHERE posttitle=$posttitlearray[posttitle]";
In theory am I not sql injecting myself? IE, am I not effectively running the query:
sql="SELECT postcontent FROM posts WHERE posttitle=Attackposttitle');DROP TABLE posts;--";
Or does the "Attackposttitle');DROP TABLE posts;--" data continue to be escaped once it is in the database?
Do I need to continually escape it like so:
sql="SELECT postcontent FROM posts WHERE posttitle=msql_real_escape_string($posttitlearray[posttitle])";
Or is the data safe once it has been escaped initially upon first being inserted into the database?
Thanks Stack!
It does not continue to be escaped once it's put in the database. You'll have to escape it again.
$sql="SELECT postcontent FROM posts WHERE posttitle='".mysql_real_escape_string($posttitlearray[posttitle])."'";
The value should be escaped every time just before insertion to SQL query. Not for magical security reasons, but just to be sure that the syntax of the resultant query is OK.
Escaping the string sound magical to many people, something like shield against some mysterious danger, but in fact it is nothing magical. It is just the way to enable special characters being processed by the query.
The best would be just to have a look what escaping really does. Say the input string is:
Attackposttitle');DROP TABLE posts;--
after escaping:
Attackposttitle\');DROP TABLE posts;--
in fact it escaped only the single slash. That's the only thing you need to assure - that when you insert the string in the query, the syntax will be OK!
insert into posts set title = 'Attackposttitle\');DROP TABLE posts;--'
It's nothing magical like danger shield or something, it is just to ensure that the resultant query has the right syntax! (of course if it doesn't, it can be exploited)
The query parser then looks at the \' sequence and knows that it is still the variable, not ending of its value. It will remove the backslash and the following will be stored in the database:
Attackposttitle');DROP TABLE posts;--
which is exactly the same value as user entered. And which is exactly what you wanted to have in the database!!
So this means that the if you fetch that string from the database and want to use it in the query again, you need to escape it again to be sure that the resultant query has the right syntax.
But, in your example, very important thing to mention is the magic_quotes_gpc directive!
This feature escapes all the user input automatically (gpc - _GET, _POST and _COOKIE). This is an evil feature made for people not aware of sql injection. It is evil for two reasons. First reason is that then you have to distinguish the case of your first and second query - in the first you don't escape and in the second you do. What most people do is to either switch the "feature" off (I prefer this solution) or unescape the user input at first and then escape it again when needed. The unescape code could look like:
function stripslashes_deep($value)
{
return is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
}
if (get_magic_quotes_gpc()) {
$_POST = stripslashes_deep($_POST);
$_GET = stripslashes_deep($_GET);
$_COOKIE = stripslashes_deep($_COOKIE);
}
The second reason why this is evil is because there is nothing like "universal quoting".
When quoting, you always quote text for some particular output, like:
string value for mysql query
like expression for mysql query
html code
json
mysql regular expression
php regular expression
For each case, you need different quoting, because each usage is present within different syntax context. This also implies that the quoting shouldn't be made at the input into PHP, but at the particular output! Which is the reason why features like magic_quotes_gpc are broken (never forget to handle it, or better, assure it is switched off!!!).
So, what methods would one use for quoting in these particular cases? (Feel free to correct me, there might be more modern methods, but these are working for me)
mysql_real_escape_string($str)
mysql_real_escape_string(addcslashes($str, "%_"))
htmlspecialchars($str)
json_encode() - only for utf8! I use my function for iso-8859-2
mysql_real_escape_string(addcslashes($str, '^.[]$()|*+?{}')) - you cannot use preg_quote in this case because backslash would be escaped two times!
preg_quote()
Try using bind variables. which will remove the need to escape your data completely.
http://php.net/manual/en/function.mssql-bind.php
only down side is your restricted to using them with stored procedures in SQL server, other database you can use them for everything.
I'm having problems inserting commas (,) in my text fields in html. When I submit it to mysql, it deletes the data. How do I work with this?
I've tried mysql_real_escape_string() but that still doesn't work. I have lots of data, and I don't want to use str_replace either. Is there another alternative?
escape your message before you send it to the server, so it's stored escaped, then unescape it when you print it in your html page.
so... msgTosend = escape(whateverText);
and then when you're printing
msgToPrint = getFromDatabase(unescape(myText))
however, as the comment points out, you're obviously doing something dreadfully wrong altogether.
If you're storing strings (as it sounds) you need to be wrapping them in quotes before you store them. Once you do that no amount of commas can ruin anything. If you're not storing strings, but some other data type, then you should be breaking those out into individual variables on the server before storing anything. The potential for malice or just plain breakage is basically 100% with what it sounds like you're doing.
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.