Inserting URLs into MySQL database - php

I'm having troubles with an insert query with MySQL. Here's what I want to do:
in one of the fields in my table, I want to insert a bunch of URLs and their respective titles. I build up this query like so:
?content=<title of webpage>%%<url of webpage>%%<title of webpage>%%<url of webpage>%%
and so on, depending how many URLs there are.
The problem is if the URL contains something like "?var=somevalue" then my query breaks there since MySQL will think that I am declaring a new variable.
How can I achieve this?

I think that you should escape the sequence with a \
If you are using PHP an option is to use the following command (it has multiple forms):
Procedural style
string mysqli_real_escape_string ( mysqli $link , string $escapestr )
Object oriented style
string mysqli::escape_string ( string $escapestr )
string mysqli::real_escape_string ( string $escapestr )

Here is how to use placeholders in PHP (which I suspect is the language you're using)
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value);
$name = 'one';
$value = 1;
$stmt->execute();
I grabbed that from php.net
Placeholders, using prepared statements serve several functions, but one of them is to separate data from code safely so that the problem you're describing goes away.
Quoting from the site mentioned above:
The parameters to prepared statements
don't need to be quoted; the driver
automatically handles this. If an
application exclusively uses prepared
statements, the developer can be sure
that no SQL injection will occur
(however, if other portions of the
query are being built up with
unescaped input, SQL injection is
still possible).

Related

How to safely insert data to mysql using php pdo

I have this php pdo:
try {
$STH = $db->prepare("INSERT INTO racuni (napomene) VALUES (:12)");
$STH->bindParam(':12', $_POST['napomena'], PDO::PARAM_STR);
} catch (PDOException $e) {
echo $e->getMessage();
}
and now when I try to add this data to mysql:
<script>alert('heheheheheheh')</script>
there is no string escapes? And in database I have the same data:<script>alert('heheheheheheh')</script>
SO,
What is the best, safe way to insert data to mysql using php pdo?
When retrieving values from the database, you need to treat those values as if they are unsafe, as if they might include HTML special characters, or might contain javascript.
To get that value displayed safely in a web page, you need to run that value through a proper escaping mechanism.
PHP provides the htmlentities function to do just that, replacing HTML special characters with suitable replacements. As an example:
$val = htmlentitites("<script>alert('heheheheheheh')</script>");
Would assign something like this to $val
<script>alert('heheheheheheh')</script>
(It might also replace some other characters.) But the end result is if you put that string out on a web page, what you are going to "see" displayed on the web page appears like the original string. That string won't be interpreted as javascript.
Bottom line, you can't assume that because a string is being returned from the database that it's "safe". You must treat it as potentially unsafe.
Does PDO "sanitize" input?
In a word, NO. PDO doesn't sanitize values in SQL statements to remove HTML special characters or other potentially unsafe values.
What the prepared statement with the bind placeholder does is ensure that the value supplied in the statement gets passed into the database, without being interpreted as SQL text.
As an example, using PDO prepared statement with bind placeholder
$sql='INSERT INTO tab (col) VALUES (:val)';
$sth=$db->prepare($sql);
$sth->bindParam(':val', $value);
$sth->execute();
vs. incorporating the value into the SQL statement
$sql = "INSERT INTO tab (col) VALUES ('" ,. $value ."')";
$db->query($sql);
Consider what happens in each case when $value contains this string
foo'); DROP TABLE tab; --
With the first pattern (prepared statement with bind placeholder), that string value gets passed to the database, and stored in the column.
In the second example, incorporating that value into the text of the SQL statement, we get potentially dangerous SQL statements submitted:
INSERT INTO tab (col) VALUES ('foo'); DROP TABLE tab; --')
This an example of what SQL Injection vulnerability is about. And this demonstrates why using prepared statements with bind placeholders thwarts SQL Injection, it defends against a whole swath of nastiness that can happen when we don't treat values as potentially unsafe.
If $value contains the string:
<script>alert('heheheheheheh')</script>
With the prepared statement and bind placeholder, that's the value that's going to be stored in the database. It's just a string. It won't be interpreted as part of the SQL statement.
We can get the same thing to happen with the other pattern, that's vulnerable to SQL Injection, if we use double quotes instead of single quotes around the string literal in our SQL, e.g.
INSERT INTO tab (col) VALUES ("<script>alert('heheheheheheh')</script>")
Or, if we used an "escape string" function
INSERT INTO tab (col) VALUES ('<script>alert(''heheheheheheh'')</script>')
Again, that string gets stored in the database, because it's a valid string. It doesn't matter one whit whether that's got HTML special characters in it.
Bottom line, PDO does not sanitize HTML characters in strings. Your code needs to handle all values returned from the database as if they are potentially unsafe, and run them through the htmlentities or a similar function to "disarm" the values from being interpreted e.g. as javascript.
Using prepared statements is best, which is what you're doing (assuming you're executing the statement (not in your code sample)). Prepared statements escape values to prevent SQL injection, not cross-site scripting.
The value is unchanged entering the database, which is good (IMO). You should filter the values when you output them if needed (for example, htmlentities()).
You can also bind params in the execute method:
$STH = $db->prepare("INSERT INTO racuni (napomene) VALUES (?)");
$STH->execute(array($_POST['napomena']));
First you need to tell PDO to throw exceptions as bellow:
$pdo = new PDO("mysql:host={$dbhost};dbname={$dbname}", $dbuser, $dbpass);
// add this:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Now wrap your database operations in a try - catch block:
try
{
$statement = $pdo->prepare("INSERT INTO racuni (napomene) VALUES (:12)");
$statement->bindParam(':12', $_POST['napomena'], PDO::PARAM_STR);
// etc.
$statement->execute();
}
catch ( PDOException $exception )
{
echo "PDO error :" . $exception->getMessage();
}

