minte9
LearnRemember



INJECTION

The SQL query ignores everything after the # and returns all records!
 
# A malicious user experiments on a form

<form method="POST">
    <input type="text" name="username" value="username' OR 1 = 1 #"/>
    <input type="password" name="password" />
    <input type="submit" name="btn_submit" value="Log In"/>
</form>
 
if (isset($_POST['btn_submit'])) {

    $username = $_POST['username']; // NO database filtering!
    $password = md5($_POST['password']);
    $sql = "
        SELECT * FROM users 
        WHERE username='{$username}' AND password='{$password}'
    ";

    echo $sql; 
        // SELECT * FROM users 
        // WHERE username='username' OR 1 = 1 #' AND ...

FILTER

As a first defence you must filter the input.
 
if (isset($_POST['btn_submit'])) {
    
    // driver-specific db filtering
    $username = mysql_escape_string($_POST['username']);
    $password = md5(mysql_escape_string($_POST['password']));
    
    $sql = "
            SELECT * FROM users 
            WHERE username='{$username}' AND password='{$password}'
    ";
    
    echo $sql; 
        // Will add slashes to username quote
        // resulting in SQL syntax error
}

BIND

If possible, use bound parameters.
 
# Use a placeholder like ? ...
# and provide the actual values using a separate API call.
#
# Two good reasons:
# - is the best way to prevent SQL injection
# - not using bind parameters is like recompiling a program every time

$stmt = $dbh->prepare("
    INSERT INTO mytable (name, value) VALUES (:name, :value)
");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);



  Last update: 260 days ago