How to protect from mysql "union select" injection - php

Simple question: how can I protect so that when the user inputs "union select" in a field and then sends it as a parameter to a query mysql won't give an error.
Should I simply check if "union select" is inputed or there are also other keywords that could result in a mysql error?
Here's the SQL protection function I use now:
function sql_protect(&$n){
$n=stripslashes($n);
$n=mysql_real_escape_string($n);
$dntwant = array("\'","\\", "/","\"",")","(","<",">","\\r\\n",";","*","%");
$n = str_replace($dntwant,"", $n);
}
The query has something similar in it:
where column1 like '%$user_input%'

You need two things
Either use PDO, no checking needed PDO does everything.
Or use :
$var = mysql_real_escape_string($_POST['var']);
$query = "SELECT * FROM test WHERE var = '$var' ";
// ^ ^ These single quotes are vital!!
This is all you need to do, forget about stripslashes, and str_replace.
If you want to use dynamic database/table/column names, or you want to inject numbers for the limit clause, be warned mysql_real_escape_string will not work. Neither will PDO.
Nothing will work except for checking the input you are about to inject against a pre-approved whitelist.
See this question on how to do that: How to prevent SQL injection with dynamic tablenames?

Try to prepare and execute the query:
$stmt = $db->prepare("SELECT * FROM test WHERE column1 LIKE ?");
$stmt->execute(array("%{$user_input}%"));

Related

PHP select query returning false

