Best Way to Avoid Code Injection in PHP

Best way to avoid code injection in PHP

Use a whitelist and make sure the page is in the whitelist:

  $whitelist = array('home', 'page');

if (in_array($_GET['page'], $whitelist)) {
include($_GET['page'].'.php');
} else {
include('home.php');
}

How can I prevent SQL injection in PHP?

The correct way to avoid SQL injection attacks, no matter which database you use, is to separate the data from SQL, so that data stays data and will never be interpreted as commands by the SQL parser. It is possible to create an SQL statement with correctly formatted data parts, but if you don't fully understand the details, you should always use prepared statements and parameterized queries. These are SQL statements that are sent to and parsed by the database server separately from any parameters. This way it is impossible for an attacker to inject malicious SQL.

You basically have two options to achieve this:

  1. Using PDO (for any supported database driver):

    $stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
    $stmt->execute([ 'name' => $name ]);

    foreach ($stmt as $row) {
    // Do something with $row
    }
  2. Using MySQLi (for MySQL):

    $stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
    $stmt->bind_param('s', $name); // 's' specifies the variable type => 'string'
    $stmt->execute();

    $result = $stmt->get_result();
    while ($row = $result->fetch_assoc()) {
    // Do something with $row
    }

If you're connecting to a database other than MySQL, there is a driver-specific second option that you can refer to (for example, pg_prepare() and pg_execute() for PostgreSQL). PDO is the universal option.



Correctly setting up the connection

PDO

Note that when using PDO to access a MySQL database real prepared statements are not used by default. To fix this you have to disable the emulation of prepared statements. An example of creating a connection using PDO is:

$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8mb4', 'user', 'password');

$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

In the above example, the error mode isn't strictly necessary, but it is advised to add it. This way PDO will inform you of all MySQL errors by means of throwing the PDOException.

What is mandatory, however, is the first setAttribute() line, which tells PDO to disable emulated prepared statements and use real prepared statements. This makes sure the statement and the values aren't parsed by PHP before sending it to the MySQL server (giving a possible attacker no chance to inject malicious SQL).

Although you can set the charset in the options of the constructor, it's important to note that 'older' versions of PHP (before 5.3.6) silently ignored the charset parameter in the DSN.

Mysqli

For mysqli we have to follow the same routine:

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); // error reporting
$dbConnection = new mysqli('127.0.0.1', 'username', 'password', 'test');
$dbConnection->set_charset('utf8mb4'); // charset


Explanation

The SQL statement you pass to prepare is parsed and compiled by the database server. By specifying parameters (either a ? or a named parameter like :name in the example above) you tell the database engine where you want to filter on. Then when you call execute, the prepared statement is combined with the parameter values you specify.

The important thing here is that the parameter values are combined with the compiled statement, not an SQL string. SQL injection works by tricking the script into including malicious strings when it creates SQL to send to the database. So by sending the actual SQL separately from the parameters, you limit the risk of ending up with something you didn't intend.

Any parameters you send when using a prepared statement will just be treated as strings (although the database engine may do some optimization so parameters may end up as numbers too, of course). In the example above, if the $name variable contains 'Sarah'; DELETE FROM employees the result would simply be a search for the string "'Sarah'; DELETE FROM employees", and you will not end up with an empty table.

Another benefit of using prepared statements is that if you execute the same statement many times in the same session it will only be parsed and compiled once, giving you some speed gains.

Oh, and since you asked about how to do it for an insert, here's an example (using PDO):

$preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');

$preparedStatement->execute([ 'column' => $unsafeValue ]);


Can prepared statements be used for dynamic queries?

While you can still use prepared statements for the query parameters, the structure of the dynamic query itself cannot be parametrized and certain query features cannot be parametrized.

For these specific scenarios, the best thing to do is use a whitelist filter that restricts the possible values.

// Value whitelist
// $dir can only be 'DESC', otherwise it will be 'ASC'
if (empty($dir) || $dir !== 'DESC') {
$dir = 'ASC';
}

How to prevent code injection attacks in PHP?

  • mysql_real_escape_string used when insert into database
  • htmlentities() used when outputting data into webpage
  • htmlspecialchars() used when?
  • strip_tags() used when?
  • addslashes() used when?

htmlspecialchars() used when?

htmlspecialchars is roughly the same as htmlentities. The difference: character encodings.

Both encode control characters like <, >, & and so on used for opening tags etc. htmlentities also encode chars from other languages like umlauts, euro-symbols and such. If your websites are UTF, use htmlspecialchars(), otherwise use htmlentities().

strip_tags() used when?

htmlspecialchars / entities encode the special chars, so they're displayed but not interpreted. strip_tags REMOVES them.

In practice, it depends on what you need to do.

An example: you've coded a forum, and give users a text field so they can post stuff. Malicious ones just try:

pictures of <a href="javascript:void(window.setInterval(function () {window.open('http://evil.example');}, 1000));">kittens</a> here

If you don't do anything, the link will be displayed and a victim that clicks on the link gets lots of pop-ups.

If you htmlentity/htmlspecialchar your output, the text will be there as-is. If you strip_tag it, it simply removes the tags and displays it:

pictures of kittens here

Sometimes you may want a mixture, leave some tags in there, like <b> (strip_tags can leave certain tags in there). This is unsafe too, so better use some full blown library against XSS.

addslashes

To quote an old version of the PHP manual:

Returns a string with backslashes before characters that need to be quoted in database queries etc. These characters are single quote ('), double quote ("), backslash () and NUL (the NULL byte).

An example use of addslashes() is when you're entering data into a database. For example, to insert the name O'reilly into a database, you will need to escape it. It's highly recommeneded to use DBMS specific escape function (e.g. mysqli_real_escape_string() for MySQL or pg_escape_string() for PostgreSQL), but if the DBMS you're using does't have an escape function and the DBMS uses \ to escape special chars, you can use this function.

The current version is worded differently.

preventing php injection in forms (if a user submits php code into a form)

No. Use htmlspecialchars instead. Don't use addslashes.

To be more specific, addslashes bluntly escapes all instances of ', " and \ and NUL. It was meant to prevent SQL injection, but it has no real use in proper security measures.

What you want is preventing the browser to interpret tags as is (and that's entirely different from preventing SQL injections). For instance, if I want to talk about <script> elements, SO shouldn't simply send that string literally, causing to start an actual script (that can lead to Cross-site scripting), but some characters, especially < and >, need to be encoded as HTML entities so they're shown as angle brackets (the same is true for &, that otherwise would be interpreted as the start of an HTML entity).

In your case, output after htmlspecialchars would look like:

<?php echo 'hi'; ?>

Preventing JavaScript Injections in a PHP Web Application

A good first step is applying the methods listed in the question Gert G linked. This covers in detail the variety of functions that can be used in different situations to cleanse input, including mysql_real_escape_string, htmlentities(), htmlspecialchars(), strip_tags() and addslashes()

A better way, whenever possible, is to avoid inserting user input directly into your database. Employ whitelist input validation: in any situation where you only have a limited range of options, choose from hard-coded values for for insertion, rather than taking the input from any client-side facing form. Basically, this means having only certain values that you accept, instead of trying to eliminate/counter evil/mal-formed/malicious input.

For example:
If you have a form with a drop down for items, do not take use the input from this dropdown for insertion. Remember that a malicious client can edit the information sent with the form's submission, even if you think they only have limited options. Instead, have the drop down refer to an index in an array in your server-side code. Then use that array to choose what to insert. This way, even if an attacker tries to send you malicious code, it never actually hits your database.

Obviously, this doesn't work for free-form applications like forums or blogs. For those, you have to fall back on the "first step" techniques. Still, there are a wide range of options that can be improved via whitelist input validation.

You can also use parameterized queries (aka prepared statements with bind variables) for your sql interactions wherever possible. This will tell your database server that all input is simply a value, so it mitigates a lot of the potential problems from injection attacks. In many situations, this can even cover free-form applications.

PHP : How to Prevent Sql Injection For this Code

No, your current code is not vulnerable. However your other code can be.

As long as you're taking mysql_real_escape_string() as a sort of "universal injection preventor", you are in danger.

Here is an answer with explanations I gave to similar question

How to validate integer values to avoid SQL injection?

For integers and floats you can use this if you don't want to do a parameterised query.

$clean_number = (int)$value;

$clean_number = (float)$value;

These are actually casting the value as int and float, this is faster than intval() and floatval() for example because it does not suffer the function overhead.

PHP Code to avoid sql injection

the better approach will be

  1. mysqli_query()
  2. PDO::query()

you can use the function below but i/we recommended you to not use function since the mysql_* now anymore maintained and updating by community .

Its for only your knowledge only

 $id = mysql_prep($_POST['id']);

function mysql_prep($value)
{
$magic_quotes_active = get_magic_quotes_gpc();
$new_enough_php = function_exists("mysql_real_escape_string"); // i.e. PHP >= v4.3.0
if ($new_enough_php) { // PHP v4.3.0 or higher
// undo any magic quote effects so mysql_real_escape_string can do the work
if ($magic_quotes_active) {
$value = stripslashes($value);
}
$value = mysql_real_escape_string($value);
} else { // before PHP v4.3.0
// if magic quotes aren't already on then add slashes manually
if (!$magic_quotes_active) {
$value = addslashes($value);
}
// if magic quotes are active, then the slashes already exist
}
return $value ;
}

Good read

Best way to prevent SQL injection in PHP?



Related Topics



Leave a reply



Submit