Prevent SQL Injection by input type text [duplicate]

This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 8 years ago.
I need some help and very very fast because my database was injected. I need at least a script that won't allow users to use :[Spaces, Sybols like ('*','=','/','.') and a list of words ('SELECT','FROM','WHERE')] in the text fields of my register form.
I heared something about mysql_real_escape_string(). What is this command doing? And don't post links to PHP: mysql_real_escape_string() Manual because I already read that.
There'a a right and a wrong way to approach this. The (usually) wrong way is to try and set up an input sanitation method (like a script) and hope that nothing gets through. It usually doesn't work.
What I recommend you to do is rewrite your PHP SQL queries to use MySQLi prepared statements. These are queries that are first converted from the common SQL syntax ("SELECT... WHERE...") to a statement your engine can work with, and only then are the fields replaced with your input, thus preventing SQL injection.
For example, the (very) susceptible SQL syntax:
"SELECT * FROM users_passwords WHERE user='" + user + "' AND pass='" + password + "'"
Can be converted to the following prepared statement:
"SELECT * FROM users_passwords WHERE user=? AND password=?"
And then, using the command bind_param(), you can safely replace the ? placeholders with your parameters after the statement is prepared. While the original SQL query allows you to use some basic injection techniques (like writing ' OR true OR '), prepared statements will not allow this.
Here's a working example:
// Create a new MySQLi connection object
$db = new mysqli('localhost','db_username','db_password','db_name');
// Create a new prepared statement
$stmt = $db->prepare('SELECT * FROM users_passwords WHERE user=? AND pass=?');
// Bind the parameters, in order, to the statement (s stands for string)
$stmt->bind_param('ss', username, password);
// Self-explanatory
$stmt->execute();
If you are in PHP then why don't you do it in your PHP script. sanitize all your user provided input in GET and POST and then move it forward to DB calls. That is the right way to do it.
I would strongly avoid constructing SQL query strings from any input even if you sanitize it.
The good way for security purposes and performance is to use functions to set the parameters:
for example:
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value);
see http://php.net/manual/en/pdo.prepared-statements.php

How Mysqli_escape_string or Prepared statement can save me from SQL Injection

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.

How to know when escape is necessary for MySQL

