当字符串包含单引号但其他方式有效时,PHP preg_replace()返回null

时间:2019-02-07 11:00:06

标签: php regex mysqli single-quotes

下面的代码非常简单。 PHP使用POST从表单中收集字符串,然后寻找并修剪并运行preg_replace函数,该函数将去除除单引号或连字符以外的所有特殊字符。切记,整个代码可以正常运行,而无需在正则表达式中使用引号或连字符。

preg_replace("/[^\w\s'-]/", '', $raw_lemurName);

然后将这些干净变量插入数据库中。 Apache / 2.4.37。 MariaDB。

当我将lemurName设为“ Diademed Sifaka <>!”之类的字符串时,它将起作用,并返回“ Diademed Sifaka”。

但是,当我使用包含单引号的字符串作为字符串时,例如“ Coquerel的Sifaka”,操作将无法完成,并且不会插入任何信息。

我已经单独测试了regex表达式,它可以正常工作,似乎当您开始涉及SQL和数据库时,它便停止工作。

值得注意的是:

  • 使用phpMyAdmin。如果我在此处插入字符串,则可以正常工作,因此我的数据库可以保存这些值。
  • 尝试在各个地方使用mysqli_real_escape_string(),但是运气不好,也许做错了。
  • 仔细阅读,我认为这与SQL有关,SQL不允许插入带有单引号的字符串,并且服务器会在post方法中自动转义单引号。

有什么想法吗?

非常感谢。

$raw_lemurName          =    isset($_POST['lemurName']) ? $_POST['lemurName'] : null;

$raw_lemurLat           =    isset($_POST['lemurLat']) ? $_POST['lemurLat'] : null;

$raw_family             =    isset($_POST['family']) ? $_POST['family'] : null;

//下面的正则表达式似乎把东西弄乱了

$c_lemurName            =    trim(preg_replace("/[^\w\s'-]/", '', $raw_lemurName));

$c_lemurLat             =    strtolower(trim(preg_replace('/[^\w\s]/', '', $raw_lemurLat))); 

$c_family               =    trim(preg_replace('/[^\w\s]/', '', $raw_family));

if (isset($_POST['submit'])) {

$query1 = "INSERT INTO `lemurs` (`id`, `lemur`, `latin`, `family`) VALUES (NULL, '$c_lemurName','$c_lemurLat','$c_family')";

$run_query = mysqli_query($connection, $query1);

if($run_query){
    echo "Data has been inserted";

} else {
    echo "Operation Unsuccessful";
}

    header("location:  index.php");

    return;

}

3 个答案:

答案 0 :(得分:1)

这是标准的SQL注入问题。问题源于将这些变量添加到查询中的方式:

$query1 = "INSERT INTO `lemurs` (`id`, `lemur`, `latin`, `family`) VALUES (NULL, '$c_lemurName','$c_lemurLat','$c_family')";

仔细考虑这里发生的事情,您所做的只是将字符串并置,因此,如果$c_lemurName'-那么您的SQL将变为:

[...] VALUES (NULL, ''', '[...]

实际上,这实际上使您可以进行所谓的“注入攻击”。基本上,恶意用户可以将$c_family设置为... ');drop table lemurs;--之类的东西-您现在正在执行一条insert语句,然后执行一个drop table语句,其余的SQL则为注释。 / p>

有几种方法可以解决这个问题,最常用的方法是查看参数化查询-对于mysqli库,这必须通过准备好的语句来完成。 PHP docs page上有一个示例。

答案 1 :(得分:0)

也替换第二个参数区域中的单引号。用这个。

preg_replace("/[^\w\s'-]/", "", $raw_lemurName);

希望它能工作

答案 2 :(得分:0)

您将$ c_lemurLat和$ c_family用于正则表达式:     “ / [^ \ w \ s] /”

这将正确过滤单引号。

对于$ c_lemurName,您正在使用:    “ / [^ \ w \ s'-] /”

这不会删除单引号。

删除'-,即可正常运行。