You can't 'protect' the actual data coming in, but you can clean it for DB input.
You can check the data type / validate the value.
If it passes the validation, you then clean it with mysql_real_escape_string(). No need for anything else. Just be careful with integer placeholders in queries. As they aren't quoted, mysql_real_escape_stringed value can still cause havoc - that's why you MUST check to see if the value is an integer/float etc.
diafol
Rhod Gilbert Fan (ardav)
7,792 posts since Oct 2006
Reputation Points: 1,170
Solved Threads: 1,080
To clarify, if you've got a numeric placeholder in the query, it could be a problem:
SELECT * FROM users WHERE user='$u' AND password='$p'
is fine as there are '' single quotes about the placeholder, however, when you get:
SELECT * FROM users WHERE id=$id
is susceptible as there are no '' about the placeholder. So, either put the quotes in - it'll still work, but I'm not sure about a performance hit. OR ensure your validation routine on $id is foolproof.
diafol
Rhod Gilbert Fan (ardav)
7,792 posts since Oct 2006
Reputation Points: 1,170
Solved Threads: 1,080
No performace hit with this I shouldn't have thought.
diafol
Rhod Gilbert Fan (ardav)
7,792 posts since Oct 2006
Reputation Points: 1,170
Solved Threads: 1,080
$user = mysql_real_escape_string($user),
$password = mysql_real_escape_string($password);
$query = "SELECT * FROM users WHERE user='$user' AND password='$password'";
Do you need sprintf? I though you had to have LIKE in the sql to use wildcards, otherwise % is a literal. DOn't quote me on that - I may be wrong!
diafol
Rhod Gilbert Fan (ardav)
7,792 posts since Oct 2006
Reputation Points: 1,170
Solved Threads: 1,080
Regarding:
preg_replace('/_/', 'html', preg_replace('/%/', 'html', htmlentities(mysql_real_escape_string($apost))));
You always want mysql_real_escape_string() to be the last operation of that string before including in an sql query. Otherwise it is possible to inject some sql - though unlikely in this example.
An issue is if the mysql encoding does not match that of PHP. This is important since mysql_real_escape_string() makes the mysql encoding into account. The preg_replace() or htmlentities() could return a string with a byte sequence that represents a ' in mysql but really a part of a multibyte character correctly returned by mysql_real_escape_string().
@ardav - good note on using mysql_real_escape_string() only with strings. I've used intval() for intgers but never thought about floats... So you can use floatval() to escape floats?
digital-ether
Nearly a Posting Virtuoso
1,293 posts since Sep 2005
Reputation Points: 461
Solved Threads: 101
@digital-ether
I've used is_int, is_numeric, is_float as opposed to forcing data into various types. perhaps rejecting invalid data is safer than second guessing the user's intentions. Mind you, I've used intval too. Sometimes, it's just less hassle.
I may be missing the point here, but is all this preg_replace and sprintf stuff really necessary? Why can't you just clean your variables and write a normal query?
diafol
Rhod Gilbert Fan (ardav)
7,792 posts since Oct 2006
Reputation Points: 1,170
Solved Threads: 1,080
> The preg_replace was to just try and cover some the sql injection that mysql_real_escape_string and htmlentities doesn't cover.
I'm just a little lost as to what it doesn't cover. AFAIK '%' is fine to use as long as you don't use sprintf. Your choice I suppose.
diafol
Rhod Gilbert Fan (ardav)
7,792 posts since Oct 2006
Reputation Points: 1,170
Solved Threads: 1,080
The preg_replace was to just try and cover some the sql injection that mysql_real_escape_string and htmlentities doesn't cover.
More filters or escaping will NOT improve the escaping of a variable. In fact it does the opposite - makes the filter less secure. (an example of this was an XSS injection with a Google website a couple years ago).
mysql_real_escape_string() is what you use to escape strings you pass to mysql. It is the only escape you need for strings as mentioned already.
htmlentities() is the escape for strings you pass to HTML. That is what you write out to a page, and do not want HTML injection, also known as XSS.
htmlspecialchars() is the escape for strings you pass to XML. This is common for AJAX requests and prevents XML injection.
If you use the wrong filter it is useless. If you combine filters, it does not help. When using a filter or escape function you also need to know the encoding of the string being escaped, otherwise it won't work 100%. For example, you cannot use the same filter for utf-8 string as for ASCII string.
When using htmlentities() you need to specificy the encoding with the third parameter. This must be the encoding of the HTML you send to the browser.
With mysql_real_escape_string() the character encoding is taken from the database table, so it is done for you.
In any case you do not need preg_replace() as you cannot match all characters that can be injected. preg_replace actually replaces on the byte level, not character level. So it does not understand what characters are unless you specify this. It will become very complex and just re-inventing what specific functions like htmlentities() or mysql_real_escape_string() already does.
digital-ether
Nearly a Posting Virtuoso
1,293 posts since Sep 2005
Reputation Points: 461
Solved Threads: 101