I'm in the process of building a site with CodeIgniter. This is the 1st site that I've built myself that interacts with a database. I'm using MySQL for this project. How can I tell if data needs to be escaped before saving it to the database?
I would advice you to accustom yourself to use prepared statements. Especially since you are new to working with databases. The sooner you start using these, the easier it becomes a second nature.
I, for instance, didn't know about prepared statements when I started with databases. And I experienced my own stubborness when I came in touch with them. Because I had accustomed myself to another way of doing things already. Now, this might not be a character trade of yourself, but it doesn't hurt to start as soon as possible with it either way.
Prepared statements allow you to use placeholders in queries. These placeholders can then be substituted with actual values by binding them to the placeholders. This process of binding, automatically escapes the values.
Here's a (simple) PDO example:
$db = new PDO( /* some database parameters */ );
$statement = $db->prepare( 'INSERT INTO table VALUES( :username, :password )' );
$statement->bindValue( ':username', $dirtyUsername );
$statement->bindValue( ':password', $dirtyPassword );
$result = $statement->execute();
// result checking ommited for brevity
There's lot's more possibilities with PDO and prepared statements. For instance you can easily reuse the prepared statement in a loop, as such:
$statement = $db->prepare( 'INSERT INTO table VALUES( :username, :password )' );
foreach( $users as $dirtyUser )
{
$statement->bindValue( ':username', $dirtyUser->username );
$statement->bindValue( ':password', $dirtyUser->password );
$result = $statement->execute();
// result checking ommited for brevity
}
Or pass the placeholder bindings to the execute method, like so:
$statement = $db->prepare( 'INSERT INTO table VALUES( :username, :password )' );
$result = $statement->execute( array(
':username' => $dirtyUsername,
':password' => $dirtyPassword
) );
// result checking ommited for brevity
... etc., etc.
Don't worry about escaping yourself (you WILL screw it up). Use a DB layer where you prepare the statement first, and then add data to it.
In PHP you should use PDO. You write
SELECT * FROM table WHERE key = :key AND value = :value
and then add the data in by calling functions.
If you're using the database class with query bindings, you don't have to do any manual escaping:
The secondary benefit of using binds
is that the values are automatically
escaped, producing safer queries. You
don't have to remember to manually
escape data; the engine does it
automatically for you.
If the data is a string, it must always be escaped.
However, it's better to use parameters instead.
If you are generating SQL yourself rather than using something like PDO, then you must always escape strings.
Escaping strings is a basic requirement of the SQL language. It's what allows you to use characters like apostrophes or backslashes in a string without everything going bad. There is no situation at all in which escaping strings is not required.
Even non-strings will have to be filtered to ensure that they are, indeed, non-strings.
If you are learning, please seriously consider learning something like PDO as many others have said, rather than escaping your own strings.
When in doubt, escape it all. Can't be too safe.
Alright, alright. I get it
ALWAYS ESCAPE
You escape a MySQL query string when any of the string is made up of user input, for example:
in PHP:
$username = ;//VALUE FROM USER INPUT
then your query string is:
"INSERT INTO table ('username') VALUES (".$username.")"
You would have to escape this mySQL query due to the fact the $username variable could potentionally have malicous code inserted by the client to be injected into your database.
When to escape? As soon as your site goes public.

use mysql_real_escape_string() but allow names with apostrophes

I use mysql_real_escape_string() to validate all user inputs before I insert them in a sql database. One of the fields is name, and we've had issues with users with names like O'Reilly. Is there any way to use mysql_real_escape_string() to block injections but allow these names in the db?
The problem is most likely that the apostrophes get quoted twice: first by the evil and deprecated in 5.3 magic quotes and then by mysql_real_escape_string().
What you can do is either disable magic quotes or run stripslashes() on your input values before feeding them to mysql_real_escape_string()
Brief explanation of the problem:
the user enters O'Reilly
magic quotes automatically turn it into O\'Reilly
the script feeds the string through mysql_real_escape_string() which escapes both the backslash and the apostrophe (again) yielding O\\\'Reilly
the query is executed, the quoting is processed and the database understands that you want a backslash and an apostrophe since they where both escaped, and records O\'Reilly
As already mentionned : mysql_real_escape_string is not meant for input validation. If you want to validate inputs, use your own functions or the filter functions from php.
If you have too many slashes added automatically by php, disable magic quotes.
To prevent SQL injection, use parameterized queries with either PDO or mysqli.
+1 for using PDO. I've been using PDO in favour of a MySQL class acting as a database abstraction layer for a few months now and it's a breeze.
Traditionally, developers would use the stripslashes() function on data before applying a function like mysql_real_escape_string(). It's still a good idea to remove slashes from input data, but you can then either use the PDO method for escaping data (PDO::quote($data)) or binding the parameter.
Your query block would then look something like this:
$pdo = new PDO(DSN, DB_USER, DB_PASS);
$sql = "INSERT INTO table (field1, field2) VALUES (:value1, :value2)";
$smt = $pdo->prepare($sql);
$smt->bindParam(':value1', $value1, PDO::PARAM_STR);
$smt->bindParam(':value2', $value2, PDO::PARAM_STR);
$smt->execute();
$rows = $smt->rowCount(); // returns number of rows affected
I hope this helps somewhat. Take a look at http://php.net/manual/en/book.pdo.php for more information on PDO in PHP.

Categories