0

I am trying to write a Java program that reads a password from a user, hashes it, then sends it to a PHP script on my website. This PHP script compares the hashed password in the database to the one passed to the script.

According this this answer on Stackoverflow, Joomla! uses PHPass to encrypt passwords, rather than the previous MD5. What I need to do, is encrypt the password in the Java application, and send the hashed version to the server to check. I found this port of PHPass in Java. I tested it out, but sadly, it does not work.

I have a user, test with the password test set up on my Joomal! site. In the database, the password is:

$2y$10$d8TS1ghHSGPqpxtmzgvsN.905fIbgZqtICvaQzKDSl2bNaEbQy7ZW

But using PHPass (in Java), the output hash is:

$S$DNrrYw1XFU2dAKUaQhiJV/1eYBYvQHEMOJtqatuo0LJ8JG/WhK54

This is the script I am using on my website to test the passwords, checkuser.php (http://neonorb.com/software/checkuser.php), (sorry about the bad formatting):

<?php
  include('checkuserfunction.php');
  echo checkUser($_GET['user'], $_GET['pass'], $_GET['package']);
?>

checkuserfunction.php (http://neonorb.com/software/checkuserfunction.php), (sorry about the bad formatting):

<?php
  function checkUser($user, $pass, $package){
    /**
 * Joomla! External authentication script
 *
 * @author vdespa
 * Version 1.0
 *
 * Code adapted from /index.php
 *
 * @package    Joomla.Site
 *
 * @copyright  Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 */

if (version_compare(PHP_VERSION, '5.3.1', '<'))
{
    die('Your host needs to use PHP 5.3.1 or higher to run this version of Joomla!');
}

/**
 * Constant that is checked in included files to prevent direct access.
 * define() is used in the installation folder rather than "const" to not error for PHP 5.2 and lower
 */
define('_JEXEC', 1);

if (file_exists(__DIR__ . '/defines.php'))
{
    include_once __DIR__ . '/defines.php';
}

if (!defined('_JDEFINES'))
{
    define('JPATH_BASE', '/home4/neonorb/public_html');
    require_once JPATH_BASE . '/includes/defines.php';
}

require_once JPATH_BASE . '/includes/framework.php';

// Instantiate the application.
$app = JFactory::getApplication('site');

// JFactory
require_once (JPATH_BASE .'/libraries/joomla/factory.php');


$credentials['username'] = $user;
$credentials['password'] = $pass;

/**
 * Code adapted from plugins/authentication/joomla/joomla.php
 *
 * @package     Joomla.Plugin
 * @subpackage  Authentication.joomla
 *
 * @copyright   Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

// Get a database object
$db    = JFactory::getDbo();
$query = $db->getQuery(true)
    ->select('id, password')
    ->from('#__users')
    ->where('username=' . $db->quote($credentials['username']));

$db->setQuery($query);
$result = $db->loadObject();

if ($result)
{
    echo $credentials['password']."<br>";
    echo $result->password."<br>";
    //$match = JUserHelper::verifyPassword($credentials['password'], $result->password, $result->id);
    $match = $credentials['password'] == $result->password;
    $id = $result->id;
    jimport( 'joomla.access.access' );
    $groups = JAccess::getGroupsByUser($id, false);
    $db = JFactory::getDbo();
    $db->setQuery(
        'SELECT `id` FROM `#__usergroups` WHERE \''.$package.'\' = title'
    );
    $groupid .= $db->loadResult();
    if ($match === true)
    {
        // Bring this in line with the rest of the system
        $user = JUser::getInstance($result->id);
        if(in_array($groupid, $groups)){
          return 1;
        }else{
          return 2;
        }
    }else{
      return 0;
    }
} else {
  return 0;
}
  }
?>

I call this script like this:

checkuser.php?user=<username>&pass=<hashed-password>&package=derby-pro-paid

The package thing is to test to see if that particular user has paid for the package, for our purposes, it will always be derby-pro-paid.

The first line printed is the password entered to the function, the second, the one stored in the database. The third, the return of the function.

Returning 0 means that the password was incorrect. 1 means that the password was correct. 2 is unneeded for this, it means that the user has not paid for that package. As long as package is set to derby-pro-paid, it should never return 2.

Here is my code for calling the hash method in Java:

PasswordHasher passwordHasher = new PasswordHasher();
Log.debug(passwordHasher.createHash("test"));

Why doesn't this Java method of creating Joomla! hashes work correctly?

Community
  • 1
  • 1
Chris Smith
  • 2,928
  • 4
  • 27
  • 59
  • 1
    I don't see a question? – Epodax Sep 17 '15 at 12:57
  • Updated with question at end. – Chris Smith Sep 17 '15 at 14:28
  • Why are you doing the hashing in Java rather than in the php? One of the problems there is that you don't know the salt so it is not going to match. You don't want to pass the hashed version in because it's in java anymore than you would in PHP. You use password_verify() to compare the passed in password with the hashed version in the database http://php.net/manual/en/function.password-verify.php. – Elin Sep 18 '15 at 03:00
  • @Elin I am worried about sending the password over the internet in plain text. Sniffers could just see the password. I don't have HTTPS for my website so that is the problem. I was thinking of possibly requesting the salt from the server from the Java application, then hashing it, then testing it back with the server. – Chris Smith Sep 18 '15 at 11:40
  • That's just how it goes. There is not any alternative. If you send the encrypted one then anyone who gets your database can just login as if you were saving your passwords in plain text. – Elin Sep 19 '15 at 09:48
  • I see a rogue dot between `$groupid` and `=` that needs to be removed. I would also like to offer an untested rescripting of half of your code -- consider this snippet: https://3v4l.org/fOBLf Please consider joining us at [joomla.se] Stack Exchange, there is a dedicated pool of volunteers there. @Chris – mickmackusa Nov 07 '19 at 07:37

1 Answers1

0

I have a user, test with the password test set up on my Joomal! site. In the database, the password is:

$2y$10$d8TS1ghHSGPqpxtmzgvsN.905fIbgZqtICvaQzKDSl2bNaEbQy7ZW

But using PHPass (in Java), the output hash is:

$S$DNrrYw1XFU2dAKUaQhiJV/1eYBYvQHEMOJtqatuo0LJ8JG/WhK54

You want to use a compatible bcrypt implementation. PHPass isn't bcrypt.

Scott Arciszewski
  • 33,610
  • 16
  • 89
  • 206