I am having this piece of code:
$result = mysqli_query($con , 'SELECT * FROM messages WHERE group = "'.$_POST['group'].'" ORDER BY date '.$_POST['order'].'');
I don't understand why it is always returning me false. The variables $_POST['group'] and $_POST['order'] aren't empty .
$_POST['group']='PHP'
$_POST['order']='DESC'
The conecction to the database is corect too.
GROUP is a mysql reserved word and needs to be quoted using backticks;
SELECT * FROM messages WHERE `group` = ...
You're also wide open to SQL injection, you should never add un-validated/un-escaped POST data in string format to your SQL. The safest way to do queries with user data is using prepared statements, or - as a less secure alternative - escape the data using mysqli_real_escape_string.
$result = mysqli_query($con , "SELECT * FROM messages WHERE group = '".mysqli_real_escape_string($_POST['group'])."' ORDER BY date '".mysqli_real_escape_string($_POST['order'])."'";
Try formatting the query like this and see if it helps your result. I also added mysqli_real_escape_string() to escape your input, as your query was wide open to SQL injection.
http://php.net/manual/en/mysqli.real-escape-string.php

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

Secure against SQL Injection - PDO, mysqli [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Best way to prevent SQL Injection in PHP
I just found that my website is vunerable.
Since it's connected to a DB and have functions like: Register, Change Password, Notices, etc... and SUPOSING it's fully vulnerable.
What should I look for into the code in order to start making it safe?
I mean, I did some researches and everywhere, everyone says different things about security.
"Use PDO."
"Use mysql_real_escape_string."
"Use addslashes."
What exactly should I look for??
"$_POST" and "$_GET" variables??
"$_SESSION" variables?
SQL querys?
$sql = "select * from user";
$sql = "update user set user="new_user_name";
$sql = "insert into user (user) values ('userid')";
What should I do in each case?
Please, help me to know what and where I must go.
Thank you.
Following are the points to be considered for making safe php application.
USE PDO or mysqli
Never trust any inputs. Consider every variable viz $_POST, $_GET, $_COOKIE, $_SESSION, $_SERVER as if they were tainted. Use appropriate filtering measure for these variables.
To avoid XSS attack use php’s builtin functions htmlentities,
strip_tags, etc while inserting the user input data into the
database.
Disable Register Globals in PHP.INI
Disable “allow_url_fopen” in PHP.INI
Don’t allow user to input more data than required. Validate input to
allow max number of characters. Also validate each field for
relevant datatypes.
Disable error reporting after Development period. It might give
information about database that’ll be useful to hackers.
Use one time token while posting a form. If token exist and matches
the form post is valid otherwise invalid.
Use parametrized database queries
Use stored procedures
You can google for each point for more details.
HOpe this helps
What you should look for: Any data send from the client/user. Sanitize/escape this data.
PDO can sanitize queries (using PDO::prepare) and supports multiple SQL systems.
For MySQL, use MySQLi. mysqli_real_escape_string is the function to use for sanitizing data if you are using MySQL.
None of the SQL queries you provided are actually vulnerable to SQL injection.
SQL injection vulnerabilities happen because SQL input is not properly escaped.
For example:
$sql = "select * from users where user_id =" . $_GET['user_id'];
Consider if I passed in the following:
http://some_server.com/some_page.php?user_id=123%20or%201=1
The query when executed would end up being:
select * from users where user_id = 123 or 1=1
To fix this, use parameterized queries:
$query = "select * from users where user_id = ?"
When you bind the user_id value to the query, the data access layer will escape the input string properly and the following would be executed:
select * from users where user_id = '123 or 1=1' which would not return any rows, preventing the injection
If using PHP and the mysql extension:
$sql = "select * from users where user_id = '" . mysql_real_escape_string($_GET['user_id']) . "'";
Keep in mind you need to escape ALL input that is going into a SQL query:
$sql = "select id_column from some_table where id = 1";
$stmt = mysqli_query($conn, $sql);
if($stmt === false) die(mysqli_error($conn) . "\n");
while($row = mysqli_fetch_assoc($conn, $stmt) {
$sql = "update some_other_table set some_value = 'new value' where some_column = '" . mysqli_real_escape_string($conn, $row['id_column']) . "'";
....
}
This is because values you select from the database might include characters that are not safe for execution in a SQL statement, like the name "O'Hara" or example.
}
I've been using PDO.
An example for that in your case:
<?php
$stmt = $dbh->prepare("insert into user (user) values (?)");
$stmt->bindParam(1, $name);
$name = 'ValueHere';
$stmt->execute();
?>

PHP: using prepared statements and protecting against SQL injection vs escape

I do understand that the prepared statements is the ultimate way to seek protection against the SQL injection. However, they provide coverage in a limited fashion; for example, in cases where I let the user to decide how the order by operation to be ( i.e, is it ASC or DESC? etc ), I get no coverage there with the prepared statements.
I understand that I can map the user input to a pre-defined white list for that. But, this is only possible when a whitelist can be created or guessed thoroughly beforehand.
For example, in the cases I mention above ( the ASC, or DESC ), this can easily be mapped and verified against a list of accepted values. But isn't there a situation where the portion of the SQL statement cannot be verified against a white list?
If such a situation exists, then what's the recommended approach?
If I were to escape the user_input using the underlying database's built-in escape utility (such as mysqL_real_escape_string for mysql) across the board, where would I fail?
I'm asking this question with the assumption that I always construct my sql statements with quoted values - even for integers...
Let's take a look at the following example and reflect upon it..
select {$fields} from {$table} where Age='{$age}' order by {$orderby_pref}
Assume all vars are user supplied.
If I were to mysql_real_escape_string all the variables in the above SQL ( as opposed to using prepared statements which covers me only half-way forcing me to come up whitelists for the other half that it cannot help), wouldn't it be equally safe (and easier to code)? If not, in which input scenario escape utility would fail?
$fields = mysql_escape($fields);
$table = mysql_escape($table);
$age = mysql_escape($age);
$orderby_pref = mysql_escape($orderby_pref);
select {$fields} from {$table} where Age='{$age}' order by {$orderby_pref}
You always need to use white-lists for stuff like table- or column names, whether you use prepared statements or the mysql escape functions.
The problem is that table names and column names are not quoted in single or double quotes, so if you use a function that specifically quotes these characters (and some more of course...), it will do nothing for your table name.
Consider the table name my_table; DELETE * FROM mysql; SELECT * FROM my_table. Nothing in this string will get escaped by mysql's escape functions but it is definitely a string you would want to check against a white-list.
Apart from that the mysql escape functions have a problem with character sets that can render them useless, so you are always better off with prepared statements.
You could use PDO and your life will get easier ... :
# Order
switch(strtoupper($Order)){
default:
case 'ASC':
$Order = 'ASC';
break;
case 'DESC':
$Order = 'DESC';
break;
}
# ID
$ID = 39;
$Username = 'David';
# Query
$Query = $this->DB->Main->prepare('SELECT * FROM Table WHERE ID = :ID AND Username = :Username ORDER BY HellBob '.$Order);
$Query->bindValue(':ID', $ID, PDO::PARAM_INT);
$Query->bindValue(':Username', $Username, PDO::PARAM_STR);
# All good ?
if(!$Query->execute()){
exit('Error');
}
// Results
$Row = $Query->fetch(PDO::FETCH_ASSOC);
You don't have to worry about quotes or SQL injections. You can use simple "white list" as you mention to get variable into your query.

How to avoid SQL Injection in SQL query with Like % Operator. only php mysql

How to avoid SQL Injection in SQL query with Like Operator for only PHP and Mysql?
can this be done using string functions?
or can anybody tell me what should I do to prevent attacks of like % operator?
You can escape the string using mysql_real_escape_string and add the % wildcards afterwards.
When you run the query use mysql_real_escape_string() as follows:
mysql_query("SELECT field FROM table WHERE field2 LIKE '%".mysql_real_escape_string($yourVar)."%'");
There are few things you could do to make it secure.
First of you have to figure out what type of data you will be searching: number, string etc.
I would suggest using PHP's PDO library, preparing the query and binding the value according to the data type you should receive.
Below an example where the received data is supposed to be string. Notice the PARAM_STR.
...
$value = "apple";
$sth = $dbh->prepare('SELECT name FROM fruit WHERE type LIKE :something');
$sth->bindParam(':something', '%'.$something.'%', PDO::PARAM_STR);
$sth->execute();
...

Categories