T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/domains/soundstudiopro.com/private_html/includes/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/soundstudiopro.com/private_html/includes/shield.php
<?php
/**
 * SHIELD PROTECTION MIDDLEWARE
 * 
 * Include this file at the top of your main entry points (index.php, etc.)
 * to enable bot protection screening.
 * 
 * Usage: require_once 'includes/shield.php';
 * 
 * If Shield is disabled, this file does nothing.
 */

// Load config (only if not already loaded)
if (!defined('SHIELD_ENABLED')) {
    require_once __DIR__ . '/../config/shield_config.php';
}

// Start session if not started (and headers not sent)
if (session_status() === PHP_SESSION_NONE && !headers_sent()) {
    session_start();
}

/**
 * Main Shield check - call this to protect a page
 */
function shield_protect() {
    global $SHIELD_BOT_WHITELIST, $SHIELD_IP_WHITELIST, $SHIELD_SKIP_PATHS, $SHIELD_SKIP_EXTENSIONS;
    
    // Check if Shield is enabled
    if (!shield_is_enabled()) {
        return true; // Shield disabled, allow all
    }
    
    $request_uri = $_SERVER['REQUEST_URI'] ?? '/';
    $request_path = parse_url($request_uri, PHP_URL_PATH);
    $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
    $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
    
    // Skip static files
    $extension = strtolower(pathinfo($request_path, PATHINFO_EXTENSION));
    if (in_array($extension, $SHIELD_SKIP_EXTENSIONS)) {
        return true;
    }
    
    // Skip configured paths
    foreach ($SHIELD_SKIP_PATHS as $skip_path) {
        if (strpos($request_path, $skip_path) === 0) {
            return true;
        }
    }
    
    // Check IP whitelist
    if (shield_is_ip_whitelisted($ip, $SHIELD_IP_WHITELIST)) {
        return true;
    }
    
    // Whitelist speed test and monitoring tools (GTmetrix, Lighthouse, etc.)
    $speed_test_bots = ['GTmetrix', 'PageSpeed', 'Lighthouse', 'PTST', 'Chrome-Lighthouse',
                        'pingdom', 'uptimerobot', 'StatusCake', 'Site24x7', 'Datadog', 
                        'WebPageTest', 'YSlow', 'DareBoost'];
    foreach ($speed_test_bots as $bot) {
        if (stripos($user_agent, $bot) !== false) {
            shield_log('speed_test_allowed', $ip, ['bot' => $bot, 'action' => 'bypassed']);
            return true;
        }
    }
    
    // Check for verified search engine bots
    if (shield_is_verified_bot($ip, $user_agent, $SHIELD_BOT_WHITELIST)) {
        shield_log('bot_allowed', $ip, ['bot' => 'verified_search_engine', 'ua' => $user_agent]);
        return true;
    }
    
    // Check for valid verification cookie
    if (shield_has_valid_cookie()) {
        return true;
    }
    
    // Check rate limit for challenges
    if (!shield_check_rate_limit($ip)) {
        shield_log('rate_limited', $ip, ['action' => 'blocked']);
        http_response_code(429);
        die('Too many requests. Please try again later.');
    }
    
    // Redirect to challenge
    shield_redirect_to_challenge($request_uri);
    exit;
}

/**
 * Check if IP is in whitelist (supports CIDR notation)
 */
function shield_is_ip_whitelisted($ip, $whitelist) {
    foreach ($whitelist as $allowed) {
        if (strpos($allowed, '/') !== false) {
            // CIDR notation
            if (shield_ip_in_cidr($ip, $allowed)) {
                return true;
            }
        } else {
            if ($ip === $allowed) {
                return true;
            }
        }
    }
    return false;
}

/**
 * Check if IP is in CIDR range
 */
function shield_ip_in_cidr($ip, $cidr) {
    list($subnet, $mask) = explode('/', $cidr);
    $ip_long = ip2long($ip);
    $subnet_long = ip2long($subnet);
    $mask_long = -1 << (32 - $mask);
    return ($ip_long & $mask_long) === ($subnet_long & $mask_long);
}

/**
 * Verify if a bot claiming to be a search engine is legitimate
 * Uses reverse DNS verification
 */
