iam using this code below, but the character "&" will not be inserted into the db, also when i copy/paste some text from other pages and put it into the db the text ends for example in the middle of the text, dont know why, i tried also addslashes() and htmlspecialchars() or htmlentities().
i read mysqli_real_escape_string() is againt SQL injection attacks and htmlspecialchars() against XSS attachs, should i also combine them ?
$beschreibung = mysqli_real_escape_string($db, $_POST['beschreibung']);
SQL Injection is merely just improperly formatted queries. What you're doing is not enough, stop now. Get into the practice of using prepared statements..
$Connection = new mysqli("server","user","password","db");
$Query = $Connection->prepare("SELECT Email FROM test_tbl WHERE username=?");
$Query->bind_param('s',$_POST['ObjectContainingUsernameFromPost']);
$Query->execute();
$Query->bind_result($Email);
$Query->fetch();
$Query->close();
Above is a very basic example of using prepared statements. It will quickly and easily format your query.
My best guess to what is happening, I'm assuming you're just using the standard:
$Query = mysqli_query("SELECT * FROM test_tbl WHERE Username=".$_POST['User']);
As this query is not properly formatted you may have the quotes in your chunk of text which close the query string. PHP will then interpret everything as a command to send to the SQL server
If you know what you are doing, you can escape indata yourself and add the escaped data to the query as long as you surround the data with single quotes in the sql. An example:
$db = mysqli_connect("localhost","my_user","my_password","my_db");
$beschreibung = mysqli_real_escape_string($db, $_POST['beschreibung']);
$results = mysqli_query(
$db,
sprintf("INSERT INTO foo (beschreibung) VALUES ('%s')", $beschreibung)
);
To get predictable results, I advise you to use the very same character encoding, e,g, UTF-8, consistently through your application.
Related
I was reading lots of forums and answers on Stack over flow regarding SQL-Injection
and i came to know this is very basic level of SQL-injection
$_POST['name'] = 'xyz;DROP Table users';
mysqli_query ('select * from abc where name='."$_POST['name']")
To prevent this
Use mysqli_escape_stirng on any input that comes from user can save me from SQl-injection
Use PDO and prepare statement can also save me from SQL-injection
Q1. What i want to know here how passing data to Mysqli_escape_string can save me from SQL-Injection
$safe_variable = mysqli_escape_String($connection ,$_POST['name'];
How mysqli_escape_string will only save "XYZ" from POST data and leave the rest of the part (if that is the case)
Q2. How PDO will save me from SQL-Injection
$stmt = $dbh->prepare("select * from ABC where name = :name");
$stmt->bindParam(':name',$name);
$name = $_POST['name'];
$stmt->execute();
Any help in this regard his highly appreciated
The problem with incorporating user input into SQL is that in the resulting SQL you can’t tell which parts were provided by the developer and which by the user. That’s why the developer must ensure that user input gets interpreted as intended.
This is where string escaping functions and parameterization come in:
String escaping functions like mysqli_real_escape_string process the value so that it can be securely used in a string literal without fearing it may be interpreted as anything else than string data.
However, it is important to note that the value is actually placed in a string literal and nowhere else as it’s only intended for that specific purpose, i. e., it ensures that the passed data is interpreted as string data only when placed inside a string literal. Unfortunately, the PHP manual fails to mention the string literal part.
Parameterization as implemented by prepared statements separate the SQL and the data parameters. So there can’t be a confusion of SQL code and provided data. With server-side prepared statements first the statement gets prepared having only parameter placeholders and then the parameter values get passed for execution. And whenever a parameter is encountered, the DBMS uses the corresponding parameter value.
As for your specific example:
What i want to know here how passing data to Mysqli_escape_string can save me from SQL-Injection
$safe_variable = mysqli_escape_String($connection ,$_POST['name'];
How mysqli_escape_string will only save "XYZ" from POST data and leave the rest of the part (if that is the case)
It doesn’t because you didn’t put the value in a string literal. However, the following would work:
mysqli_query("select * from abc where name='$safe_variable'")
How PDO will save me from SQL-Injection
$stmt = $dbh->prepare("select * from ABC where name = :name");
$stmt->bindParam(':name',$name);
$name = $_POST['name'];
$stmt->execute();
As already said, you explicitly state what the SQL looks like by preparing the statement. And then you pass the parameters for execution. As the parameterized SQL and its parameters are separated, they won’t mix and a passed parameter value can’t be mistaken as SQL.
Q1:
mysql(i)_real_escape_string() calls MySQL's library function
mysql(i)_real_escape_string, which prepends backslashes to the following
characters: \x00, \n, \r, \, ', " and \x1a.
(http://php.net/mysqli_real_escape_string)
Note that this depends on the character encoding (not workin in this case is SET NAMES ... (security risk!!!), $mysqli->set_charset('utf8'); should be used!). (You can read about encoding in my post Mastering UTF-8 encoding in PHP and MySQL.)
How does it prevent SQL injection?
- Well it prevents breaking the variables context by escaping ' etc, the thing is, that mysql_query and mysqli_query only execute one query per query, that means, it simply ignores ;DROP Table users.
mysqli_real_escape_string DOES NOT prevent inserting code like DROP DATABASE.
Only PDO and/or mysqli_multi_query are vulnerable in this case.
Q2:
The statement is sent to the server first, then the bound variables will get sent seperated and then the statement gets executed, in this case, the security is provided by the database library, not by the client library. You should prefere this.
That means, you first send $dbh->prepare("select * from ABC where name = :name"); to the server and the database knows your bind param will be inserted into the :name placeholder and it will automatically wrap it properly to not break out of its supposed context. The database will try to look for a name value of xyz;DROP Table users and it won't executed any command, just fill that variable space.
I think this is the case for most SQL escaping functions:
They escape the control chars like ;, ', ", ...
So your string
xyz;DROP Table users
Will be escaped by the functions to
xyz\;DROP Table users
So your string now isn't a valid SQL command anymore.
But be aware of HTML tags in the data stored in a DB.
If I insert for example
<script>alert('foobar');</script>
This will be stored in DB and not treated by the SQL escape functions. If you print out the field somewhere again, the JS will be executed by the visitors browser.
So use in addtion htmlspecialchars() or htmlentities() for sanitize user input. This is also true for prepared 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. :)
I wasn't too sure on how to word the title, so I'll try my best to explain here.
I've created a register system and came across a bug that I never took into consideration when developing the system.
When a user types in the input boxes or a textarea, if they use single quotations the data won't be sent to the database as it will be closing the query.
This is my query code:
mysqli_query($uys, "INSERT INTO users SET bandname='$bandname', genre='$genre', location='$location', bio='$bio', password='$password', email='$email', ip='$ip'");
Of course if they don't use single quotations, there will be no error. They can use double quotes fine.
My variables are like this:
$bandname = $_POST['bandname'];
$genre = $_POST['genre'];
$location = $_POST['location'];
What is a way around this? I'm not the best with PHP, still learning so your help will be amazing and will help me lots.
Sorry if this wasn't well explained, if you're confused on what I mean I'll try my best to explain it better
This is a serious issue. What you face here is a wide open SQL INJECTION
You concatenate a query from unsanitized strings - this might lead to any kinds of troubles, where the smallest is getting your whole database deleted...
Don't concatenate query strings without using proper sanitization! In this case, mysqli_real_escape_string is the proper solution.
The most recommendable (is that a word?) solution is using prepared statements wherever possible:
$stmt = $mysqli->prepare("INSERT INTO users SET bandname=?, genre=?, location=?, bio=?, password=?, email=?, ip=?");
$stmt->bind_param("sssssss", $bandname, $genre, $location, $bio, $password, $email, $ip);
$stmt->execute();
Note: sanitization is still important from a content point of view, to prevent issues like XSS attacks, or Javascript injection to pages...
(Also, using PDO promises independence of databases too, it is worth checking it out...)
You need to replace the single-quote with 2 single-quotes, like this:
str_replace("'", "\''", $bandname);
before sending the string to SQL. It will then show in the SQL table as a single-quote.
This should do the trick:
$bandname = mysqli_real_escape_string($_POST['bandname']);
$genre = mysqli_real_escape_string($_POST['genre']);
$location = mysqli_real_escape_string($_POST['location']);
mysqli_query($uys, "INSERT INTO users SET bandname='$bandname', genre='$genre', location='$location', bio='$bio', password='$password', email='$email', ip='$ip'");`
You need to escape your strings, otherwise it's possible to attack your database with sql 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
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.