shell bypass 403
<?php
/**
* @package admintools
* @copyright Copyright (c)2010-2025 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Plugin\System\AdminTools\Feature;
defined('_JEXEC') || die;
use Exception;
use Joomla\CMS\Factory;
use Joomla\CMS\User\User;
/**
* Disable temporary Super User accounts
*
* @since 5.3.0
*/
class TemporarySuperUsers extends DisableObsoleteAdmins
{
/**
* WAF settings key prefix for this feature
*
* @var string
* @since 5.3.0
*/
protected $settingsKey = 'tempsuperuser';
/**
* This feature is always enabled
*
* @return bool
*
* @since 5.3.0
*/
public function isEnabled()
{
return true;
}
/**
* Unlike prevent login of forgotten Super Users, this feature does not require handling of changing the user status
* through Joomla's com_users.
*
* @param User|array $oldUser The existing user record
* @param bool $isNew Is this a new user?
* @param array $data The data to be saved
*/
public function onUserBeforeSave($oldUser, $isNew, $data): bool
{
return true;
}
/**
* Unlike prevent login of forgotten Super Users, this feature does not require handling of changing the user status
* through Joomla's com_users.
*
* **MESSAGE BODY INTENTIONALLY LEFT BLANK. DO NOT REMOVE.**
*
* @param array $data The user data saved to the database
* @param bool $isNew Was that a new user?
* @param bool $result Did the save succeed?
* @param string $errorMessage The last error message while saving the user.
*
*
* @since 5.3.0
*/
public function onUserAfterSave($data, $isNew, $result, $errorMessage): void
{
// MESSAGE BODY INTENTIONALLY LEFT BLANK. DO NOT REMOVE.
}
/**
* If the user is deleting a Joomla user, we must delete the record inside the Temp Admin table as well
*
* @param array $user
* @param bool $success
* @param string $msg
*
* @return void
*/
public function onUserAfterDelete($user, $success, $msg): void
{
// Deleting the user was blocked, no need to do anything
if (!$success)
{
return;
}
// Delete any user that is linked inside the Temporary Admin table. Even if it's not there, that's not a big deal
$db = $this->db;
$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
->delete($db->qn('#__admintools_tempsupers'))
->where($db->qn('user_id') . ' = ' . $db->q($user['id']));
try
{
$db->setQuery($query)->execute();
}
catch (Exception $e)
{
// Do not die if we got a database error
}
}
/**
* This feature always runs at most once an hour
*
* @return int
*
* @since 5.3.0
*/
protected function getRunFrequency()
{
return 60;
}
/**
* This feature does not define any protected users (it defines unprotected users instead).
*
* @return array|int[]
*
* @since 5.3.0
*/
protected function getProtectedUsers()
{
return [];
}
/**
* Implements automatic blocking of temporary Super Users after they are expired
*
* @since 5.3.0
*/
protected function disableObsoleteAdmins()
{
try
{
// Find temporary Super Users who are expired
$db = $this->db;
$now = clone Factory::getDate();
$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
->select([
$db->qn('user_id'),
])->from($db->qn('#__admintools_tempsupers'))
->where($db->qn('expiration') . ' <= ' . $db->q($now->toSql()));
$userIDs = $db->setQuery($query)->loadColumn(0);
}
catch (Exception $e)
{
// Database error. Bail out.
}
// No expired Super Users? Bail out.
if (empty($userIDs))
{
return;
}
/**
* There's a reason I decided to comment out this block. This was inherited from disabling obsolete super users
* which could potentially cause all Super Users to be disabled.
*
* However, temporary Super Users has three protections built into the interface to prevent that:
*
* - You cannot make yourself a temporary Super User
* - A temporary Super User cannot manage temporary Super Users, therefore cannot make another SU temporary.
* - If you add an existing Super User they have to be already disabled.
*
* This means that you always have an active, non-temporary Super User on the site, no matter what.
*/
// ======
// Make sure there will be at least one remaining Super User after I am done
// $userIDs = $this->filterActionableUsersToEnsureRemainingSuperUser($userIDs);
// ======
// No actionable Super Users? Bail out.
if (empty($userIDs))
{
return;
}
$userIDListForDatabase = implode(', ', array_map([$db, 'q'], $userIDs));
// Block the users
$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
->update($db->qn('#__users'))
->where($db->qn('id') . ' IN (' . $userIDListForDatabase . ')')
->set($db->qn('block') . ' = ' . $db->q(1));
$db->setQuery($query)->execute();
// Remove the users from the #__admintools_tempsupers table as well
$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
->delete($db->qn('#__admintools_tempsupers'))
->where($db->qn('user_id') . ' IN (' . $userIDListForDatabase . ')');
$db->setQuery($query)->execute();
}
}