Solved

Need assistance with PHP passphrase strength checking and enforcement - passwdqc

Posted on 2010-11-18
9
944 Views
Last Modified: 2012-05-10
Hello,

I'm trying to implement a PHP "passphrase strength checking and enforcement" script called passwdqc and need some assistance getting it working.

The implementation is discussed on this page:
http://www.openwall.com/articles/PHP-Users-Passwords#enforcing-password-policy

Can someone provide some specific directions on how to get this to work?

I have the following (openwall.com-provided) code, pwqcheck.php as a 'required' script:
 
<?php

/*
 * The pwqcheck() function is a wrapper around the pwqcheck(1) program from
 * the passwdqc package:
 *
 * http://www.openwall.com/passwdqc/
 *
 * Returns 'OK' if the new password/passphrase passes the requirements.
 * Otherwise returns a message explaining one of the reasons why the
 * password/passphrase is rejected.
 *
 * $newpass and $oldpass are the new and current/old passwords/passphrases,
 * respectively.  Only $newpass is required.
 *
 * $user is the username.
 *
 * $aux may be the user's full name, e-mail address, and/or other textual
 * info specific to the user (multiple items may be separated with spaces).
 *
 * $args are additional arguments to pass to pwqcheck(1), to override the
 * default password policy.
 */
function pwqcheck($newpass, $oldpass = '', $user = '', $aux = '', $args = '')
{
// pwqcheck(1) itself returns the same message on internal error
	$retval = 'Bad passphrase (check failed)';

	$descriptorspec = array(
		0 => array('pipe', 'r'),
		1 => array('pipe', 'w'));
// Leave stderr (fd 2) pointing to where it is, likely to error_log

// Replace characters that would violate the protocol
	$newpass = strtr($newpass, "\n", '.');
	$oldpass = strtr($oldpass, "\n", '.');
	$user = strtr($user, "\n:", '..');

// Trigger a "too short" rather than "is the same" message in this special case
	if (!$newpass && !$oldpass)
		$oldpass = '.';

	if ($args)
		$args = ' ' . $args;
	if (!$user)
		$args = ' -2' . $args; // passwdqc 1.2.0+

	$command = 'exec '; // No need to keep the shell process around on Unix
	$command .= 'pwqcheck' . $args;
	if (!($process = @proc_open($command, $descriptorspec, $pipes)))
		return $retval;

	$err = 0;
	fwrite($pipes[0], "$newpass\n$oldpass\n") || $err = 1;
	if ($user)
		fwrite($pipes[0], "$user::::$aux:/:\n") || $err = 1;
	fclose($pipes[0]) || $err = 1;
	($output = stream_get_contents($pipes[1])) || $err = 1;
	fclose($pipes[1]);

	$status = proc_close($process);

// There must be a linefeed character at the end.  Remove it.
	if (substr($output, -1) === "\n")
		$output = substr($output, 0, -1);
	else
		$err = 1;

	if ($err === 0 && ($status === 0 || $output !== 'OK'))
		$retval = $output;

	return $retval;
}

?>

Open in new window


I have a form posting the username, password and a hidden variable to trigger the code to test a new password:
 
<form action="passwordtest.php" method="post" name="test">
Username: <input name="user" type="text">
<P>
Password <input name="newpass" type="text">
<input name="op" type="hidden" value="new"><br>
<input name="Submit" type="submit" value="submit">
</form>

Open in new window


Now, here... on the page that is catching the the form post and checking the password strength, is where things seem to break down. (Note: There also seems to be some extra code included from the article, for use if you are not using the pwqcheck script.) I've tried many different variations of all the code and the page either just ends up 'blank' or it throws an error complaining about an undefined fail() function.
 
<?php
require 'pwqcheck.php';
if ($_POST["user"]) {
$user=$_POST["user"];
}

if ($_POST["newpass"]) {
$newpass=$_POST["newpass"];
}

if ($_POST["op"]) {
$op=$_POST["op"];
}

