1

I have an old custom php website that I've been working on. I have updated the php code and have a password reset functionality in place. I moved the Connections folder outside of the root folder as that is what I read was the recommended course of action. My client asked for the ability to use special characters in the password reset. I have regex for this that works great. Everything seems to be working, except when I try to use multiple characters in a row, I get an internal server error. When I check the error log this is what it says:

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"]  

This was not an issue on a test website I created, but I also have the database connection file in the root of the test website folder. In the live website I have the connection file outside of the project folder as I read this was best practice.

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

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

Here is my query to update the password:

// 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;
}

I have never encountered this problem before. Does anyone have any advice on how to correct this?

Bert W
  • 546
  • 5
  • 11
  • Please add the relevant code to the question - are you e.g using parameterized queries? – AD7six Nov 26 '22 at 23:34
  • 2
    [ModSecurity](https://github.com/SpiderLabs/ModSecurity) runs on top of your web server and has nothing to do with your PHP app. It's intercepting the request (before it even gets to PHP) because it looks like a SQL injection attack. If you want to allow it, you'll need to adjust the ModSecurity config, not your app. – Alex Howansky Nov 27 '22 at 00:10
  • 2
    Also note, you can do `$lastEditTime = date('M j Y');` in one line. – Alex Howansky Nov 27 '22 at 00:12
  • 1
    The code looks good otherwise, you're using strong hashing and bound parameters. Only suggestion I'd make security-wise would be to also prompt for the old password when prompting for the new password, and then verify it before running the update. – Alex Howansky Nov 27 '22 at 00:18
  • @AlexHowansky the website is hosted on Dreamhost and I am using SFTP to make changes. Do you know if I would I be able to access the ModSecurity config through SFTP? There is nothing on the Dreamhost Cpanel allowing me to make changes to ModSecurity. – Bert W Nov 27 '22 at 00:43
  • 1
    No idea. If it's shared hosting you're probably out of luck. If it's a dedicated VPS, the config file is likely in /etc somewhere. – Alex Howansky Nov 27 '22 at 00:57

1 Answers1

3

Your ModSecurity rules for SQL injection are blocking things that look like SQL injection - and that can lead to false positives. These rules are likely coming from the OWASP ModSecurity Core Rule Set

Generally you want to exclude a password field from ModSecurity Core Rule Set checking. This is normally done by adding to your ModSec config a rule like:

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

Sub in your own URL and your specific params.

I don't know how you would go about modifying your config in a Dreamhost environment (or even whether they allow that). That is a seperate question.

Note also that ModSecurity should be configured to avoid logging the values from password and other sensitive fields. See "Removing Sensitive Data from Audit Logs" in the excellent ModSecurity Handbook.

Egret
  • 739
  • 3
  • 8
  • 1
    Thanks @Egret I contacted Dreamhost support and they were able to fix the issue on their end. – Bert W Nov 28 '22 at 01:49