Solution: Trust No One
There is no universal remedy against SQL Injection. Let's learn how we can use different techniques for different scenarios.
There is no single technique for securing our SQL code. A good approach is to learn all of the following techniques and use them in appropriate cases.
Filter input
Instead of wondering whether some input contains harmful content, we should strip away any characters that aren’t valid for that input. That is, if we need an integer, we should use only the part of the content that comprises an integer. The best way to do this depends on our programming language; for example, in PHP, we should use the filter
extension:
<?php
$bugid = filter_input(INPUT_GET, "bugid", FILTER_SANITIZE_NUMBER_INT);
$sql = "SELECT * FROM Bugs WHERE bug_id = {$bugid}";
$stmt = $pdo->query($sql);
?>
We can use type casting functions for simple cases like numbers:
<?php
$bugid = intval($_GET["bugid"]);
$sql = "SELECT * FROM Bugs WHERE bug_id = {$bugid}";
$stmt = $pdo->query($sql);
?>
We can also use regular expressions to match safe substrings, filtering out illegitimate content:
<?php
$sortorder = "date_reported"; // default
if (preg_match("/[_[:alnum:]]+/", $_GET["order"], $matches)) { }
$sortorder = $matches[1];
$sql = "SELECT * FROM Bugs ORDER BY {$sortorder}";
$stmt = $pdo->query($sql);
?>
Parameterize dynamic values
When the dynamic parts of our query are simple values, we should use query parameters to separate them from SQL expressions.
<?php
$sql = "UPDATE Accounts SET password_hash = SHA2(?) WHERE account_id = ?";
$stmt = $pdo->prepare($sql);
$params = array($_REQUEST["password"], $_REQUEST["userid"]);
$stmt->execute($params);
?>
...