// Do we have the pwqcheck(1) program from the passwdqc package?
$use_pwqcheck = TRUE;
// We can override the default password policy
$pwqcheck_args = '';
#$pwqcheck_args = 'config=/etc/passwdqc.conf';

function my_pwqcheck($newpass, $oldpass = '', $user = '')
{
	global $use_pwqcheck, $pwqcheck_args;
	if ($use_pwqcheck)
		return pwqcheck($newpass, $oldpass, $user, '', $pwqcheck_args);
		echo pwqcheck($newpass);
}

/* Some really trivial and obviously-insufficient password strength checks -
 * we ought to use the pwqcheck(1) program instead. */

	$check = '';
	if (strlen($newpass) < 7)
		$check = 'way too short';
	else if (stristr($oldpass, $newpass) ||
	    (strlen($oldpass) >= 4 && stristr($newpass, $oldpass)))
		$check = 'is based on the old one';
	else if (stristr($user, $newpass) ||
	    (strlen($user) >= 4 && stristr($newpass, $user)))
		$check = 'is based on the username';
	if ($check)
		return "Bad password ($check)";
	return 'OK';

if ($op === 'new') {
	if (($check = my_pwqcheck($pass, '', $user)) !== 'OK')
		fail($check);
		}
?>

Open in new window


I can't tell if the password is being accepted or rejected, so am unable to proceed with creating the rest of the page to enter the password into the DB or notify the user their password has been rejected.

Can someone please provide some specific insight into how to get this "passphrase strength checking and enforcement" script working?

Thanks!

Tom
0
Comment
Question by:PierceWeb
  • 5
  • 4
9 Comments
 
LVL 13

Expert Comment

by:dsmile
ID: 34170363
Problems're lying in this file passwordtest.php

1. Line 43: return "Bad password ($check)"; It causes your page to display blank when there's error.
2. Line 44: return 'OK';  It causes your page to display blank.
3. Line 47: fail($check) --> there's no such a function named fail(), that's why it gives you error.
It's really strange that you can see error on undefined function fail() because your script always ends at line 43 or 44.
0
 
LVL 13

Expert Comment

by:dsmile
ID: 34170387
Judge from your passwordtest.php file, I really don't know what you want to achieve.

If code from line 32 through 43 are supposed to be in function my_pwqcheck, and you just want to test whether this new function runs or not, then I modified it as below
<?php

require 'pwqcheck.php';



if ($_POST["user"]) {

$user=$_POST["user"];

}



if ($_POST["newpass"]) {

$newpass=$_POST["newpass"];

}



if ($_POST["op"]) {

$op=$_POST["op"];

}



// Do we have the pwqcheck(1) program from the passwdqc package?

$use_pwqcheck = TRUE;

// We can override the default password policy

$pwqcheck_args = '';

#$pwqcheck_args = 'config=/etc/passwdqc.conf';



function my_pwqcheck($newpass, $oldpass = '', $user = '')

{

        global $use_pwqcheck, $pwqcheck_args;

        if ($use_pwqcheck) {  //you should always use this brackets so that you won't be confused between logic

                return pwqcheck($newpass, $oldpass, $user, '', $pwqcheck_args);

		}



                //echo pwqcheck($newpass); //what is this anyway?



/* Some really trivial and obviously-insufficient password strength checks -

 * we ought to use the pwqcheck(1) program instead. */



        $check = '';

        if (strlen($newpass) < 7) {

                $check = 'way too short';

		}

        else if (stristr($oldpass, $newpass) ||

            (strlen($oldpass) >= 4 && stristr($newpass, $oldpass))) {

                $check = 'is based on the old one';

		}

        else if (stristr($user, $newpass) ||

            (strlen($user) >= 4 && stristr($newpass, $user))) {

                $check = 'is based on the username';

		}



        if ($check) {

                return "Bad password ($check)";

		}



        return 'OK';

}



if ($op === 'new') {

        if (($check = my_pwqcheck($newpass, '', $user)) !== 'OK') {

                //fail($check); //what is this again?

				die($check);

		}

}

?>

Open in new window

0
 
LVL 2

Author Comment

