Solved

Need assistance with PHP passphrase strength checking and enforcement - passwdqc

Posted on 2010-11-18
9
965 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
Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

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

Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

One of the biggest threats facing all high-value targets are APT's.  These threats include sophisticated tactics that "often starts with mapping human organization and collecting intelligence on employees, who are nowadays a weaker link than network…
FAQ pages provide a simple way for you to supply and for customers to find answers to the most common questions about your company. Here are six reasons why your company website should have a FAQ page
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…

832 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