is this safe in terms of SQL injection? - php

Currently getting more and more into MySQL. It's something i haven't been too fussed about but i want to write some scripts with it now.
My question is simple, im making a search script and just want to know if my php code can prevent some SQL injections.. the code:
$orig = $_POST['term'];
$term = mysql_real_escape_string($orig);
$sql = mysql_query("select * from db1 where content like '%$term%' ");
Is this ok? Alternatively if anyone has an easier/better/safer way of doing this plese feel inclined to let me know.

To avoid warnings in case $_POST['term'] isn't set:
if (isset($_POST['term'])) {
$term = mysql_real_escape_string($_POST['term']);
$sql = mysql_query("select * from db1 where content like '%$term%' ");
// rest of sql query
}

Yes, it is safe from SQL injection. If you want to use a more systematic method of avoiding SQL injection issues I would recommend learning to use PDO and parameterised queries.

yes it should be fine with mysql_real_escape_string

The standard escaping is often insufficient for values used in the LIKE clause. Unless you want the user to specify % placeholders of his own, you should add:
$term = mysql_real_escape_string($_POST['term']);
$term = addcslashes($term, "%_");
To be precise, this only an issue for very large tables, where excessive %%%% placeholder injection in LIKE queries could decelerate the database server.

In your case mysql_real_escape_string will prevent SQL injection because it escapse single quotes and your string is set between single quotes. So in any case $term will always be just a simple string for SQL.
If you have something like
select * from A where id = $number
then no escaping would prevent an injection like:
0; drop A;
To prevent this scenario you would go well with prepared statements (PDO) or type-checking.

Related

Protect generic sql query statements

Any way to prevent malicious sql statements without using prepared statements and parameterized queries?
Example after simplify:
<?php
$con = mysqli_connect($_POST['db_server'], $_POST['db_user'],
$_POST['db_password'], $_POST['db_database']) or die(mysql_error());
$result = mysqli_query($con, $_POST['query_message']);
?>
Is it possible to check out the parameter $_POST['query_message'] is safe or not?
You should always build your queries within your code and then sanitise any variables you're going to use within them. NEVER pass the query or the database connection variables in via $_POST unless your user is querying the database via that form, in which case I'd recommend you just install phpMyAdmin.
As for sanitising your variables, if you really don't want to use PDO's prepared statements, you can sanitise incoming integers as follows:
$id = (isset($_POST['id']) ? (int)$_POST['id'] : null);
if ($id) {
$sql = "SELECT *
FROM `table`
WHERE `id` = {$id}";
}
And for strings use this:
$username = (isset($_POST['username']) ? mysqli_real_escape_string($con, $_POST['username']) : null);
if ($username) {
$sql = "SELECT *
FROM `table`
WHERE `username` = {$username}";
}
You can also call real_escape_string() directly on your $con object as follows:
$username = (isset($_POST['username']) ? $con->real_escape_string($con, $_POST['username']) : null);
However, as with #Shankar-Damodaran above, I highly suggest you do use PDO prepared statements to query your database.
Why you don't wanna use Prepared Statements ? That is really weird. I strongly suggest you should go for it.
You could make use of mysqli::real_escape_string for escaping quotes that is commonly used for SQL Injection Attacks.
Something like...
OOP Style
$message = $mysqli->real_escape_string($_POST['query_message']);
Procedural Style
$message = mysqli_real_escape_string($link,$_POST['query_message']);
other way is using:
htmlentities($query);
as an extra you could use preg_match() regular expressions to avoid
the inclusion of certain words (SELECT, DROP, UNION .......)
Example:
try{
$query = sprintf("SELECT * FROM users WHERE id=%d", mysqli_real_escape_string($id));
$query = htmlentities($query);
mysqli_query($query);
}catch(Exception $e){
echo('Sorry, this is an exceptional case');
}
There are real world cases where prepared statements are not an option.
For a simple example, a web page page where you can do a search on any number of any columns in the database table. SAy that table has 20 searchable columns. you would need a huge case statement that has all 20 single column queries, all 19+18+17+16+15+14+13+... 2 column queries, all possible 3 column queries... that's a LOT of code. much less to dynamically construct the where clause. That's what the OP means by prepared statements being less flexible.
Simply put, there is no generic case. If there was, php would have it already.
real_escape_string can be beaten. a common trick is to % code the character you are trying to escape so real_escape_string doesn't see it. then it gets passed to mysql, and decoded there. So additional sanitizing is still required. and when all characters used in injection are valid data, it's a PITA, because you can't trust real_escape_string to do it.
If you are expecting an integer, it's super easy.
$sanitized=(int)$unsanitized;
done.
If you are expecting a small text string, simply truncating the string will do the trick. does't matter that it's not sanitized if there's not enough room to hold your exploit
But there is no one size fits all generic function that can sanitize arbitrary data against sql injection yet. If you write one, expect it to get put into php. :)

