SQL 基础教程
SQL 连接
SQL 高级教程
SQL 参考资料

SQL 注入

在本教程中,您将学习如何修复常见的数据库漏洞。

什么是 SQL 注入?

SQL 注入是一种攻击,攻击者可以通过从浏览器到应用服务器的输入数据(例如 Web 表单输入)注入或执行恶意 SQL 代码。

它可用于暴露敏感信息,如用户的联系电话、电子邮件地址、信用卡信息等。 攻击者甚至可以使用它绕过身份验证过程并访问整个数据库。 让我们看看它实际上是如何工作的。

SQL 注入的工作原理

考虑以下 SQL 语句,它是在 Web 应用程序中使用用户名和密码对用户进行身份验证的简单示例。

SELECT * FROM users WHERE username='username_val' AND password='password_val';

这里,username_valpassword_val分别代表用户输入的用户名和密码。 如果用户输入诸如"john"作为用户名和"123"作为密码之类的值,则生成的语句将是:

SELECT * FROM users WHERE username='john' AND password='123';

但是假设,如果用户是攻击者,而不是在输入字段中输入有效的用户名和密码,他输入的值类似于:' OR 'x'='x

在这种情况下,上面的 SQL 查询将被构造为:

SELECT * FROM users WHERE username='' OR 'x'='x' AND password='' OR 'x'='x';

该语句是有效的 SQL 语句,并且由于 WHERE 'x'='x' 始终为真,因此查询将返回 users 表中的所有行。 您可以看到攻击者只需一个小技巧即可轻松访问数据库的所有敏感信息。

如果 users 表非常大并且包含数百万或行,则此单个语句还可能通过使系统资源过载而导致拒绝服务攻击(DoS 攻击)并使您的应用程序对合法用户不可用 .

警告:如果您的脚本生成 DELETEUPDATE 查询,则忽略 SQL 注入漏洞的后果可能会更糟。 攻击者可以从表中删除数据或永久更改其所有行。


防止 SQL 注入

始终验证用户输入并且不做任何假设。 永远不要直接从用户输入构建 SQL 语句。 如果您使用 PHP 和 MySQL,您可以使用 mysqli_real_escape_string() 函数来创建可以在 SQL 语句中使用的合法 SQL 字符串。

这是一个使用 PHP 和 MySQL 进行用户身份验证的非常基本的示例,演示了如何在获取用户输入时防止 SQL 注入。

示例

Download
<?php
// 开始会话
session_start();
 
/* 尝试 MySQL 服务器连接。 假设您正在运行 MySQL
具有默认设置的服务器(用户 'root' 没有密码) */
$link = mysqli_connect("localhost", "root", "", "demo");
 
// 检查连接
if($link === false){
    die("ERROR: Could not connect to database.");
}
 
// 转义用户输入以确保安全
$username_val = mysqli_real_escape_string($link, $_POST['username']);
$password_val = mysqli_real_escape_string($link, $_POST['password']);
 
if(isset($username_val, $password_val)){
    // 尝试选择查询执行
    $sql = "SELECT * FROM users WHERE username='" . $username_val . "' AND password='" . $password_val . "'";
    if($result = mysqli_query($link, $sql)){
        if(mysqli_num_rows($result) == 1){
            // 用户已通过身份验证在这里做你的事情
            $row = mysqli_fetch_array($result);
            /* 在会话变量中保存值,以便它可以
            稍后在同一会话引用中访问 */
            $_SESSION['user_id'] = $row['user_id'];
            $_SESSION['first_name'] = $row['first_name'];
            header('Location: welcome.asp');
        } else{
            echo "ERROR: Invalid username or password.";
        }
    } else{
        echo "ERROR: Something went wrong. Please try again.";
    }
}
 
// 关闭连接
mysqli_close($link);
?>

请查看 PHP MySQL prepared statements 上的教程,了解在 Web 应用程序中防止 SQL 注入的高级技术。

提示:测试您的应用程序接收的数据的大小和类型或内容,并实施适当的限制以防止系统资源被利用。

Advertisements