PHP pdo mysql的默认字符集是什么

时间:2018-09-01 13:19:31

标签: php mysql pdo utf-8 sql-injection

我正在此页面Are PDO prepared statements sufficient to prevent SQL injection?上阅读有关二阶MySQL注入的信息。

并带来了许多有关charset的问题,我不确定我的代码对MySQL注入是否安全

在我的代码中,我从未在进行查询时使用字符集,

我只是做

$pdo = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD, [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_PERSISTENT => false]);
$stmt = $pdo->prepare("SELECT * FROM keywords  WHERE keyword_name = ? || keyword_name = ?");
$stmt->execute(["hello","world"]);
rows = $stmt->fetchAll();
// show the data on webpage
$pdo = null;

我发现有两种方法可以在pdo中set charset

$pdo = new PDO("mysql:host=" . DB_HOST . ";charset=utf8;......);

$pdo->exec("set names utf8");

根据@ircmaxell对此链接Are PDO prepared statements sufficient to prevent SQL injection?的回答。应该使用第一种方法来防止二阶SQL注入...

但是我的代码中有never set charset(如第一个代码所示),所以我有几个问题

  1. 对于我未设置任何字符集的第一个代码,“默认”字符集将是什么,并且安全吗?
  2. 它与数据库的字符集有关吗,因为我的数据库字符集(Collat​​ion)是ut8_general_ci(在phpmyadmin-> operations中发现)?
  3. utf8字符集可安全用于第二次注入吗,即$pdo = new PDO("mysql:host=" . DB_HOST . ";charset=utf8;......);已完成针对所有类型的mysql注入的工作?

1 个答案:

答案 0 :(得分:2)

选项character_set_client是MySQL用于客户端发送的查询和数据字符集的方式。

在MySQL 5.5、5.6和5.7中默认为utf8,在8.0中为utf8mb4。

还可以在my.cnf选项文件中全局更改,也可以通过SET NAMES语句在每个会话中更改。

在连接时最好显式设置该选项,这样就不必假定其默认值。


发表评论:

恐怕您会混淆两种不同的SQL注入情况。使用这五个特定的字符集时会存在风险,但这与二阶SQL注入无关。

字符集风险归因于某些多字节字符集。插入反斜杠以转义文字引号是很常见的。但是在某些字符集中,反斜杠字节合并为前一个字节,形成一个多字节字符。这使报价不被转义。

二阶SQL注入完全不同。它可以与任何字符集一起发生。这是攻击者通过合法手段(例如填写表格)将数据添加到数据库中的时候。插入数据的操作没有错误。但是它们插入的值包含旨在利用某些以后的SQL查询的语法。

开发人员认为,已经安全地保存到数据库中的数据以某种方式是“安全的”,无需进行适当的参数化即可使用。

一个仅是偶然而不是恶意的二阶SQL注入示例可能是一个人的姓氏为“ O'Reilly”,并且该名字被代码读取并在随后的查询中使用。

>
$name = $db->query("SELECT last_name FROM people WHERE id = 123")->fetchColumn();
$sql = "SELECT * FROM accounts WHERE account_owner_last_name = '$name'";

如果名称中包含单引号,则会使该示例中的第二个查询弄乱。