shell bypass 403
<?php /** * @package admintools * @copyright Copyright (c)2010-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ use Joomla\CMS\Application\SiteApplication; use Joomla\CMS\Exception\ExceptionHandler; use Joomla\CMS\Factory; use Joomla\CMS\Uri\Uri; defined('_JEXEC') || die; class AtsystemFeatureShield404 extends AtsystemFeatureAbstract { private static $previousExceptionHandler; private static $blockedUrls; /** @var AtsystemUtilExceptionshandler */ private static $exceptionHandler; protected $loadOrder = 2; public static function handleError($error) { static::doErrorHandling($error); } public static function handleException($exception) { // If this isn't a Throwable then bail out if (!($exception instanceof Throwable) && !($exception instanceof Exception)) { throw new InvalidArgumentException( sprintf('The error handler requires an Exception or Throwable object, a "%s" object was given instead.', get_class($exception)) ); } static::doErrorHandling($exception); } private static function doErrorHandling($error) { $app = Factory::getApplication(); $isAdmin = false; if (method_exists($app, 'isClient')) { $isAdmin = $app->isClient('administrator'); } elseif (method_exists($app, 'isAdmin')) { $isAdmin = $app->isAdmin(); } if ($isAdmin || ((int) $error->getCode() !== 404)) { // Proxy to the previous exception handler if available, otherwise just render the error page if (self::$previousExceptionHandler) { call_user_func_array(self::$previousExceptionHandler, [$error]); } else { ExceptionHandler::render($error); } } $rows = explode("\n", static::$blockedUrls); $blockedURLs = array_map('trim', $rows); $root = Uri::root(); $currentURL = Uri::getInstance(); $currentPath = $currentURL->toString(['scheme', 'host', 'port', 'path']); // Remove the root from the current path so we can work with relative URLs $currentPath = str_replace($root, '', $currentPath); $currentPath = static::removeLanguageTag($currentPath); $currentPath = trim($currentPath, '/'); $block = false; foreach ($blockedURLs as $blockPattern) { $shouldNegate = false; // If the pattern starts with a !, we're going to negate the assumption if (substr($blockPattern, 0, 1) == '!') { $blockPattern = substr($blockPattern, 1); $shouldNegate = true; } $blockPattern = trim($blockPattern, '/'); $match = fnmatch($blockPattern, $currentPath); // Should I invert the result? if ($shouldNegate) { $match = !$match; } $block = $match; // No need to continue if we have to block the request if ($block) { break; } } if ($block) { static::$exceptionHandler->logAndAutoban('404shield'); } // Proxy to the previous exception handler if available, otherwise just render the error page if (self::$previousExceptionHandler) { call_user_func_array(self::$previousExceptionHandler, [$error]); } else { ExceptionHandler::render($error); } } /** * Removes the language tag from the URLs generated by multilanguage sites. * * @param $pathURL * * @return string */ private static function removeLanguageTag($pathURL) { /** @var SiteApplication $app */ $app = Factory::getApplication(); $hasLanguageFilter = false; if (method_exists($app, 'getLanguageFilter')) { $hasLanguageFilter = $app->getLanguageFilter(); } if (!$hasLanguageFilter) { return $pathURL; } $db = Factory::getDbo(); // Let's get the list of SEF code used in the URLs of the published languages $query = $db->getQuery(true) ->select($db->qn('sef')) ->from($db->qn('#__languages')) ->where($db->qn('published') . ' = ' . $db->q('1')); $languages = $db->setQuery($query)->loadColumn(); foreach ($languages as $lang) { $lang .= '/'; // Replace only the starting string if (strpos($pathURL, $lang) !== 0) { continue; } $pathURL = substr($pathURL, strlen($lang)); // There can be only one language tag in the URL, so if we get here it means that there's nothing left to do break; } return $pathURL; } /** * Is this feature enabled? * * @return bool */ public function isEnabled() { // Assign those values to our static variables so we can reference to them in the static context static::$blockedUrls = $this->cparams->getValue('404shield', "wp-admin.php\nwp-login.php\nwp-content/*\nwp-admin/*"); static::$exceptionHandler = $this->exceptionsHandler; return ($this->cparams->getValue('404shield_enable', 1)); } public function onAfterInitialise() { // Joomla 3: Set the JError handler for E_ERROR to be the class' handleError method. if (class_exists('JError')) { JError::setErrorHandling(E_ERROR, 'callback', ['AtsystemFeatureShield404', 'handleError']); } // Register the previously defined exception handler so we can forward errors to it self::$previousExceptionHandler = set_exception_handler(['AtsystemFeatureShield404', 'handleException']); } }