密码中的特殊字符导致内部服务器错误“通过 libinjection 检测到 SQL 注入攻击”

Special characters in password causing internal server error "SQL Injection attack detected via libinjection"

提问人:Bert W 提问时间:11/27/2022 最后编辑:Bert W 更新时间:11/28/2022 访问量:629

问:

我有一个旧的自定义 php 网站,我一直在工作。我已经更新了 php 代码并具有密码重置功能。我将 Connections 文件夹移到了根文件夹之外,因为这是我读到的推荐操作方案。我的客户要求能够在密码重置中使用特殊字符。我有正则表达式,效果很好。一切似乎都在工作,除了当我尝试连续使用多个字符时,我收到内部服务器错误。当我检查错误日志时,它是这样说的:

ModSecurity: Warning. detected SQLi using libinjection with fingerprint 'novc' [file "/dh/apache2/template/etc/mod_sec3_CRS/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"][msg "SQL Injection Attack Detected via libinjection"] [data "Matched Data: novc found within ARGS:newPassword2: Abcd1234!@#$"] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.2"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-sqli"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/248/66"]  

这在我创建的测试网站上不是问题,但我在测试网站文件夹的根目录中也有数据库连接文件。在实时网站中,我在项目文件夹之外有连接文件,因为我读到这是最佳实践。

Connections folder
--connection.php
live website folder
--index.php
--other files, etc.

test website folder
--Connection.php
--other files

这是我更新密码的查询:

// if form is submitted and the value equals the value of the hidden input
if (isset($_POST['newPassword'])) {
    // password regex match
  if (!preg_match('/^(?=.*[A-Za-z])(?=.*\d)(?=.*[!#$%&()*@?^])[A-Za-z\d!#$%&()*@?^]{8,30}$/', $_POST['newPassword'])) {
    exit('password should be between 8 and 30 characters and contain at least one number and one special character');
  }
  // Check if both the password and confirm password fields match
  if ($_POST['newPassword'] != $_POST['newPassword2']) {
  exit('Passwords do not match!');
  }
  // set the date
  $month = date ("M");
  $year = date ("Y");
  $day = date ("j");
  // lastEditTime and lastEditedBy
  $lastEditTime = $month." ".$day.", ".$year; 
  $lastEditedBy = $_SESSION['MM_Username'];
  $userId = $_SESSION['MM_UserID'];
  $newPassword = password_hash($_POST['newPassword'],PASSWORD_DEFAULT);
  $updateStmt = $connection->prepare("UPDATE tbl_users SET newPassword= ?, lastEditedBy= ?, lastEditTime= ? WHERE userID= ?");
  $updateStmt->bind_param('sssi',$newPassword,$lastEditedBy,$lastEditTime,$userId);
  $updateStmt->execute();
    $updateStmt->close();     

  header("Location: reset4.php");
  exit;
}

我以前从未遇到过这个问题。有没有人对如何纠正这个问题有任何建议?

php sql 注入

评论

0赞 AD7six 11/27/2022
请在问题中添加相关代码 - 例如,您是否使用参数化查询?
2赞 Alex Howansky 11/27/2022
ModSecurity运行在Web服务器之上,与PHP应用程序无关。它拦截了请求(甚至在它到达 PHP 之前),因为它看起来像是 SQL 注入攻击。如果要允许它,则需要调整 ModSecurity 配置,而不是您的应用。
2赞 Alex Howansky 11/27/2022
另请注意,您可以在一行中完成。$lastEditTime = date('M j Y');
1赞 Alex Howansky 11/27/2022
否则,代码看起来不错,您使用的是强哈希和绑定参数。出于安全考虑,我唯一的建议是在提示输入新密码时也提示输入旧密码,然后在运行更新之前对其进行验证。
1赞 Alex Howansky 11/27/2022
不知道。如果是共享主机,您可能不走运。如果是专用的 VPS,配置文件可能在 /etc 的某个地方。

答:

3赞 Egret 11/28/2022 #1

用于 SQL 注入的 ModSecurity 规则正在阻止看起来像 SQL 注入的内容,这可能会导致误报。这些规则可能来自 OWASP ModSecurity 核心规则集

通常,您希望从 ModSecurity 核心规则集检查中排除密码字段。这通常是通过在 ModSec 配置中添加如下规则来完成的:

SecRule REQUEST_URI "@streq /your/page/uri" \
"id:12345,phase:1,t:none,nolog,pass,\
ctl:ruleRemoveTargetByTag=.*;ARGS:password"

在您自己的 URL 和特定参数中加入。

我不知道您将如何在 Dreamhost 环境中修改您的配置(甚至他们是否允许这样做)。这是一个单独的问题。

另请注意,应将 ModSecurity 配置为避免记录密码和其他敏感字段中的值。请参阅优秀的 ModSecurity 手册中的“从审计日志中删除敏感数据”。

评论

1赞 Bert W 11/28/2022
感谢@Egret我联系了 Dreamhost 支持,他们能够最终解决问题。