MySQL injection prevention not working? - php

I want to prevent the 1=1 using the mysql_real_escape_string but not sure if im doing it right because I can still perform 1=1. This is my code:
$memberId = mysql_real_escape_string($_GET["memberId"]);
$sql = "SELECT firstName, lastName, dateSent, message, messageId FROM member, message WHERE member.memberId = message.sentFromId AND message.inboxId=" . $memberId . " ORDER BY dateSent DESC;";
Thanks

mysql_real_escape_STRING() is for STRINGS, not integers. There's nothing in 1=1 that requires escaping, so m_r_e_s() will pass it back unchanged.
if you're dealing with integers, then use integer tools:
$memberID = intval($_GET['memberId']);

The only correct way to not have SQL injections is using prepared statements.
If you attempt to mitigate using escaping you will fail.
If you as a rule never concatenate your queries and always use prepared statements, you have a chance.
It also has the advantage of making your code more readable.
And has no disadvantages.

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. :)

sql injection vulnerabilities in empty and isset checks

i am currently working on making my site injection proof and was wondering about the validations i am making, my code goes like this:
if(!empty($_POST['city']) && !empty($_POST['street'])){
$city = htmlentities(mysql_real_escape_string($_POST['city']));
$street = htmlentities(mysql_real_escape_string($_POST['street']));
}
my question is isnt the empty check itself is a vulnerability?
i mean do i have to escape string in the !empty validation as well? or it is safe to keep it that way?
thanks.
SQL injection vulnerabilities work like this:
$username = $_GET["username"];
mysql_query("SELECT 1 FROM `users` WHERE `username` = '" . $username . "'");
Now if the value of $_GET["username"] is something like "foo' OR 1=1--"
The query:
SELECT 1 FROM `users` WHERE `username` = 'foo' OR 1=1
--'
will be run which selects all users
If you escape your input you will get the (intended) query:
SELECT 1 FROM `users` WHERE `username` = 'foo\' OR 1=1--'
PHP functions themselves aren't vulnerable.
Maybe this a good analogy: when someone says "Say your name" they want you to say "I'm John" not "your name"
For SQL injection you only need to worry when quering the database, so isset is safe.
There should be no need for htmlentities (use it as protection against XSS).
mysql_real_escape_string will protect against SQL injection if done correctly, but should not be used at all, since the mysql_ prefix / DB-handler is outdated, deprecated and should not be used at all.
The safest way is to use either mysqli_ or PDO, and use prepared statements.

Is this SQL query safe from injection?

The code below is written in php:
$user = addslashes($_POST['user']);
$pwd = addslashes($_POST['pwd']);
$query = "SELECT * FROM userdata WHERE UserName='$user' AND Password=PASSWORD('$pwd')";
the query will then be sent to mysql
Is there anything more I need to take care of?
Please point out.
No it's not safe, use mysql_real_escape_string at minimum:
$user = mysql_real_escape_string($_POST['user']);
$pwd = mysql_real_escape_string($_POST['pwd']);
And for better security go for prepared statements.
Best Options:
PDO
mysqli
You may ask which one to choose, check out:
What is difference between mysql,mysqli and pdo?
Nope.
The reason is that while a single quote ' is not the only char that break a sql query, quotes are the only chars escaped by addslashes().
Better: use mysql_real_escape_string
$user = mysql_real_escape_string($_POST['user'], $conn);
$pwd = mysql_real_escape_string($_POST['pwd'], $conn);
$query = "SELECT * FROM userdata WHERE UserName='$user' AND Password=PASSWORD('$pwd')";
Best: use PDO and prepared statements
$stmt = $dbh->prepare("SELECT * FROM userdata WHERE UserName=':user' AND Password=PASSWORD(':pass')");
$stmt->bindParam(':user', $user);
$stmt->bindParam(':pass', $pass);
No. You should not be using addslashes() to escape your data. That's been obsolete for years. You should be either:
using mysql_real_escape_string() as a replacement
using prepared statements with PDO or MySQLi
Plus using MySQL's Password() function is also poor pracdtive. Use hashes with salts. Bcrypt is my recommendation. Also, check out PHPass.
Protecting against SQL injection is easy:
Filter your data.
This cannot be overstressed. With good data filtering in place, most security concerns are mitigated, and some are practically eliminated.
Quote your data.
If your database allows it (MySQL does), put single quotes around all values in your SQL statements, regardless of the data type.
Escape your data.
Sometimes valid data can unintentionally interfere with the format of the SQL statement itself. Use mysql_escape_string() or an escaping function native to your particular database. If there isn't a specific one, addslashes() is a good last resort.
Read more: http://phpsec.org/projects/guide/3.html#3.2

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.

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