What is the best function to run my strings through to ensure that MySQL injection is impossible?
Also, will it require running it through another function on the way out to make it display correctly?
See also
Are Parameters really enough to prevent Sql injections?
C# Parameterized Query MySQL with in clause
Can I protect against SQL Injection by escaping single-quote and
surrounding user input with
single-quotes?
Parameterized Queries
A parameter function.
Humor aside, I mean don't dynamically execute user-entered content as SQL if you can at all avoid it. Pass everything as parameters, and reference them from your query instead. See Chad Birch's answer for a good link explaining this.
As Chad says, always use parameterized queries to avoid SQL injection.
To answer the second half of your question, if your output is to a web page then always escape any special HTML characters (&, <, >) to protect against script injection.
Add to parameterized queries the use of input validation within the application. Never trust that the input is clean. Check it. For instance, if it's supposed to be an integer, check to make sure it converts to a numeric value without issue.
In PHP the best way is to use HTML escaping on strings.
It turns special characters into HTML compliant characters.
Example: " " (space) transforms into "%20".
Related
select name from movies where id = 1; gives me
name
----------
How the 'A' Stole Christmas
How would I select in order to get
name
----------
How the \'A\' Stole Christmas
I can use replace(title,'\'','\\\'') which turns ugly since I need to do it twice one for single & double quote, Curious to know if there is cleaner approach
Struggling with escaping characters is a sign that you may be unnecessarily converting strings manually as data flows through different systems. The question I would ask is whether it is necessary to have escaped strings for your requirements.
When constructing and executing your queries you should use bind variables which removes the need to quote strings to build up your Sql queries and minimizes the risk of Sql injection security issues.
See http://php.net/manual/en/mysqli-stmt.bind-param.php
Once you have Sql results in a variable or PHP structure it is often better to find functions/libraries such as JSON functions described at https://coderwall.com/p/p2kumg/json_encode-vs-serialize-with-php-arrays
And of course there's http://www.w3schools.com/php/func_string_addslashes.asp as mentioned by D4V1D as a comment.
Edit ...
There also appears to be a Mysql QUOTE() function that does what you are asking.
See http://www.w3resource.com/mysql/string-functions/mysql-quote-function.php
So I have been developing a little system in which, at a point, the user can type in some HTML into ckeditor, that HTML is then stored in a database (it's kind of a microCMS).
The problem is When using Mysqli, It inserts escape characters before and after " and ' in order to stop injection, logically, which breaks loads of HTML code.
for example
becomes
or somthing close to that, which breaks the code
Is there a way i can disable the injection prevention, or input it into the database another way ? Or mabi replace the /" when it is being taken from the database ?
Thanks
-jman6495
EDIT :
I have resolved the problem
I replaced the /" by " using the php str_replace function.
here's the code :
$pagecontent = str_replace('\"','"',$pagecontent);
echo $pagecontent;
thanks anyway
-jman6495
If you're seeing these characters when you fetch data back out you're somehow double-escaping the content. Check that you're only escaping it once, and doing it with the placeholder and not mysql_real_escape_string. You haven't fixed the problem. You've un-done the damage of a serious bug.
The purpose of SQL escaping is to insert the data correctly and reliably. For instance, O'Reilly should be O''Reilly for MySQL. The actual content in the database should be O'Reilly regardless of quoting.
I want to make sure rogue users can't damage my site or database by inserting code in my input fields.
What kind of code should I use to test it?
I know there are html tags like iframe but I don't know what to put inside to test it.
Thanks.
HTML
I think using htmlspecialchars(doc) (It's a function in PHP but other language may has similar function) or using other markup system(?)s like phpBB and MediaWiki would be work. Using HTML tags by black/whitelisting tags can work but it's quite dangerous - a cracker would harm your site by XSSing.
For example, you may think that only allowing p, br, img, font, a is OK (BTW, it's not good to use font when one can use CSS), but XSS can be done by input <img src="asdf" onerror="alert('hi')"/> or <a href="javascript:alert('hi')">.
SQL
You should aware of SQLi - injecting SQL commands.
An example of SQLi is :
A way to avoid being SQLi'd in PHP is using mysql_real_escape_string(doc).
You could read about SQL Injections
Insert special characters, especially ', ?, ", $, ;, , and \. If your site doesn't fail on those, you're on the right track.
But the best is to use queries with parameters. You just pass the string as a parameter and the database takes care of escaping the characters for you. You can hardly make a mistake if you do that.
It really depends on the architecture and user interaction with your site.
SQL injection into user entered fields is a typical attack on systems that use databases for user logins etc. Hence restrictions on characters entered into user fields and screening them before use.
"About your son ..."
"Oh Little Billy !drop tables ?"
In field post_content I have a string like this in nearly 800 rows:
http://somesite.com/">This is some site</a>
I need to remove everything from "> onwards so that it leaves just the URL. I can't do a straight find and replace because the text is unique.
Any clues? This is really my first foray into MySQL database modifications but I did do an extensive search before posting here.
Thanks,
~Kyle~
From this site: http://www.regular-expressions.info/mysql.html
LIB_MYSQLUDF_PREG
If you want more regular expression power in your database, you can consider using LIB_MYSQLUDF_PREG. This is an open source library of MySQL user functions that imports the PCRE library. LIB_MYSQLUDF_PREG is delivered in source code form only. To use it, you'll need to be able to compile it and install it into your MySQL server. Installing this library does not change MySQL's built-in regex support in any way. It merely makes the following additional functions available:
Here it comes...
PREG_CAPTURE extracts a regex match from a string. PREG_POSITION returns the position at which a regular expression matches a string. PREG_REPLACE performs a search-and-replace on a string. PREG_RLIKE tests whether a regex matches a string.
Sounds exactly what you're looking for.
All these functions take a regular expression as their first parameter. This regular expression must be formatted like a Perl regular expression operator. E.g. to test if regex matches the subject case insensitively, you'd use the MySQL code PREG_RLIKE('/regex/i', subject). This is similar to PHP's preg functions, which also require the extra // delimiters for regular expressions inside the PHP string.
See this post: How to do a regular expression replace in MySQL?
Either that or you could just write a script in any lanugage which goes through each record, does a regex replacement and then updates the field. For more info on regex, see here: http://www.regular-expressions.info/reference.html
There's a number of options. One might be to use SUBSTRING_INDEX():
UPDATE
table
SET field = SUBSTRING_INDEX( field, '">', 1 )
It's possible - there is a syntax for User Defined Functions which would let you pass in a regular expression pattern that matches the link and strips everything else.
However, this is quite complicated for somebody new to MySQL, and from your question, this sounds like a one-off. In which case - why not just use Excel and then reimport the data?
Great stuff!
All seems doable with a little bit of time and self education.
In the end, I exported that table as a CSV in Sequel Pro and did some nifty find and replace work in Coda. Not as sophisticated as your suggestions, but it worked.
Thanks again,
~Kyle~
To prevent SQL injection, is it necessary to use mysql_real_escape_string(), when magic_quotes_gpc is on?
For some rare encodings, such as GBk - yes.
But you should revert it not for this reason. Magic quotes should be turned off anyway (and will be in the next PHP version). So, mysql_real_escape_string() is the only escape function is left. Note that it is not sql injection prevention function. Many many people don't understand this point: it's just a part of syntax. It must be used not to "protect" anything, but to assemble syntactically correct SQL query. And must be used every time you build your query, no matter where data come from. Sure it will protect you from SQL injections too, as a side effect.
Of course, mysql_real_escape_string() works only within quoted strings. So, if you do
$num=mysql_real_escape_string($num);
$sql="SELECT INTO table SET data=$num"; /BAD!!!
It will protect nothing.
If you going to use numbers unquoted, it must be cast to the proper type obligatory, like this:
$num=intval($num);
$sql="SELECT INTO table SET data=$num"; /GOOD
Keep in mind that mo make mysql_real_escape_string() works as intended, proper client encoding should be set, and it is possible only with mysql_set_charset() function, SET NAMES query will not set that.
If you want to get rid of all these complexities, you can use prepared statements, though you will need to switch your mysql driver to mysqli or PDO.
Please note that no proper syntax nor prepared statements would not help you with query parts other than literals. You can't escape Identifiers or operators. If you happen to use these parts dynamically, they must be hardcoded in your script, like this (for the ORDER BY clause):
$orders=array("name","price","qty");
$key=array_search($_GET['sort'],$orders));
$orderby=$orders[$key];
$query="SELECT * FROM `table` ORDER BY $orderby";
or this (WHERE clause)
$w=array();
if (!empty($_GET['rooms'])) $w[]="rooms='".mysql_real_escape_string($_GET['rooms'])."'";
if (!empty($_GET['space'])) $w[]="space='".mysql_real_escape_string($_GET['space'])."'";
if (!empty($_GET['max_price'])) $w[]="price < '".mysql_real_escape_string($_GET['max_price'])."'";
if (count($w)) $where="WHERE ".implode(' AND ',$w); else $where='';
$query="select * from table $where";
Looking at the documentation; http://php.net/manual/en/function.mysql-real-escape-string.php
Note: If magic_quotes_gpc is enabled, first apply stripslashes() to the data. Using this function on data which has already been escaped will escape the data twice.
You can check if magic_quotes_gpc is on, see example; http://php.net/manual/en/function.get-magic-quotes-gpc.php
yes its good practice to run all values that are going into your sql statement through the filter mysql_real_escape_string() its not just quotes that the filter is fixing.
it prevents injection attacks, see the example on the php manual for the method.
http://php.net/manual/en/function.mysql-real-escape-string.php
No and yes. If magic_quotes is turned on and mysql_real_escape_string is applied, then some escapes will be doubled, which results things like "It\'s an example." I saw on some forums. For best practices, you should disable magic_quotes and use mysql_real_escape_string all the time, or even better, use a DB abstraction library.