您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

如何防止在PHP中进行SQL注入?

如何防止在PHP中进行SQL注入?

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.

您基本上有两种选择可以实现此目的:

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

    $stmt->execute([ 'name' => $name ]);

    foreach ($stmt as $row) {
        // Do something with $row
    }
        $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
    }

如果你连接到MysqL之外的数据库,有一个特定的驱动程序,第二个选项,你可以参考一下(例如,pg_prepare()pg_execute()Postgresql的)。PDO是通用选项。

注意,当PDO用于访问MysqL数据库时 *

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

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

在上面的示例中,错误模式不是严格必需的, 。这样,Fatal Error当出现问题时,脚本不会以a停止。并且它为开发人员提供了解决catch任何thrown为PDOExceptions的错误的机会。

但是,第一行是 ,setAttribute()它告诉PDO禁用模拟的预备语句并使用 实际的 预备语句。这样可以确保在将语句和值发送到MysqL服务器之前,不会对PHP进行解析(这样可能会使攻击者没有机会注入恶意sql)。

尽管可以charset在构造函数的选项中设置,但必须注意,PHP的“较旧”版本(5.3.6之前的版本)静默忽略了DSN中的charset参数

传递给您的sql语句prepare数据库服务器解析和编译。通过指定参数(如上例中的?参数或命名参数:name),您可以告诉数据库引擎要在何处进行过滤。然后,当您调用execute,准备好的语句将与您指定的参数值组合在一起。

这里重要的是参数值与已编译的语句组合,而不是与sql字符串组合。sql注入通过在创建要发送到数据库sql时欺骗脚本使其包含恶意字符串来起作用。因此,通过将实际的sql与参数分开发送,可以降低因意外获得最终结果的风险。

使用预处理语句发送的任何参数都将被视为字符串(尽管数据库引擎可能会进行一些优化,因此参数最终也可能以数字结尾)。在上面的示例中,如果$name变量包含'Sarah'; DELETE FROM employees结果,则仅是搜索字符串"'Sarah'; DELETE FROMemployees",并且最终不会得到空表

使用准备好的语句的另一个好处是,如果您在同一会话中多次执行同一条语句,则该语句仅被解析和编译一次,从而可以提高速度。

哦,既然您询问了如何进行插入,这是一个示例(使用PDO):

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

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

尽管您仍可以对查询参数使用准备好的语句,但是无法对动态查询本身的结构进行参数化,并且无法对某些查询功能进行参数化。

对于这些特定方案,最好的办法是使用白名单过滤器来限制可能的值。

// Value whitelist
// $dir can only be 'DESC', otherwise it will be 'ASC'
if (empty($dir) || $dir !== 'DESC') {
   $dir = 'ASC';
}
php 2022/1/1 18:46:36 有328人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