function shield_is_verified_bot($ip, $user_agent, $whitelist) {
    foreach ($whitelist as $bot_name => $config) {
        // Check if user agent contains the bot identifier
        if (stripos($user_agent, $config['ua_contains']) === false) {
            continue;
        }
        
        // Do reverse DNS lookup
        $hostname = gethostbyaddr($ip);
        if ($hostname === $ip) {
            // DNS lookup failed - not verified
            shield_log('bot_unverified', $ip, ['claimed' => $bot_name, 'reason' => 'dns_failed']);
            return false;
        }
        
        // Check if hostname ends with allowed suffix
        $verified = false;
        foreach ($config['dns_suffix'] as $suffix) {
            if (substr($hostname, -strlen($suffix)) === $suffix) {
                // Forward DNS to verify
                $forward_ip = gethostbyname($hostname);
                if ($forward_ip === $ip) {
                    $verified = true;
                    break;
                }
            }
        }
        
        if ($verified) {
            return true;
        } else {
            shield_log('bot_unverified', $ip, [
                'claimed' => $bot_name, 
                'hostname' => $hostname,
                'reason' => 'dns_mismatch'
            ]);
            return false;
        }
    }
    
    return false;
}

/**
 * Check if visitor has valid verification cookie
 */
function shield_has_valid_cookie() {
    $cookie_name = 'shield_verified';
    
    if (!isset($_COOKIE[$cookie_name])) {
        return false;
    }
    
    $token = $_COOKIE[$cookie_name];
    
    // Parse token
    $parts = explode('.', $token);
    if (count($parts) !== 3) {
        return false;
    }
    
    list($payload_b64, $expires, $signature) = $parts;
    
    // Check expiration
    if (time() > (int)$expires) {
        return false;
    }
    
    // Verify signature
    $expected_sig = hash_hmac('sha256', $payload_b64 . '.' . $expires, SHIELD_SECRET_KEY);
    if (!hash_equals($expected_sig, $signature)) {
        return false;
    }
    
    // Optionally verify payload matches current visitor
    $payload = json_decode(base64_decode($payload_b64), true);
    if (!$payload) {
        return false;
    }
    
    // Loose IP check (first 3 octets) to allow for dynamic IPs within ISP
    $current_ip = $_SERVER['REMOTE_ADDR'] ?? '';
    $token_ip = $payload['ip'] ?? '';
    
    $current_prefix = implode('.', array_slice(explode('.', $current_ip), 0, 3));
    $token_prefix = implode('.', array_slice(explode('.', $token_ip), 0, 3));
    
    if ($current_prefix !== $token_prefix) {
        shield_log('cookie_ip_mismatch', $current_ip, [
            'token_ip' => $token_ip
        ]);
        return false;
    }
    
    return true;
}

/**
 * Generate verification cookie
 */
function shield_generate_cookie($ip, $fingerprint = '') {
    $payload = [
        'ip' => $ip,
        'fp' => substr(hash('sha256', $fingerprint), 0, 16),
        'ts' => time()
    ];
    
    $payload_b64 = base64_encode(json_encode($payload));
    $expires = time() + SHIELD_COOKIE_LIFETIME;
    $signature = hash_hmac('sha256', $payload_b64 . '.' . $expires, SHIELD_SECRET_KEY);
    
    $token = $payload_b64 . '.' . $expires . '.' . $signature;
    
    setcookie('shield_verified', $token, [
        'expires' => $expires,
        'path' => '/',
        'secure' => true,
        'httponly' => true,
        'samesite' => 'Lax'
    ]);
    
    return $token;
}

/**
 * Check rate limit for challenges
 */
