Avatar of Bobby
Bobby
Flag for United States of America asked on

key data, how to see expiration length?

The following code is supposed to determine how long it has been since a password reset request was submitted. If the request has expired, disallow.

        } else if(!empty($request->get('key'))) {
          $dbAccessor = new DbAccessor();
          $new_password = $request->get('new_password');
          $rawkey = $dbAccessor->unobfuscate_id($request->get('key'));
          $keyparts = explode(":", $rawkey);
          $contact_id = $keyparts[0];
          $expiration = $keyparts[1];

          if(time() > $expiration) {
             $redirect = "/account/reset_my_password?error=key_expired";

Open in new window


I know it works, because I changed the > to a < in the if(time() > $expiration), and I could not reset my password.

I'm a complete newb at this, taking over for a staff member who moved away. He was our main back end web dev, and Im scrambling to fill his shoes as much as I can.

I was tasked with this because somebody ran across a link that was sent out to a real customer months ago to reset their password. We clicked the link, and it took us to the password reset page, as if it was perfectly fine to reset our password after all those months. The link should have expired.

BUT

This may have been designed so that the user doesn't get a message that it has expired, it just doesnt do what it says (like my test in reversing the <>). That would be perfectly acceptable... not graceful, but at least the password could not be reset via that link 3 months later.

So... obviously I need to figure out the value of this: $keyparts[1]; to see what time value is being specified (if any). How do I see that? Here is the unobfuscate_id function:

   public function unobfuscate_id($str) {  
      $key = "realdatastripped";
      $encrypted_str = base64_decode(str_pad(strtr($str, '-_', '+/'), strlen($str) % 4, '=', STR_PAD_RIGHT));
      $str = mcrypt_decrypt(MCRYPT_DES, $key, $encrypted_str, MCRYPT_MODE_ECB);
      $block = mcrypt_get_block_size('des', 'ecb');
      $pad = ord($str[($len = strlen($str)) - 1]);
      $unencrypted_str = substr($str, 0, strlen($str) - $pad);
      return str_replace("dm", "", $unencrypted_str);

Open in new window


If it helps, here is the key in one email I initiated to myself for a password request: reset_my_password?key=XPLDFLhFhu0O192aM6dmCGhW4srTDUQw
EncryptionPHPSecurity

Avatar of undefined
Last Comment
Julian Hansen

8/22/2022 - Mon
Julian Hansen

mcrypt functions have been deprecated.
Trying to run that code gives a warning
Key of size 16 not supported by this algorithm. Only keys of size 8 supported
There is a way to convert to opnessl but it is taking too much time.
Can you add the following to your code (line 8 - or anywhere after line 4).
echo "<pre>" . print_r($rawkey, true) . "</pre>";

Open in new window

Post the results here.

This is a very complicated solution. Another option is just to generate a UUID() (if you are using MySQL or MariaDB you can do it with the UUID() function).
Save this to an activation key table in the DB with a timestamp and userid.
When a key comes in compare timestamp to current time() - if outside expiry period then deny.

Cleanup script runs regularly to clean up table.

The nice thing about this approach is that no information is stored in the key.
The key can't be tampered with.
You can change the expiry time and it will apply to all existing keys.
David Favor

Julian is correct, mcrypt has been deprecated. Use libsodium instead.

Also, as Julian said, fixing this will be complex.

My guess is you'll have to fix your code to use libsodium or another supported encryption type.

Once your code is working, this should trigger every user doing a password reset.

Depending on your database table schema, you may also have to run an alter table to change your password field length.

Also version of PHP you're running on today + version your upgrading to will be a factor.
David Favor

Since you said, "I'm a complete newb at this" likely best if you hire someone to help you with this.

Also, keep the PHP Compatibility Checker URL handy, as this tool is a must for finding other potential problems in your code which are near impossible to catch by eye.

Also, if your code has a debugging facility, enable it so all problems are logged instantly.

If your code has no debugging facility, this will be one of the first tasks you complete, so you can see all errors/warnings, rather than guess.
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Bobby

ASKER
Julian, I added

echo "<pre>" . print_r($rawkey, true) . "</pre>";

where you said but it does not print to the browser, so I have no results to post.
Julian Hansen

Then either the decrypt is not working or the key is not present.

The code after line 8 expects a value in the form
CONTACTID:EXPIRES

If you are not seeing this then the extract of the key is not working.

What version of PHP are you using?

Seriously, I would move away from an encrypted solution - in my view it only complicates your solution. A simple unguessable key (like UUID) linked to database record would work much better.
Bobby

ASKER
we upgraded about a month ago from php 5.5 to php 7.2
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Julian Hansen

Well - that is your problem isn't it.
From here http://php.net/manual/en/function.mcrypt-decrypt.php
This function has been DEPRECATED as of PHP 7.1.0 and REMOVED as of PHP 7.2.0. Relying on this function is highly discouraged.
Your code is never going to work because the mcrypt functions have been removedin 7.2
Bobby

ASKER
Ugh. Thanks for researching. So, in a nutshell, what do you think our quickest solution will be? I need to take this to the CEO and give him some kind of timeline to getting it fixed.
ASKER CERTIFIED SOLUTION
Julian Hansen

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.