by:PierceWeb
ID: 34173592
Hi dsmile,

Thanks for your response. I won't be able to test the code you supplied until this evening, but I'll be sure to let you know what I find.

The passwordtest.php page is pretty much a regurgitation of the code I found in the cited article, as best I could determine. Here's the article URL:
http://www.openwall.com/articles/PHP-Users-Passwords#enforcing-password-policy

The goal is to build a new-user creation page that checks the strength of the user's password, prior to accepting it and inserting it into the database as part of their log-in credentials. The first step I am trying to accomplish is ensuring the new user has entered a STRONG password. Once I accomplish that, I'll be able to create the rest of what's needed.

Any additional advice I can test this evening is greatly appreciated.

Thanks!  Tom
0
 
LVL 13

Expert Comment

by:dsmile
ID: 34174674
OK then.
My code in post 34170387 has already wrap it up for you as shown in your provided article.
I'll wait for your feedback :)
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 2

Author Comment

by:PierceWeb
ID: 34174702
Thanks dsmile.

I'll get back to you this evening.

I appreciate your assistance. Tom
0
 
LVL 2

Author Comment

by:PierceWeb
ID: 34177889
Hi dsmile,

I tried your code additions on the passwordtest.php page and it does return a result now. Unfortunately, no matter what password I enter into form it responds with "Bad passphrase (check failed)".

I'm not sure what it is, but something is still not working.

Do you have any ideas on what might make this entire script package work?

Thanks, Tom

0
 
LVL 13

Accepted Solution

by:
dsmile earned 500 total points
ID: 34180329
That message, Tom, is default message of pwqcheck() function

In the beginning of that php file, you can see these lines

/*
 * The pwqcheck() function is a wrapper around the pwqcheck(1) program from
 * the passwdqc package:
 *
 * http://www.openwall.com/passwdqc/
 *
 * Returns 'OK' if the new password/passphrase passes the requirements.
 * Otherwise returns a message explaining one of the reasons why the
 * password/passphrase is rejected.

So if you want to use pwqcheck(), you have to install passwdqc first.
I think these actions might be needed in order to get something right:
1. install passwdqc library and make sure it runs properly
2. run the php script again
3. debug the output case by case

I'm afraid I can only assist you this far, Tom
0
 
LVL 2

Author Comment

by:PierceWeb
ID: 34181433
Hi dsmile,

Thank you very much for your assistance.

I was under the impression that pwqcheck() could be used by accessing it via PHP. It looks like I won't be able to use the program then, as the site I wanted to use it on is hosted on a shared server and I don't have administrative rights to install pass the passwdqc module on the server.

Thanks again for your help!

Best regards,

Tom
0
 
LVL 2

Author Comment

by:PierceWeb
ID: 34181595
In the spirit of community, and to assist those who will come in search of a PHP script that can validate the strength of a password posted to it, below I have included a script I located and have done a slight bit of tweaking to. It still needs some work, but it's a good start.

Cheers!

Tom

 
<?php

$pwd = $_POST['pwd'];

if( strlen($pwd) < 8 ) {
	$error .= "Password too short! <br />";
}

if( strlen($pwd) > 20 ) {
	$error .= "Password too long! <br />";
}

if( !preg_match("#[0-9]+#", $pwd) ) {
	$error .= "Password must include at least one number! <br />";
}


if( !preg_match("#[a-z]+#", $pwd) ) {
	$error .= "Password must include at least one lowercase letter! <br />";
}


if( !preg_match("#[A-Z]+#", $pwd) ) {
	$error .= "Password must include at least one UPPERSCASE letter! <br />";
}



if( !preg_match("#\W+#", $pwd) ) {
	$error .= "Password must include at least one symbol! <br />";
}


if($error){
	echo "Password validation failure (password not strong enough): $error";
} else {
	echo "Your password passes our site requirements.";
}

?>

Open in new window

0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

SHARE your personal details only on a NEED to basis. Take CHARGE and SECURE your IDENTITY. How do I then PROTECT myself and stay in charge of my own Personal details (and) - MY own WAY...
Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now