function shield_check_rate_limit($ip) {
    $rate_dir = __DIR__ . '/../cache/shield_rates/';
    
    if (!is_dir($rate_dir)) {
        @mkdir($rate_dir, 0755, true);
    }
    
    $key = hash('sha256', $ip);
    $file = $rate_dir . $key . '.json';
    
    $window = 3600; // 1 hour
    $limit = SHIELD_RATE_LIMIT;
    
    $data = ['count' => 0, 'reset_time' => time() + $window];
    
    if (file_exists($file)) {
        $content = @file_get_contents($file);
        if ($content) {
            $existing = json_decode($content, true);
            if ($existing && isset($existing['reset_time'])) {
                if (time() > $existing['reset_time']) {
                    $data = ['count' => 0, 'reset_time' => time() + $window];
                } else {
                    $data = $existing;
                }
            }
        }
    }
    
    if ($data['count'] >= $limit) {
        return false;
    }
    
    $data['count']++;
    @file_put_contents($file, json_encode($data), LOCK_EX);
    
    return true;
}

/**
 * Redirect to challenge page
 */
function shield_redirect_to_challenge($return_url) {
    $challenge_token = bin2hex(random_bytes(16));
    $challenge_time = time();
    
    // Store challenge in session
    $_SESSION['shield_challenge'] = [
        'token' => $challenge_token,
        'time' => $challenge_time,
        'return_url' => $return_url
    ];
    
    // Redirect to challenge page
    $challenge_url = '/shield_challenge.php?t=' . $challenge_token;
    header('Location: ' . $challenge_url);
    exit;
}

/**
 * Log Shield events with enhanced tracking
 */
function shield_log($event, $ip, $data = []) {
    $log_dir = __DIR__ . '/../logs/';
    
    if (!is_dir($log_dir)) {
        @mkdir($log_dir, 0755, true);
    }
    
    $log_file = $log_dir . 'shield_' . date('Y-m-d') . '.log';
    
    // Enhanced log entry with more context
    $log_entry = [
        'time' => date('Y-m-d H:i:s'),
        'timestamp' => time(),
        'event' => $event,
        'ip' => $ip,
        'user_agent' => substr($_SERVER['HTTP_USER_AGENT'] ?? 'unknown', 0, 500),
        'request_uri' => $_SERVER['REQUEST_URI'] ?? '/',
        'method' => $_SERVER['REQUEST_METHOD'] ?? 'GET',
        'data' => $data
    ];
    
    @file_put_contents($log_file, json_encode($log_entry) . "\n", FILE_APPEND | LOCK_EX);
    
    // Also log to database for easier querying (if table exists)
    shield_log_to_db($log_entry);
}

/**
 * Get IP intelligence (geolocation, organization, etc.)
 * Uses ip-api.com (free, 45 requests/minute)
 */
function shield_get_ip_info($ip) {
    // Check cache first
    $cache_dir = __DIR__ . '/../cache/ip_info/';
    if (!is_dir($cache_dir)) {
        @mkdir($cache_dir, 0755, true);
    }
    
    $cache_file = $cache_dir . md5($ip) . '.json';
    
    // Cache for 24 hours
    if (file_exists($cache_file) && (time() - filemtime($cache_file)) < 86400) {
        $cached = json_decode(file_get_contents($cache_file), true);
        if ($cached) return $cached;
    }
    
    // Query ip-api.com (free, no API key needed)
    $url = "http://ip-api.com/json/" . urlencode($ip) . "?fields=status,message,country,countryCode,region,regionName,city,zip,lat,lon,timezone,isp,org,as,asname,reverse,mobile,proxy,hosting,query";
    
    $context = stream_context_create([
        'http' => [
            'timeout' => 3,
            'ignore_errors' => true
        ]
    ]);
    
    $response = @file_get_contents($url, false, $context);
    
    if ($response) {
        $data = json_decode($response, true);
        if ($data && isset($data['status']) && $data['status'] === 'success') {
            // Enhance with our own analysis
            $data['is_datacenter'] = $data['hosting'] ?? false;
            $data['is_vpn_proxy'] = $data['proxy'] ?? false;
            $data['is_mobile'] = $data['mobile'] ?? false;
            
            // Check if it's a known search engine
            $data['is_search_engine'] = false;
            $hostname = $data['reverse'] ?? '';
            $org = strtolower($data['org'] ?? '');
            $isp = strtolower($data['isp'] ?? '');
            
            if (strpos($hostname, 'googlebot.com') !== false || strpos($hostname, 'google.com') !== false) {
                $data['is_search_engine'] = true;
                $data['search_engine'] = 'Google';
            } elseif (strpos($hostname, 'search.msn.com') !== false || strpos($org, 'microsoft') !== false) {
                $data['is_search_engine'] = true;
                $data['search_engine'] = 'Bing';
            } elseif (strpos($hostname, 'yandex') !== false) {
                $data['is_search_engine'] = true;
                $data['search_engine'] = 'Yandex';
            } elseif (strpos($org, 'facebook') !== false || strpos($isp, 'facebook') !== false) {
                $data['is_search_engine'] = true;
                $data['search_engine'] = 'Facebook';
            } elseif (strpos($org, 'twitter') !== false) {
                $data['is_search_engine'] = true;
                $data['search_engine'] = 'Twitter';
            }
            
            // Cache the result
            @file_put_contents($cache_file, json_encode($data));
            
            return $data;
        }
    }
    
    // Fallback: just do reverse DNS
    $hostname = @gethostbyaddr($ip);
    return [
        'status' => 'partial',
        'query' => $ip,
        'reverse' => ($hostname !== $ip) ? $hostname : null,
        'country' => 'Unknown',
        'countryCode' => '??',
        'city' => 'Unknown',
        'isp' => 'Unknown',
        'org' => 'Unknown'
    ];
}

/**
 * Log to database for persistent tracking
 */
function shield_log_to_db($entry) {
    try {
        require_once __DIR__ . '/../config/database.php';
        $pdo = getDBConnection();
        if (!$pdo) return;
        
        // Create table if not exists (with IP info columns)
        $pdo->exec("CREATE TABLE IF NOT EXISTS shield_logs (
            id INT AUTO_INCREMENT PRIMARY KEY,
            event_time DATETIME NOT NULL,
            event_type VARCHAR(50) NOT NULL,
            ip_address VARCHAR(45) NOT NULL,
            user_agent TEXT,
            request_uri VARCHAR(500),
            request_method VARCHAR(10),
            event_data JSON,
            is_bot TINYINT(1) DEFAULT 0,
            bot_name VARCHAR(50),
            is_threat TINYINT(1) DEFAULT 0,
            country VARCHAR(100),
            country_code VARCHAR(5),
            city VARCHAR(100),
            isp VARCHAR(255),
            org VARCHAR(255),
            hostname VARCHAR(255),
            is_datacenter TINYINT(1) DEFAULT 0,
            is_vpn_proxy TINYINT(1) DEFAULT 0,
            is_search_engine TINYINT(1) DEFAULT 0,
            search_engine_name VARCHAR(50),
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            INDEX idx_event_time (event_time),
            INDEX idx_event_type (event_type),
            INDEX idx_ip (ip_address),
            INDEX idx_is_bot (is_bot),
            INDEX idx_is_threat (is_threat),
            INDEX idx_country (country_code),
            INDEX idx_is_datacenter (is_datacenter)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
        
        // Add new columns if they don't exist (for existing tables)
        try {
            $pdo->exec("ALTER TABLE shield_logs ADD COLUMN IF NOT EXISTS country VARCHAR(100)");
            $pdo->exec("ALTER TABLE shield_logs ADD COLUMN IF NOT EXISTS country_code VARCHAR(5)");
            $pdo->exec("ALTER TABLE shield_logs ADD COLUMN IF NOT EXISTS city VARCHAR(100)");
            $pdo->exec("ALTER TABLE shield_logs ADD COLUMN IF NOT EXISTS isp VARCHAR(255)");
            $pdo->exec("ALTER TABLE shield_logs ADD COLUMN IF NOT EXISTS org VARCHAR(255)");
            $pdo->exec("ALTER TABLE shield_logs ADD COLUMN IF NOT EXISTS hostname VARCHAR(255)");
            $pdo->exec("ALTER TABLE shield_logs ADD COLUMN IF NOT EXISTS is_datacenter TINYINT(1) DEFAULT 0");
            $pdo->exec("ALTER TABLE shield_logs ADD COLUMN IF NOT EXISTS is_vpn_proxy TINYINT(1) DEFAULT 0");
            $pdo->exec("ALTER TABLE shield_logs ADD COLUMN IF NOT EXISTS is_search_engine TINYINT(1) DEFAULT 0");
            $pdo->exec("ALTER TABLE shield_logs ADD COLUMN IF NOT EXISTS search_engine_name VARCHAR(50)");
        } catch (Exception $e) {
            // Columns might already exist
        }
        
        // Get IP intelligence
        $ip_info = shield_get_ip_info($entry['ip']);
        
        // Determine if this is a bot and if it's a threat
        $is_bot = 0;
        $bot_name = null;
        $is_threat = 0;
        
        $ua = $entry['user_agent'] ?? '';
        
        // Check for known good bots
        $good_bots = ['Googlebot', 'bingbot', 'DuckDuckBot', 'YandexBot', 'Baiduspider', 
                      'facebookexternalhit', 'Twitterbot', 'LinkedInBot', 'Slackbot'];
        foreach ($good_bots as $bot) {
            if (stripos($ua, $bot) !== false) {
                $is_bot = 1;
                $bot_name = $bot;
                break;
            }
        }
        
        // Check for suspicious/threat indicators
        $threat_indicators = ['verify_too_fast', 'bot_unverified', 'rate_limited', 
                              'blocked', 'bot_indicators_detected'];
        if (in_array($entry['event'], $threat_indicators)) {
            $is_threat = 1;
        }
        
        // Check for bad bot patterns
        $bad_patterns = ['python-requests', 'curl/', 'wget/', 'scrapy', 'HeadlessChrome',
                         'PhantomJS', 'selenium', 'puppeteer'];
        foreach ($bad_patterns as $pattern) {
            if (stripos($ua, $pattern) !== false) {
                $is_threat = 1;
                $is_bot = 1;
                $bot_name = $pattern;
                break;
            }
        }
        
        $stmt = $pdo->prepare("
            INSERT INTO shield_logs 
            (event_time, event_type, ip_address, user_agent, request_uri, request_method, event_data, 
             is_bot, bot_name, is_threat, country, country_code, city, isp, org, hostname,
             is_datacenter, is_vpn_proxy, is_search_engine, search_engine_name)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        ");
        $stmt->execute([
            $entry['time'],
            $entry['event'],
            $entry['ip'],
            $entry['user_agent'] ?? null,
            $entry['request_uri'] ?? null,
            $entry['method'] ?? null,
            json_encode($entry['data']),
            $is_bot,
            $bot_name,
            $is_threat,
            $ip_info['country'] ?? null,
            $ip_info['countryCode'] ?? null,
            $ip_info['city'] ?? null,
            $ip_info['isp'] ?? null,
            $ip_info['org'] ?? null,
            $ip_info['reverse'] ?? null,
            $ip_info['is_datacenter'] ?? 0,
            $ip_info['is_vpn_proxy'] ?? 0,
            $ip_info['is_search_engine'] ?? 0,
            $ip_info['search_engine'] ?? null
        ]);
    } catch (Exception $e) {
        // Silently fail - don't break the site if logging fails
        error_log("Shield DB log error: " . $e->getMessage());
    }
}

/**
 * Get Shield statistics
 */
function shield_get_stats() {
    $log_dir = __DIR__ . '/../logs/';
    $stats = [
        'challenges_today' => 0,
        'verified_today' => 0,
        'blocked_today' => 0,
        'bots_allowed' => 0,
        'bots_blocked' => 0
    ];
    
    $log_file = $log_dir . 'shield_' . date('Y-m-d') . '.log';
    
    if (file_exists($log_file)) {
        $lines = file($log_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        foreach ($lines as $line) {
            $entry = json_decode($line, true);
            if (!$entry) continue;
            
            switch ($entry['event'] ?? '') {
                case 'challenge_served':
                    $stats['challenges_today']++;
                    break;
                case 'verified':
                    $stats['verified_today']++;
                    break;
                case 'blocked':
                case 'rate_limited':
                    $stats['blocked_today']++;
                    break;
                case 'bot_allowed':
                    $stats['bots_allowed']++;
                    break;
                case 'bot_unverified':
                    $stats['bots_blocked']++;
                    break;
            }
        }
    }
    
    return $stats;
}


CasperSecurity Mini