微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何防止在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.

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

  1. 使用PDO(对于任何受支持数据库驱动程序):
        $stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');

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

    foreach ($stmt as $row) {
        // Do something with $row
    }
  1. 使用MySQLi(对于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
    }

如果你连接到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';
}

解决方法

如果将用户输入未经修改地插入到SQL查询中,则应用程序容易受到SQL注入的攻击,如以下示例所示:

$unsafe_variable = $_POST['user_input'];

mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')");

这是因为用户可以输入类似的内容value’); DROP TABLE table;–,并且查询变为:

INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')

可以采取什么措施来防止这种情况的发生?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。