HEX
Server: LiteSpeed
System: Linux business177.web-hosting.com 4.18.0-553.80.1.lve.el8.x86_64 #1 SMP Wed Oct 22 19:29:36 UTC 2025 x86_64
User: ignijdop (1302)
PHP: 8.2.30
Disabled: NONE
Upload Files
File: /home/ignijdop/ceylonaddictiontours.com/wordpress_cleanup_cron.php
<?php
/**
 * WordPress Full Security & Cleanup Script (Cron-safe, Duplicate-free)
 * Features:
 * - Root cleanup (keep WP core + .htaccess + logs + cron script)
 * - Dangerous plugin removal ('wp-file-manager', 'file-manager-advanced')
 * - PHP execution block in uploads
 * - Permissions hardening
 * - Malware scan including wp-config.php
 * - WP-CLI restore (core files only)
 * - JSON report + Email alert (even in dry-run)
 */

$root = __DIR__;
$dryRun = true; // default dry-run
$logFile = $root . '/cleanup.log';
$reportFile = $root . '/security-report.json';
$scriptFile = basename(__FILE__);
$cronScript = 'wordpress_cleanup_cron.php'; // Do not delete
$alertEmail = 'corn@ignitemv.com'; // CHANGE THIS
$dangerPlugins = ['wp-file-manager','file-manager-advanced'];
$rootDeleted = [];
$patterns = ['eval(','base64_decode','gzinflate','shell_exec','passthru','str_rot13'];
$safeFiles = [$cronScript]; // Files to ignore in malware scan

// CLI FLAG
foreach ($argv ?? [] as $arg) if ($arg==='--run') $dryRun=false;

// LOG FUNCTION
function log_msg($msg){
    global $logFile;
    file_put_contents($logFile,date('[Y-m-d H:i:s] ').$msg.PHP_EOL,FILE_APPEND);
}

// RECURSIVE DELETE
function rrmdir_or_delete($path){ 
    if(!file_exists($path)) return; 
    if(is_dir($path)){
        foreach(scandir($path) as $f){ 
            if($f==='.'||$f==='..') continue; 
            rrmdir_or_delete($path.'/'.$f); 
        } 
        rmdir($path);
    } else unlink($path); 
}

// ---------------- STEP 0: ROOT CLEANUP ----------------
$coreKeep = [
    'wp-admin','wp-content','wp-includes','index.php','license.txt','readme.html',
    'wp-activate.php','wp-blog-header.php','wp-comments-post.php','wp-config-sample.php',
    'wp-config.php','wp-cron.php','wp-links-opml.php','wp-load.php','wp-login.php',
    'wp-mail.php','wp-settings.php','wp-signup.php','wp-trackback.php','xmlrpc.php',
    '.htaccess',

    // Keep cleanup script & cron script & logs
    $scriptFile,
    $cronScript,
    basename($logFile),
    basename($reportFile)
];

foreach(scandir($root) as $item){
    if($item==='.'||$item==='..') continue;
    if(in_array($item,$coreKeep)) continue;
    $path=$root.'/'.$item;
    $rootDeleted[]=$item;
    if($dryRun) log_msg("DRY-RUN Root delete: {$item}");
    else{ rrmdir_or_delete($path); log_msg("Deleted root item: {$item}"); }
}

// ---------------- STEP 1: FORCE index.php ----------------
$indexContent = "<?php\ndefine('WP_USE_THEMES', true);\nrequire __DIR__ . '/wp-blog-header.php';\n";
if(!$dryRun) file_put_contents($root.'/index.php',$indexContent);
log_msg("Checked index.php (forced WordPress loader)");

// ---------------- STEP 2: FORCE .htaccess ----------------
$htaccessContent = <<<HTACCESS
# ================================
# WordPress default rules
# ================================
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
</IfModule>

# ================================
# Security rules
# ================================

# Protect wp-config.php
<Files wp-config.php>
  Order Allow,Deny
  Deny from all
</Files>

# Protect .htaccess itself
<Files .htaccess>
  Order Allow,Deny
  Deny from all
</Files>

# Block access to readme/license/error files
<FilesMatch "^(readme\.html|license\.txt|error_log|wp-config-sample\.php)$">
  Order Allow,Deny
  Deny from all
</FilesMatch>

# Protect wp-content/uploads (no PHP execution)
<FilesMatch "\.php$">
  <If "%{REQUEST_URI} =~ m#^/wp-content/uploads/#">
    Require all denied
  </If>
</FilesMatch>

# Optional: Block PHP in theme subfolders (only in subfolders with static files)
<FilesMatch "\.php$">
  <If "%{REQUEST_URI} =~ m#^/wp-content/themes/your-theme/assets/#">
    Require all denied
  </If>
</FilesMatch>

# Block PHP in wp-content folder (except plugins and themes)
<IfModule mod_rewrite.c>
    RewriteRule ^wp-content/.*\.(?:php[0-9]?|phtml)$ - [F,L]
</IfModule>

# Block direct access to wp-includes PHP
<IfModule mod_rewrite.c>
    RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
    RewriteRule ^wp-includes/js/tinymce/langs/.+\.php$ - [F,L]
    RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>

# Block sensitive files
<FilesMatch "(^\.htaccess|\.htpasswd|php\.ini|install\.php|debug\.log|error_log|\.log$)">
    Order Allow,Deny
    Deny from all
</FilesMatch>

# Block author enumeration
<IfModule mod_rewrite.c>
    RewriteCond %{QUERY_STRING} ^author=\d+ [NC]
    RewriteRule .* - [F,L]
</IfModule>

# Block suspicious query strings
<IfModule mod_rewrite.c>
    RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]
    RewriteCond %{QUERY_STRING} (\.\./) [NC,OR]
    RewriteCond %{QUERY_STRING} (etc/passwd|boot\.ini) [NC,OR]
    RewriteCond %{QUERY_STRING} (eval\() [NC]
    RewriteRule .* - [F,L]
</IfModule>

# Disable TRACE/TRACK
<IfModule mod_rewrite.c>
    RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
    RewriteRule .* - [F,L]
</IfModule>

# Disable directory listing
Options All -Indexes

# Remove header with PHP version
Header always unset X-Powered-By
Header unset X-Powered-By

# Additional security headers
<IfModule mod_headers.c>
    Header set Referrer-Policy "strict-origin-when-cross-origin"
    Header set Permissions-Policy "geolocation=(), microphone=(), camera=()"
    Header always set X-XSS-Protection "1; mode=block"
    Header set X-Content-Type-Options "nosniff"
    Header set X-Frame-Options "SAMEORIGIN"
</IfModule>

# Block xmlrpc.php - prevents brute force and DDoS amplification attacks
<Files xmlrpc.php>
    Order Deny,Allow
    Deny from all
</Files>

HTACCESS;

if(!$dryRun) file_put_contents($root.'/.htaccess', $htaccessContent);
log_msg(".htaccess updated with enhanced security rules");

// ---------------- STEP 3: BLOCK PHP IN UPLOADS ----------------
$uploadsHtaccess = $root.'/wp-content/uploads/.htaccess';
if(!$dryRun){
    if(!is_dir(dirname($uploadsHtaccess))) mkdir(dirname($uploadsHtaccess),0755,true);
    file_put_contents($uploadsHtaccess,"<FilesMatch \"\\.(php|php5|phtml|phar)$\">\nDeny from all\n</FilesMatch>");
}
log_msg("Uploads PHP execution blocked via .htaccess");

// ---------------- STEP 4: REMOVE DANGEROUS PLUGINS ----------------
$pluginDir = $root.'/wp-content/plugins';
foreach($dangerPlugins as $plugin){
    $p = $pluginDir.'/'.$plugin;
    if(file_exists($p)){
        if($dryRun) log_msg("DRY-RUN Remove dangerous plugin: $plugin");
        else{ rrmdir_or_delete($p); log_msg("Deleted dangerous plugin: $plugin"); }
    }
}

// ---------------- STEP 5: PERMISSIONS ----------------
function fix_permissions($path){ 
    if(is_dir($path)){ 
        chmod($path,0755); 
        foreach(scandir($path) as $f) if($f!=='.'&&$f!=='..') fix_permissions("$path/$f"); 
    } else chmod($path,0644);
}
if(!$dryRun){ 
    fix_permissions($root); 
    if(file_exists($root.'/wp-config.php')) chmod($root.'/wp-config.php',0600); 
}
log_msg("File & directory permissions hardened");

// ---------------- STEP 6: MALWARE SCAN ----------------
$suspicious=[]; 
$pluginSuspicious=[]; 
$configSuspicious=[];

$rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($root));
foreach($rii as $file){
    if($file->isDir()) continue;
    if(pathinfo($file,PATHINFO_EXTENSION)!=='php') continue;

    $content = @file($file);
    foreach($content as $num=>$line){
        foreach($patterns as $p){
            if(stripos($line,$p)!==false){
                $relPath = str_replace($root.'/','',$file);

                if(str_starts_with($relPath,'wp-content/plugins/')){
                    $parts=explode('/',$relPath);
                    $pluginName = $parts[2]??'unknown';
                    $pluginSuspicious[$pluginName][]=['file'=>$relPath,'line_number'=>$num+1,'content'=>trim($line)];
                } elseif($relPath==='wp-config.php'){
                    $configSuspicious[]=['line_number'=>$num+1,'content'=>trim($line)];
                } elseif(!in_array($relPath,$safeFiles) && !in_array($relPath,$suspicious)) {
                    $suspicious[]=$relPath;
                }
            }
        }
    }
}
log_msg("Malware scan completed. Suspicious root files: ".count($suspicious)." , Plugins: ".count($pluginSuspicious)." , wp-config: ".count($configSuspicious));

// ---------------- STEP 7: WP-CLI ----------------
$wpCli = !empty(shell_exec('which wp 2>/dev/null'));
$wpVersion='Unknown'; 
$pluginList=[];
if($wpCli){
    $wpVersion = trim(shell_exec('wp core version 2>/dev/null'));
    $out = shell_exec('wp plugin list --format=json 2>/dev/null');
    if($out) $pluginList = json_decode($out,true);
    if(!$dryRun){
        shell_exec('wp core verify-checksums --quiet');
        shell_exec('wp core download --force --skip-content'); // keep wp-content safe
    }
}
log_msg($wpCli ? "WP-CLI detected" : "WP-CLI not available");

// ---------------- STEP 8: JSON REPORT ----------------
$report=[
    'timestamp'=>date('c'),
    'dry_run'=>$dryRun,
    'wordpress_version'=>$wpVersion,
    'wp_cli'=>$wpCli,
    'root_deleted_count'=>count($rootDeleted),
    'root_deleted_items'=>$rootDeleted,
    'suspicious_files_count'=>count($suspicious),
    'suspicious_files'=>$suspicious,
    'plugin_suspicious'=>$pluginSuspicious,
    'wp_config_suspicious'=>$configSuspicious,
    'installed_plugins'=>$pluginList
];
if(!$dryRun) file_put_contents($reportFile,json_encode($report,JSON_PRETTY_PRINT));
log_msg("Security JSON report generated");

// ---------------- STEP 9: EMAIL ALERT ----------------
$msg = "WP Security Cleanup Report\n\n";
$msg .= "Mode: ".($dryRun ? "DRY-RUN (No changes applied)" : "LIVE RUN")."\n\n";
$msg .= "WordPress Version: $wpVersion\n\n";

$msg .= "Root Deleted Files (".count($rootDeleted)."):\n"; 
foreach($rootDeleted as $f) $msg.=" - $f\n";

$msg .= "\nSuspicious Root PHP Files (".count($suspicious)."):\n"; 
foreach($suspicious as $f) $msg.=" - $f\n";

$msg .= "\nPLUGIN SUSPICIOUS DETAILS:\n";
foreach($pluginSuspicious as $pluginName=>$entries){
    $msg.="\nPlugin: $pluginName\n";
    foreach($entries as $e) $msg.=" - {$e['file']} [Line {$e['line_number']}]: {$e['content']}\n";
}

$msg .= "\nWP-CONFIG.PHP SUSPICIOUS LINES:\n";
foreach($configSuspicious as $c) $msg.=" - Line {$c['line_number']}: {$c['content']}\n";

mail(
    $alertEmail,
    'WP Security Cleanup Report - '.($dryRun ? 'DRY-RUN' : 'LIVE'),
    $msg
);
log_msg("Security report email sent to {$alertEmail}");

// ---------------- END ----------------
echo "Cleanup completed\n";
if($dryRun) echo "DRY-RUN mode. Use --run to apply changes.\n";