php Prevents SQL injection from being elaborated and prevented

  • 2020-11-18 06:08:32
  • OfStack

One is not filtering the input data (filtering input), and one is not escaping the data sent to the database (escaping output). These two important steps are missing 1, and special attention needs to be paid at the same time to reduce bugs.
For an attacker to perform an SQL injection attack requires thinking and experimentation, and it is necessary to make a well-grounded inference about the database scheme (assuming, of course, that the attacker cannot see your source and database scheme). Consider the following simple login form:

<form action="/login.php" method="POST">
<p>Username: <input type="text" name="username" /></p>
<p>Password: <input type="password" name="password" /></p>
<p><input type="submit" value="Log In" /></p>
</form>

As an attacker, he starts with a query that presumably authenticates the user name and password. By looking at the source file, he can begin to guess your habits.
Like naming conventions. It is often assumed that the field name in your form is the same as the field name in your data table. Of course, making sure they are different is not necessarily a reliable safety measure.
For the first guess, general 1 will use the query in the following example:

<?php
 $password_hash = md5($_POST['password']);

$sql = "SELECT count(*)
      FROM   users
      WHERE  username = '{$_POST['username']}'
      AND    password = '$password_hash'";
 ?>

The MD5 value for the user password used to be 1 common practice, but it is not particularly secure now. Recent studies have shown that the MD5 algorithm is flawed, and the large number of MD5 databases reduces the difficulty of reverse cracking MD5. Please visit http: / / md5. rednoize. com/view the demo (sic, shandong university professor xiao-yun wang's research shows that can quickly find MD5 "crash", is the ability to produce the same MD5 values of two different files and strings. MD5 is a message summary algorithm, not an encryption algorithm, so reverse cracking is impossible. Based on this work, however, it is dangerous to use md5 directly in this particular case. .
The best way to protect your password is to attach a string you have defined, such as:

<?php
 $salt = 'SHIFLETT';
$password_hash = md5($salt . md5($_POST['password'] . $salt));
 ?>

Of course, attackers don't always get it right the first time; they often need to do a few more tests. A good experiment is to include single quotes as a user directory because it may reveal some important information. Many developers call the function mysql_error() to report errors when an Mysql statement goes wrong. See the following example:

<?php
 mysql_query($sql) or exit(mysql_error());
 ?>

Although this method is useful for 10 points in development, it can expose important information to attackers. If the attacker USES the single quote as the user name and mypass as the password, the query will look like this:

<?php
 $sql = "SELECT *
      FROM   users
      WHERE  username = '''
      AND    password = 'a029d0df84eb5549c641e04a9ef389e5'";
 ?>

When the statement is sent to MySQL, the system displays the following error message:

You have an error in your SQL syntax. Check the manual that corresponds to your
MySQL server version for the right syntax to use near 'WHERE username = ''' AND
password = 'a029d0df84eb55

With no effort, the attacker already knows the two field names (username and password) and the order in which they appear in the query. In addition, the attacker knows that the data is not properly filtered (the program does not prompt for an invalid user name) and escaped (a database error occurs), and the entire format of the WHERE condition is exposed so that the attacker can attempt to manipulate the records that match the query.
At this point, the attacker has many options. 1 is to try to fill in a special user name so that the query can get a match regardless of whether the user name and password match:

myuser' or 'foo' = 'foo' --

Assuming that mypass is used as the password, the entire query becomes:

<?php

$sql = "SELECT *
      FROM   users
      WHERE  username = 'myuser' or 'foo' = 'foo' --
      AND    password = 'a029d0df84eb5549c641e04a9ef389e5'";

?>

Fortunately, THE SQL injection is easy to avoid. As mentioned earlier, you must always filter inputs and escape outputs.
Although neither step can be omitted, implementing just one of them will eliminate most of the SQL injection risk. If you filter the input without escaping the output, you are likely to encounter database errors (valid data may also affect the correct format of the SQL query), but this is not reliable, and valid data may also change the behavior of the SQL statement. On the other hand, if you escape the output without filtering the input, you ensure that the data does not affect the format of the SQL statement, and you also prevent a number of common SQL injection attacks.
Of course, stick with both steps. The way input is filtered depends entirely on the type of input data (see the example in Chapter 1), but escaping the output data used to send to the database is as simple as using the same function. For MySQL users, you can use the function mysql_real_escape_string() :

<?php
 $clean = array();
$mysql = array();

$clean['last_name'] = "O'Reilly";
$mysql['last_name'] = mysql_real_escape_string($clean['last_name']);

$sql = "INSERT
      INTO   user (last_name)
      VALUES ('{$mysql['last_name']}')";
 ?>

Try to use escape functions designed for your database. If not, using the function addslashes() is ultimately the better approach.
When all the data used to create an SQL statement is properly filtered and escaped, the risk of SQL injection is effectively avoided. If you are using database operation classes that support parameterized queries and placeholders (PEAR::DB, PDO, etc.), you get an extra layer of protection. See the following example using PEAR::DB:

<?php
$sql = 'INSERT
      INTO   user (last_name)
      VALUES (?)';
$dbh->query($sql, array($clean['last_name']));
?>

Since the data in the above example does not directly affect the format of the query statement, the risk of SQL injection is reduced. PEAR::DB will automatically escape according to your database requirements, so you only need to filter the output.
If you are using a parameterized query, the input will only be treated as data. There is no need to escape, although you might think this is a necessary step (if you want to stick to the escape output habit). In fact, it makes little difference whether or not you escape at this point, because there are no special characters to convert. Parameterized queries provide powerful protection against SQL injection.
Note: about SQL injection, have to say is now mostly virtual host will open the magic_quotes_gpc options, in this case all client GET and POST addslashes processing data automatically, so at this point to a string value SQL injection is not feasible, but should prevent SQL injection of numeric values, such as using intval () function for processing. But if you're writing generic software, you'll need to read magic_quotes_gpc from the server and handle it accordingly.

Related articles: