This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Best way to prevent SQL injection in PHP?
I have been doing some research about SQL Injection but I have some questions that I couldn't find answer to. Isn't it possible to prevent SQL injection attacks on string levels? What I mean is, can't we prevent it by;
Finding illegal characters before processing them through mysql queries?
$postID = $_POST['id'];
if($postID contains characters)
remove characters;
if($postID still contains characters)
then exit;
else
mysql_real_escape_string($postID); //just in case?
continue to do whatever you are doing...
Is it really necessary to use PDO/mysqli stuff? Is it sufficient to analyze your sql strings to be processed in mysql? Please keep in mind that I am not a PHP or MySQL expert while replying. I am someone who is trying to learn about them.
Sure, you can protect against injection with mysql_real_escape_string($postID), as long as you don't mind a query every time you call the function.
PDO and MySQLi provide a lot more than just injection protection. They allow for prepared statements that can protect agaisnt injection without multiple calls to the db. This means faster overall performance. Imagine trying to insert to a table a user record with 30 columns... that's a lot of mysql_real_escape_string() calls.
Prepared statements send all the data at once along with the query and escape it on the server in one request. Mysql DB's support prepared statments, the old php mysql_ libraries don't support them.
Time to move on to mysqli or preferrably PDO--you'll never look back.
I would encourage you to use PDO (PHP Data Objects). It will help against SQL injection and should speed up queries. Also, your application becomes more abstracted from the database.
Something like the following:
$stmt = $conn->prepare("INSERT INTO table_name VALUES(:id, :firstname, :lastname)");
$stmt->bindValue(':id', $id);
$stmt->bindValue(':firstname', $firstname);
$stmt->bindValue(':lastname', $lastname);
$stmt->execute();
If your ID it's an integer, just use
$postID = (int)$_POST['id'];
And of course, validate if $postID it's != zero after that line.
I wouldn't encourage you to use the mysql_ functions anymore because they're deprecated.
Check: http://php.net/manual/en/function.mysql-real-escape-string.php for more information on why the regular mysql_ has been discontinued.
You could switch to mysqli really easy. It really isn't that complicated. Plus if you want to escape characters and you don't want to be replacing every mysql_real_escape_string for the new way of escaping, you could use this function:
function mysql_string_safe($stringtoclean)
{
//In this case,
$safestring = mysqli_real_escape_string('your_handle_here',$stringtoclean);
return $safestring;
}
So then you would replace mysql_real_escape_string for mysql_string_safe.
Mysqli is really similar to mysql_ but It's more secure. I've switched to it and it didn't take too long, it was easy since it was just replacing stuff. Connecting to the database is different too. On the other hand, PDO has support towards different database drivers but if you want to save time and you're not going to switch database drivers, just use mysqli.
Is it really necessary to use PDO/mysqli stuff?
No.
Is it sufficient to analyze your sql strings to be processed in mysql?
No.
Learning Material
MySQL SQL Injection Cheat Sheet
SQL Injection Prevention Cheat Sheet
How to Avoid SQL Injection Vulnerabilities
more security cheat sheets
Coding Security Controls
Don’t write your own security controls! Reinventing the wheel when it comes to developing security controls for every web application or web service leads to wasted time and massive security holes. The OWASP Enterprise Security API (ESAPI) Toolkits help software developers guard against security‐related design and implementation flaws - https://code.google.com/p/owasp-esapi-php/
Just use PDO and prepare your statements.
Related
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 6 years ago.
I'm starting to think about protecting my inputs from SQL injection. I've read about PDO and mysqli and will be using those techniques. While I was researching protection against SQL injection, I had a thought about a technique. Whenever I have an input from a user, I could scan the input string and search for occurrences of "'" or "DROP" and if the string contains those characters, then I could just not proceed. Would this technique prevent a lot of SQL injection?
Thanks for your help.
It is best to go with methods which have gone through rigorous testing before hand, and not try to implement your own.
A problem with your desired solution is, what happens when SQL add a new notation for dropping tables? Or what if they use 'truncate' instead? This is not foolproof.
Just use PDO or SQLi.
If used correctly and as intended, both will stop it; it'd be silly to use a measure like stopping the word DROP -- Imagine if someone types 'dropbox,' for example?
You should escape your input, and consider using prepared statements. This will remove nearly all SQL injection weaknesses. Scanning for specific words is a terrible practice, as it generally annoys legit users, and doesn't stop determined hackers.
Try to use only prepared statement. It one of the best technique ever.
http://php.net/manual/pt_BR/pdo.prepared-statements.php
The best way is to validate all user input against strict patterns to ensure no user data is abnormal, along with PDO prepared statements - this way you may also prevent XSS however it is usually beneficial to sanitize all user generated output as well just in case you didn't properly validate something and a user is able to execute malicious code.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Best way to stop SQL Injection in PHP
MySQL injection protection and vulnerability signs using PHP
Hey i asked a question about my code if its vulnerable to sql injection
The code was this :
$searchData = $_POST['searchData'];
$searchResult = mysql_query("SELECT * FROM songs WHERE songname LIKE '$searchData%' ");
echo $searchResult;
And yess everyone answered that it is ... but i wanted some extra help on how to protect this kind of input from sql injection.
I read about mysql_real_escpape_string addslashes etc. But im confues which is the best one ?
Shoud i combine them ... or how should i structure my code to protect the input
Anyone helpin me with the best solution would be very apercciated.
The best approach is not to mess about with escaping at all; use bound parameters. See e.g. the PHP manual on PDO.
An example:
<?php
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stuff = array('one', 1);
$stmt->execute($stuff);
$stuff = array('two', 2);
$stmt->execute($stuff);
?>
I highly recommend a short book called Essential PHP Security by Chris Shiflett (by O'Reilly) because you are asking a question that has many aspects that need to be covered. SQL Injection protection starts from the HTML all the way to the database with several steps in between to make sure your data is protected from injection.
Short answer: mysql_real_escape_string
Longer answer: prepared statements (using PDO or MySQLi)
Longer-er answer: When possible you should use prepared statements with bound parameters (as Oli Charlesworth said), however, the second best option is to use the escaping mechanism specific to a specific RDBMS. In this case, you would use mysql_real_escape_string instead of addslashes. mysql_real_escape_string is aware of a few things that addslashes is not. addslashes is a glorified str_replace of ' with \'. mysql_real_escape_string is a hook into the MySQL client library's mysql_real_escape_string function. It is aware of a few settings on the server (hence the connection parameter to it), and it is safer than addslashes.
Bound parameters are still safer though. Even though mysql_real_escape_string knows a lot about the connection and so on, a lot of factors can contribute to the security of it. For example, character sets and encodings can be difficult to handle. Bound parameters have a different method of operation, and they do not do escaping like normal queries. As such, they are safer as there is less room for error on things like character encoding and what not.
Would it be possible to prevent mysql injection using the gzcompress (and after retrieving it from the database, the gzuncompress) function? Or is there a reason why this would not work? Or is there a reason that this would not be a good idea at all?
This is a bad idea because
Theoretically, there might be a sequence of data that, when compressed, leads to a SQL injection or simply breaks the query
gzcompressed data can't be properly indexed and searched - you'll have a database full of garbled characters
gzcompression is computationally expensive
simply always sanitize your data before entering it into a database, using the string escaping method of your library (like mysql(i)_real_escape_string()) or parametrized queries.
If you do that reliably, no further protection is necessary.
to protect against SQL Injection attacks, use PDO's parameterized queries.
SQL injection can be prevented 1 of 2 ways. You can use parameterized queries or you can properly sanitize values when building your SQL statements.
Now, what you are suggesting will probably prevent malicious injections into the database, but that does not eliminate the possibility that will introduce SQL syntax errors (effectively SQL injection) into your SQL statements.
Also, by using compression functions, it will eliminate the possibility of viewing or searching the contents of the database without going through decompression.
This is a novel approach to avoiding SQL injection, but will cause you more problems than it actually solves. You really need to stick with the tried and true solutions.
OWASP - SQL Injection
Steve Friedl's Unixwiz.net Tech Tips - SQL Injection Attacks by Example
MSDN - SQL Injection
How would I go about storing potential SQL injection attacks in a database?
Assume first that I have detected a potential attack, and have the offending attack string in a variable and would like to add it to a table containing a log of suspicious events.
What would I need to do to safely insert these strings into a database so that no errors would be produced?
I have a feeling that it will be something along the lines of htmlspecialchars and mysql_real_escape_string... but I wanted to throw it out there to see if anybody else had any ideas!
One thought was to store the attack as an encoded base64 value, but that seems a bit hackish...
FYI, I am writing the application in PHP :)
Any responses would be greatly appreciated!
Always use parameterized queries. If you are using parameters, you don't need to rely on escaping strings and your query will always do exactly what you intend.
e.g.:
$statement = $db->prepare('INSERT INTO table_name (field_name1, field_name2) VALUES (:value, :value2)');
$statement->execute(array(':value' => $value, ':value2' => $value2));
See documentation for PDO prepare here:
http://www.php.net/manual/en/pdo.prepare.php
Use mysqli prepared statements to store the queries, it's the safest method to avoid sql injection. If you're going to display them via a web interface and concerned about XSS/CSRF attacks, use htmlspecialchars() before displaying them.
The same way you are storing any other data.
There is nothing special in storing SQL injection attacks, whatever you call it.
Like Steve Mayne said ... please use php PDO connection with prepared statements. It's the safes right now . Don't user mysql_connect() and subfunctions anymore because it's old and you cannot fully benefit of new mysql / sql / etc .. funcitons .
All I would do is run it though a simple encryption.
Then when you want to show the suspected sql, you would just decrypt it.
This should insure the suspected sql statement does not get executed on your db.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to prevent SQL injection in PHP?
I am working for a video streaming website for my college library. I am using PHP and MySql. I have not used any parameterized queries in this project.
Recently I came to know about SQL injections. Now that my code is almost done and I have to submit the project in the next two days, how can I now ensure that my code is not SQL injection prone?
Converting the whole thing in to a parameterized interface is what I can't do now. What should I do now to avoid SQL Injections on my website?
The basic idea to prevent SQL injections (if not using Prepared Statements) is to escape your data.
When you inject some expected integer value into an SQL query, make sure it's an integer, using intval().
When you have a decimal/numeric field in your table, use floatval().
And when you have a string (char, varchar, text) field in your table, use the function provided by your API to escape strings :
mysql_real_escape_string()
mysqli_real_escape_string()
PDO::quote()
I really recommend that you go back and do it right with parameterized queries. It is the only solid path towards security. It likely won't take too long to do this once you get started.
You should also know that websites are never "finished". When you launch a site, your work has just begun. Fixing security troubles as you learn about them is part of it, and this is no different.
You'll want to make sure any user provided inputs that get used in SQL queries are escaped using the PHP function mysql_real_escape_string and if you are letting people submit text to run htmlentities on the provided text so XXS isn't possible. If possible, white-list user provided input and discard anything else
This is just touching the surface of what you can do but look into query escaping and preventing cross site scripting.
Use PDO (or alternatively mysqli or some abstraction layer) and prepared statements.
Quick example:
$pdo = new PDO($dsn);
$stmt = $pdo->prepare("SELECT name FROM users WHERE id = ?");
$stmt->execute(array($unsafe_id));
$name = $stmt->fetchColumn();
In this example, $unsafe_id will be safe to use. To quote the manual page:
Calling PDO::prepare() and
PDOStatement::execute() for statements
that will be issued multiple times
with different parameter values
optimizes the performance of your
application by allowing the driver to
negotiate client and/or server side
caching of the query plan and meta
information, and helps to prevent SQL
injection attacks by eliminating the
need to manually quote the parameters.
PDO will emulate prepared
statements/bound parameters for
drivers that do not natively support
them, and can also rewrite named or
question mark style parameter markers
to something more appropriate, if the
driver supports one style but not the
other.