Would this work to prevent SQL injection?

Is the code below better at preventing a SQL injection on a MySQL database than mysqli_real_escape_string would be?
$str = "SELECT * FROM customers WHERE username = '; DELETE FROM customers WHERE 1 or username = '";
$str2 = "";
for($i = 0; $i < strlen($str); $i++)
{
if (strpos ("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ,.?!0123456789", $str[$i], 0) !== FALSE)
{
$str2 = $str2 . $str[$i];
}
}
echo "$str2";
There is absolutely no reason to use a whitelist/blacklist when trying to avoid SQL injection. All you need to do when using the mysqli_ functions without prepared statements is to process data with mysqli_real_escape_string().
However, you'd be better off learning about prepared statements instead. They are cleaner and safer than escaping.
The code to execute your example query with prepared statements would look like this:
$stmt = $conn->prepare('SELECT * FROM customers WHERE username = ?');
$stmt->bind_param('s', $username);
$result = $stmt->execute();
Since you don't understand the example, here's a detailed explanation:
Line 1 prepares the statement. You use ? whenever you want to use external data.
Line 2 binds a string (s) parameter for the first placeholder. So $username should contain the (untrusted) value
Line 3 executes the statement with the previously bound parameter. SQL and data is transferred separately so there is no SQL injection risk.
Is the code below better at preventing a mysql injection than mysqli_real_escape_string or does it not matter?
Neither. It is worse and you should not do it! Instead of escaping(!) data(!!) you are breaking your whole query.
In short, it will
make valid queries not work
not prevent malicious queries
Even if you apply your method just on the data, not on the whole query, it will
mess with your data
not prevent all kinds of SQL injection
Read this article. On the bottom, where users comments are, you will find a lot of useful SQL injection prevention tricks and hints.
The first step, however, is to validate and sanitize yout GET/POST data before inserting it into a query.

MySQL Injection Problem

