first commit
This commit is contained in:
69
classes/rules/FilterTrapRule.php
Normal file
69
classes/rules/FilterTrapRule.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
use PrestaShop\PrestaShop\Core\Crypto\PhpEncryption;
|
||||
|
||||
class FilterTrapRule implements RuleInterface
|
||||
{
|
||||
public function execute()
|
||||
{
|
||||
// 1. Only analyze heavy requests (filters/sorting)
|
||||
if (!Tools::getIsset('q') && !Tools::getIsset('order')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$context = Context::getContext();
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
// 2. Allow whitelisted Bots (Google/Bing)
|
||||
// We trust them not to spam. If they do, use robots.txt.
|
||||
$ua = isset($_SERVER['HTTP_USER_AGENT']) ? strtolower($_SERVER['HTTP_USER_AGENT']) : '';
|
||||
if (strpos($ua, 'googlebot') !== false || strpos($ua, 'bingbot') !== false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3. Check if user is already verified in this session
|
||||
if (isset($context->cookie->bot_verified) && $context->cookie->bot_verified == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 4. Check for Incoming Token (Returning from Verify Controller)
|
||||
$incoming_token = Tools::getValue('bot_token');
|
||||
if ($incoming_token) {
|
||||
try {
|
||||
// Verify Token
|
||||
$encryption = new PhpEncryption(_NEW_COOKIE_KEY_);
|
||||
$decrypted_ip = $encryption->decrypt($incoming_token);
|
||||
|
||||
if ($decrypted_ip === $ip) {
|
||||
// SUCCESS: User ran JS, posted back, and IP matches.
|
||||
$context->cookie->bot_verified = 1;
|
||||
$context->cookie->write(); // Force save
|
||||
return true;
|
||||
} else {
|
||||
// Token mismatch (stolen URL?)
|
||||
BotLogger::logBan($ip, 'INVALID_TOKEN');
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
die('Security Token Mismatch');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// Garbage token
|
||||
BotLogger::logBan($ip, 'GARBAGE_TOKEN');
|
||||
die('Access Denied');
|
||||
}
|
||||
}
|
||||
|
||||
// 5. If we are here: Heavy request + No Cookie + No Token.
|
||||
// Redirect to the Trap (Verify Controller)
|
||||
|
||||
$current_url = $_SERVER['REQUEST_URI'];
|
||||
// Remove existing bot_token if present to avoid loops
|
||||
$current_url = preg_replace('/([?&])bot_token=[^&]+(&|$)/', '$1', $current_url);
|
||||
|
||||
// Encode target URL safely
|
||||
$target = urlencode($current_url);
|
||||
|
||||
$link = $context->link->getModuleLink('botlimiter', 'verify', ['return_url' => $target]);
|
||||
|
||||
Tools::redirect($link);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
18
classes/rules/HeadRequestRule.php
Normal file
18
classes/rules/HeadRequestRule.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
class HeadRequestRule implements RuleInterface
|
||||
{
|
||||
public function execute()
|
||||
{
|
||||
// Detect HEAD request with Filter parameters
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'HEAD' && (Tools::getIsset('q') || Tools::getIsset('order'))) {
|
||||
|
||||
// Log for Fail2Ban
|
||||
BotLogger::logBan($_SERVER['REMOTE_ADDR'], 'HEAD_REQUEST_SPAM');
|
||||
|
||||
header('HTTP/1.1 405 Method Not Allowed');
|
||||
die('Method Not Allowed');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
8
classes/rules/RuleInterface.php
Normal file
8
classes/rules/RuleInterface.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
interface RuleInterface
|
||||
{
|
||||
/**
|
||||
* @return bool|void Returns true if passed, calls exit/redirect if failed
|
||||
*/
|
||||
public function execute();
|
||||
}
|
||||
Reference in New Issue
Block a user