shell bypass 403
<?php
/**
* @package admintools
* @copyright Copyright (c)2010-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\Component\AdminTools\Administrator\Model;
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\MVC\Model\BaseModel;
use Joomla\Utilities\IpHelper;
#[\AllowDynamicProperties]
class EmergencyofflineModel extends BaseModel
{
/**
* Checks if the Emergency Off-Line Mode .htaccess backup exists
*
* @return bool
*/
public function isOffline(): bool
{
$backupFile = $this->getPublicFolder() . '/.htaccess.eom';
if (!File::exists($backupFile))
{
return false;
}
$filedata = @file_get_contents($backupFile) ?: '';
return substr($filedata, 0, 48) === '## EOMBAK - Do not remove this line or this file';
}
/**
* Tries to put the site in Emergency Off-Line Mode, backing up the original .htaccess file
*
* @return bool True on success
*/
public function putOffline(): bool
{
// If the backup doesn't exist, try to create it
$htaccessFilePath = $this->getPublicFolder() . '/.htaccess';
if (!$this->isOffline())
{
$backupFile = $this->getPublicFolder() . '/.htaccess.eom';
$sourceFile = $htaccessFilePath;
$sourceData = @file_get_contents($sourceFile) ?: '';
$sourceData = "## EOMBAK - Do not remove this line or this file\n" . $sourceData;
$result = File::write($backupFile, $sourceData);
if (!$result)
{
return false;
}
if (@file_exists($sourceFile))
{
File::delete($sourceFile);
}
}
// Create the offline.html file, if it doesn't exist. If you can't create it, don't worry too much.
$offlineFile = $this->getPublicFolder() . '/offline.html';
if (!@file_exists($offlineFile))
{
$app = Factory::getApplication();
$message = $app->get('offline_message');
$sitename = $app->get('sitename');
$langTag = $app->getLanguage()->getTag();
$fileContents = <<<ENDHTML
<html lang="$langTag">
<head>
<title>$sitename</title>
<meta name="color-scheme" content="light dark">
<style>
body{font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"}h1{font-size:1.5em;padding-bottom:0.5em;border-bottom:thin solid rgba(0,0,0,.1)}.container{padding:0;height:99vh;width:99vw;display:flex;justify-content:center;align-items:center}.banner{min-width:100px;max-width:800px;text-align:center;background:rgba(0,0,0,.2);padding:1em 3em;border:thin solid rgba(0,0,0,.3);border-radius:1em}@media (prefers-color-scheme: dark){h1{border-color:rgba(255,255,255,.3)}.banner{background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.1)}}
</style>
</head>
<body>
<div class="container">
<div class="banner">
<h1>
$sitename
</h1>
<p>
$message
</p>
</div>
</div>
</body>
</html>
ENDHTML;
File::write($offlineFile, $fileContents);
}
$htaccess = $this->getHtaccess();
return File::write($htaccessFilePath, $htaccess);
}
/**
* Puts the site back on-line
*
* @return bool True on success
*/
public function putOnline(): bool
{
if (!$this->isOffline())
{
return false;
}
$htaccessPath = $this->getPublicFolder() . '/.htaccess';
$oldHtaccessPath = $this->getPublicFolder() . '/.htaccess.eom';
if (@file_exists($htaccessPath) && !File::delete($htaccessPath))
{
return false;
}
if (!@file_exists($oldHtaccessPath))
{
return true;
}
$fileData = @file_get_contents($oldHtaccessPath) ?: '';
// Removes the "## EOMBAK - Do not remove this line or this file" line
$fileData = substr($fileData, 49);
if (File::write($htaccessPath, $fileData))
{
return File::delete($oldHtaccessPath);
}
return false;
}
/**
* Returns the contents of the stealthy .htaccess file
*
* @return string
*/
public function getHtaccess()
{
// Sniff the .htaccess for a RewriteBase line
$rewriteBase = '';
$sourceFile = $this->getPublicFolder() . '/.htaccess.eom';
$sourceFile = @file_exists($sourceFile) ? $sourceFile : $this->getPublicFolder() . '/.htaccess';
if (@file_exists($sourceFile))
{
$sourceData = @file($sourceFile);
foreach ($sourceData as $line)
{
$line = trim($line);
if (substr($line, 0, 12) == 'RewriteBase ')
{
$rewriteBase = $line;
break;
}
}
}
// And finally create our stealth .htaccess
$ip = IpHelper::getIp();
$ip = str_replace('.', '\\.', $ip);
return <<<HTACCESS
RewriteEngine On
$rewriteBase
RewriteCond %{REMOTE_ADDR} !$ip
RewriteCond %{REQUEST_URI} !offline\.html
RewriteCond %{REQUEST_URI} !(\.png|\.jpg|\.gif|\.jpeg|\.bmp|\.swf|\.css|\.js)$
RewriteRule (.*) offline.html [R=307,L]
HTACCESS;
}
/**
* Returns the absolute filesystem folder to the site's public web root directory.
*
* Joomla! 5 can be installed with a custom public folder. In this case the .htaccess file needs to be written in
* the public directory.
*
* @return string
*
* @since 7.4.3
*/
private function getPublicFolder(): string
{
return !defined('JPATH_PUBLIC') ? JPATH_ROOT : JPATH_PUBLIC;
}
}