I've been coding my website in PHP lately and I was pretty proud of myself for my good practices of sanitizing my input before I used it in a query. It was all going great until my friend said I need to sanitize my input. When I tried to explain to him that it was sanitized, he showed me that he had found everything in 'users' table in my database. I didn't know how, so I thought I would post what I was doing wrong that made my sanitizing not work. Here is the PHP code he was exploiting:
start_mysql(); // Starts the databases stuff, etc.
$id = mysql_real_escape_string($_GET['id']);
$game = mysql_query("SELECT * FROM `games` WHERE `id` = $id LIMIT 0, 1");
All he was doing was changing the id parameter, making him able to use SQL injection on my database. I thought mysql_real_escape_string escaped all characters like that, but apparently I was wrong. I did some tests with a normal string to see what would happen, and this is what it said
URL: /game.php?id=' OR '' = '
echo($_GET['id']); // This echo'd: \' OR \'\' = \'
echo(mysql_real_escape_string($_GET['id'])); // This echo'd: \\\' OR \\\'\\\' = \\\'
So, my simple question is, what am I doing wrong?
You need to put the escaped string in single quotes:
WHERE `id` = '$id'
Since id was an integer parameter and you did not surround it in single-quotes in your SQL, the value of $id is sent directly into your query. If you were expecting an integer id, then you should verify that the value of $_GET['id'] is a valid integer.
$id = intval($_GET['id']);
Matt,
mysql_real_escape_string() will only filter for certain characters, if you truly want to prevent injection attacks check out this other Stack Overflow article that suggests you use Prepared statements:
Prepared Statements
PHP Manual entry on Prepared statements
Edit: Also check out Slaks and Michael's postings about wrapping your variable in single quotes.
Good luck!
H
Cast ID. If it is a string it will cast as 0.
$id = (int)$_GET['id'];
Also, MySQL support quotes around both string and numbers in the query.
$game = mysql_query("SELECT * FROM `games` WHERE `id` = '$id' LIMIT 0, 1");
You need to use the parameter binding api. The problem is in this piece of code:
WHERE `id` = $id
You are directly interpolating user input into your SQL statement. That's the open barn door for SQL injection attacks.
You're not using parameterized queries.
MDB2 allows this, though that library may be falling out of favor.
It's very likely that your configuration has magic_quote_gpc, an ancien attempt in PHP to make scripts secure magically. It proved to have multiple flaws and was since deprecated and was scheduled to be completely removed in 5.4 the last time I heard of it.
If you have access to your php.ini configuration, you should disable it. Otherwise, you can modify your script to take it into account and sanitize your input.
All of this is documented here: http://www.php.net/manual/en/security.magicquotes.disabling.php
Otherwise, there is nothing wrong with mysqli_real_escape_string().
You can't prevent SQL injections using mysql_real_escape_string(). It is used for escaping special characters like single quotes ('), double quotes ("), etc.
To prevent SQL injections you have to use PDO statements and filter functions in PHP for sanitizing the user data.

Sample code to fix this particular SQL-injection hole

Please read fully first
In this answer: How to prevent SQL injection with dynamic tablenames?
Pekka points out why this code:
$clas=$_POST['clas'];
$query="SELECT * FROM $clas ";
Cannot be repaired by using a PDO or mysql-real_escape_string().
Can anyone please provide sample code how to fix this so a newbie can paste that code
(after/adjusting it to his needs) and be safe from SQL-injection.
Please don't explain SQL-injection, I know all about injection and PDO, I just need sample code
You could use a whitelist to ensure that the value is indeed one of the tables you wish to be accessed in that way.
Example:
$allowed_tables = array('table1', 'table2');
$clas = $_POST['clas'];
if (in_array($clas, $allowed_tables)) {
$query = "SELECT * FROM `$clas`";
}
Note that constructing SQL queries directly from GET or POST parameters is usually a bad idea anyways, but a whitelist can make it safe.
You can use the for escape :P
$clas = str_replace('`','\\`',$_POST['clas']);
$query = "SELECT * FROM \`{$clas}\`";
So, is a ver very bad idea.
Do it different.

Is this sql query vulnerable to injection?

$column = $_GET['id'];
$result = mysql_query("SELECT $column FROM table");
echo $result;
I'm building a website with mysql and am thus trying to learn about sql injections. I assume that this code is vulnerable, but i cant seem to make a working exploit. How would i pull column 'here' from table 'example2'?
Thanks
Imagine $_GET['id'] was equal to something like this
* FROM anytable_i_want; --
the double hypen means the rest of your string is a comment ... so now the sql you're executing is:
SELECT * FROM anytable_i_want;
The single best way to protect from this kind of nonsense is the prepared statement. If you use, say the PDO interface, you do something like this:
$HANDLE = $PDO->prepare('SELECT ? FROM mytable');
$HANDLE->execute(array($_GET['id']));
now no matter what was submitted as $_GET['id'] it woudlnt have any odd effects.
mysql_real_escape_string will cover you if using my mysql_ family of functions, although there is an exploit in the wild that you may be subject to if you change the charset at runtime.
Take a look at PDO and the use of prepared statements to help with preventing SQL injections:
http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/
make $column something like :
" here FROM example2 -- "
if the following text was passed as $_GET['id'], you would have an exploit:
$_GET['id'] = '[other sql commands here]';
use either mysql_real_escape_string() or mysqli_real_escape_string() (if you are using the improved interface)

Categories