This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 6 years ago.
If user input is inserted without modification into an SQL query, then the application becomes vulnerable to SQL injection, like in the following example:
$unsafe_variable = $_POST['user_input'];
mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')");
That's because the user can input something like value'); DROP TABLE table;--, and the query becomes:
INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')
What can be done to prevent this from happening?
The absolute minimum you need to do here is escape that variable:
$unsafe_variable = mysql_real_escape_string($_POST['user_input']);
Nothing in your query has to change at that point. This is not necessarily the end of the story, though, as mysql_real_escape_string is not invulnerable and you remain exposed to injection attacks by those using more sophisticated techniques.
The entire mysql_query API has been trashed, it's obsolete and the latest version of PHP no longer supports it. You need to move on to something better, and I'd recommend PDO as a baseline.
The best way to be sure you're doing it right is to use prepared statements with placeholder values. That is your query looks like this:
INSERT INTO table name (column1) VALUES (:column1)
With PDO you can name your placeholders. This makes executing your statement later very easy, you just match up the values:
$stmt->execute(array('column1' => $_POST['user_input'));
So the best way to avoid injection bugs is to avoid injection in the first place. Placeholder values will be substituted correctly, safely, and most important, consistently. All it takes is one mistake where you thought you escaped something but you didn't and people can bust your site wide open.
Related
Is it a good idea to use:
// input can only contain numbers letters
if (preg_match('/^[a-zA-Z0-9_\-\.]+$/', 'input')) {}
Will this help preventing SQL injections ? and make site more secure?
I will begin by saying that you absolutely should be using PHP Prepared Statements here. Do not try to handle SQL injection yourself, and besides this problem was solved a long time ago.
Your pattern might block certain types of SQL injection. For example, let's say you had the following SQL query:
SELECT col1, col2 FROM some_table WHERE col = ?;
Your regex pattern would prevent someone from injecting 'value'; DELETE FROM some_table into the query. This is because your regex pattern doesn't allow for semicolon.
However, there are other types of injection attacks which don't involve chaining on additional (malicious) statement. Union attacks can also happen, and your current regex does allow for this. Consider injecting the following fragment:
'value' UNION ALL SELECT username, password FROM users
This would give the following full SQL query:
SELECT col1, col2 FROM some_table WHERE col = 'value'
UNION ALL
SELECT username, password FROM users;
While it would probably be unlikely that the attacker would be able to pull this off, it could happen, and if it did, the attacker could get every username and password from a totally different user table.
Use prepared statements and forget about handling this problem yourself.
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 7 years ago.
If user input is inserting without modification from SQL query, then the application becomes vulnerable to SQL injection, like in the following example:
$unsafe_variable = $_POST['user_input'];
mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')");
That's because the user can input something like value '); DROP TABLE table;--, and the query becomes:
INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')
What can be done to prevent this from happening?
There is extensive information through simple Google searches that can guide you in the right direction. To start though:
DON'T USE MYSQL_* FUNCTIONS These are deprecated and will generate warnings. They are not even remotely good practice for modern web development.
USE A DATABASE LIBRARY INSTEAD like PDO or MySQLi. There's plenty of tutorials to get you started and most importantly these libraries take care of SQL injection for you. So use them!
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 7 years ago.
I read so much about types to prevent sql injections. I probably don't want to use prepared statements if there is another way to prevent them by 100% of the cases.
Currently I'm sticking to this:
$safe_var = mysql_real_escape_string ( $unsafe_var);
mysql_set_charset("utf8");
$sql = "REPLACE `news` (`id`, `author`, `title`, `text`, `time`)" . "VALUES ('".$id."', '$author', '$title', '$text', UNIX_TIMESTAMP());";
mysql_query ( $sql );
For this example all the variables in the sql statement are constructed as the safe_var at the start. I see many opinions on what is save in sql and what not so I don't know what is right.
My question is, is this 100% save and is it save to use this way in every possible sql statement, by using mysql_real_escape_string and putting the variables in single quotes as I did in the statement?
Thanks in advance for help!
PS: I know there are many question likes this but everyone keeps saying diffrent stuff and I still not found anyone that says that my way is safe from sql injections in every possible statement.
At the least you would want to convert to mysqli rather than mysql. You would want to also further test the user input as much as possible to ensure it is legitimate.
Highly recommend pdo and prepared statements
There's a lot of warnings about SQL injections here on SO, but no one I've found doesn't really answer, how does it happen? In this question, I'm assuming it's MySQL and PHP.
The basic mysql_ doesn't accept a second query inside a query, right?
So, basically, this
$unsafe = "');DROP TABLE table;--";
mysqli_query($con,"INSERT INTO table (Column) VALUES ('$unsafe'");
doesn't actually do anything harmful? Correct me on this.
I've no experience working with mysqli_, so I'll skip to PDO, and "Prepared statements".
When I started working with PDO, I had a lack of information on it, and basically used it like this, thinking it's safe.
$stm = $pdo->prepare("INSERT INTO table (Column) VALUES ('$unsafe');
$stm->execute();
However, same thing with PDO as with mysql_. It doesn't support multiple queries out of the box, right? Again, correct me on this.
Then, this is consired safe, if I'm not wrong?
$stm = $pdo->prepare("INSERT INTO table (Column) VALUES (?);
$stm->execute(array($unsafe);
How does a malicious user with no access to the database inject malicious data, if multiple queries aren't even supported?
Or are they?
How does a malicious user with no access to the database inject malicious data, if multiple queries aren't even supported?
"SQL injection" is not equal to "second query".
Or are they?
Surely they are.
Second query is just an example. While it can be any valid SQL statement. SQl injection is an exploit of improperly formatted query. If a developer don't format SQL properly, there is a possibility to break from limits of literal and add code to the SQL body.
Is an SQL injection actually possible by adding a second query?
Yes, depends on the API you are using.
Two queries with mysql + php is a fallacy
Source: http://xkcd.com/327/
This will not work with mysql and php without deliberate steps to make it possible, since the normal query function will only execute the first query.
That doesn't mean it's not possible - only that it should be very obvious when it is.
SQL injection is very real
But the above means almost nothing in terms of sql injection. There is a huge, huge amount of information out there about sql injection including a large number of questions here on stack overflow. Taking the example in the question, this is an equivalent attack which would work:
$id = "123 OR 1 = 1 --";
mysqli_query($con,"DELETE FROM table WHERE id = $id LIMIT 1");
i.e. finding an interface to delete my own, e.g., comment, if the id is not escaped it would be trivial to delete all comments. But this example is just the very tip of an iceberg.
Executing arbitrary sql statements are exploitable
This code in the question:
$stm = $pdo->prepare("INSERT INTO table (Column) VALUES ('$unsafe')");
$stm->execute();
Has none of the benefits of using PDO - i.e. any exploit (of the truly massive number) that would work with the mysql/mysqli driver (used naively) will work with pdo used in this way.
Parametrized queries protect against sql injection
Using PDO with prepared statements with parameters escapes values appropriately preventing sql injection attacks, so yes this is safe from injection:
$stm = $pdo->prepare("INSERT INTO table (Column) VALUES (?)");
$stm->execute(array($unsafe));
How does a malicious user with no access to the database inject malicious data
Simply by finding a way to execute sql that either does what they want to do, or gives them the information to do it a different way.
For example:
function login() {
$username = "irrelevant' OR is_admin = 1 --";
$password = hash('irrelevant');
$query = "SELECT id from users where username = '$username' AND password = '$password'";
...
}
How did malicious user get access to the admin functionality on a system with no concern for injection? Very easily.
For general information about injection see the previous references.
somewhere while studying I juz found out something interesting.. It says something as follows:
$query = sprintf("SELECT firstname, lastname, address, age FROM friends
WHERE firstname='%s' AND lastname='%s'",mysql_real_escape_string($firstname),
mysql_real_escape_string($lastname));
using the query like this instead of
$query="select firstname, lastname, address, age FROM friends
WHERE firstname='".$_RETURN['name1']."', lastname='".$_RETURN['name2']."'";
does this seem reasonable.. have u tried this coding ever.. and how it helps prevent any malicious attacks..
First off, what this is about is called is SQL-Injection. It's basically just the possibility to alter queries against the database via user input.
Let's look at an example:
Query:
SELECT temp1 FROM temp WHERE temp2 = 'VAR1';
Now we'll assign VAR1 the value of: '; DROP TABLE *; --
And we'll get:
SELECT temp1 FROM temp WHERE temp2 = ''; DROP TABLE *; --';
With mysql_real_escape_string it would look like this:
SELECT temp1 FROM temp WHERE temp2 = '\'; DROP TABLE *; --'
mysql_real_escape_string 'secures' a string for usage within a query.
But in the end, you should stop using the mysql_* altogether. They're deprecated and considered as insecure when it comes to preventing SQL injection or other means of tempering with the queries.
You should simply stop concatenating queries together like this and start using prepared statements, which not only are easier to use, prevent SQL Injection by default but also can improve the speed of your application.
For PHP there are two extensions which are designed to close the whole mysql_* opened:
mysqli
PDO
And I say it again: Please stop using mysql_*!
As far as I'm aware, mysql_real_escape_string is one of the better ways to prevent SQL injection, short of using prepared statements with mysqli or PDO.
Using formatting functions like sprintf is purely a matter of taste; the big advantage in the first example is that the function mysql_real_escape_string prevents all SQL injections (explained in one of the other answers); unlike the somewhat iffy magic_quotes_gpc feature in PHP, which many people rely on instead.
magic_quotes_gpc automatically escapes things you receive in requests from clients... but it cannot detect so-called second-level injections:
You get a malicious query from a client and store its contents in the database. magic_quotes_gpc prevents SQL injection; the malicious string gets stored correctly.
Later on, you fetch this string from the database and include it in another query. Now the string didn't come out of a request, so magic_quotes_gpc doesn't escape the string. VoilĂ , SQL injection; your data is now probably gone.
Using some means of escaping yourself, either something like mysql_real_escape_string or a database abstraction layer with a query builder (e.g. Adodb), is definitely superior to just hoping for the best.