JezK
Edit File: wordpress_cleanup_cron.php
<?php /** * WordPress Full Security & Cleanup Script * - Root cleanup (keeps WP core + robots.txt) * - Dangerous plugin removal * - Permissions hardening * - Malware scan * - WP-CLI verification * - Auto robots.txt create/override (dynamic sitemap) */ $root = __DIR__; $dryRun = true; // default DRY-RUN (use --run to execute live) $logFile = $root . '/cleanup.log'; $reportFile = $root . '/security-report.json'; $scriptFile = basename(__FILE__); $cronScript = 'wordpress_cleanup_cron.php'; $alertEmail = 'corn@ignitemv.com'; $dangerPlugins = ['wp-file-manager','file-manager-advanced']; $rootDeleted = []; $patterns = ['eval(','base64_decode','gzinflate','shell_exec','passthru','str_rot13']; $safeFiles = [$cronScript]; // 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', 'robots.txt', // KEEP ROBOTS $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"); // ---------------- 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> # ================================================== # MIME TYPE FIX (SVG SUPPORT) # ================================================== AddType image/svg+xml .svg AddType image/svg+xml .svgz # ================================================== # BASIC SECURITY # ================================================== # Disable directory browsing Options -Indexes # Protect wp-config.php <Files wp-config.php> Require all denied </Files> # Protect .htaccess <Files .htaccess> Require all denied </Files> # Block readme & license files <FilesMatch "^(readme\.html|license\.txt|wp-config-sample\.php|debug\.log|error_log)$"> Require all denied </FilesMatch> # ================================================== # BLOCK PHP EXECUTION IN UPLOADS ONLY (SAFE WAY) # ================================================== <IfModule mod_rewrite.c> RewriteRule ^wp-content/uploads/.*\.(php[0-9]?|phtml)$ - [F,L] </IfModule> # ================================================== # PROTECT WP-INCLUDES # ================================================== <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 XMLRPC (if not using Jetpack) # ================================================== <Files xmlrpc.php> Require all denied </Files> # ================================================== # 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> # ================================================== # REMOVE SERVER SIGNATURE # ================================================== ServerSignature Off # Remove X-Powered-By <IfModule mod_headers.c> Header always unset X-Powered-By Header set Referrer-Policy "strict-origin-when-cross-origin" Header set X-Content-Type-Options "nosniff" Header set X-Frame-Options "SAMEORIGIN" Header set Permissions-Policy "geolocation=(), microphone=(), camera=()" </IfModule> HTACCESS; if(!$dryRun) file_put_contents($root.'/.htaccess', $htaccessContent); log_msg(".htaccess updated"); // ---------------- 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"); // ---------------- 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("Permissions hardened"); // ---------------- STEP 6: MALWARE SCAN ---------------- $suspicious=[]; $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 $line){ foreach($patterns as $p){ if(stripos($line,$p)!==false){ $rel=str_replace($root.'/','',$file); if(!in_array($rel,$safeFiles)) $suspicious[]=$rel; } } } } log_msg("Malware scan complete"); // ---------------- STEP 7: WP-CLI VERIFY ---------------- $wpCli = !empty(shell_exec('which wp 2>/dev/null')); if($wpCli && !$dryRun){ shell_exec('wp core verify-checksums --quiet'); shell_exec('wp core download --force --skip-content'); } log_msg($wpCli ? "WP-CLI detected" : "WP-CLI not found"); // ---------------- STEP 8: ROBOTS.TXT AUTO CREATE / OVERRIDE ---------------- $robotsFile = $root . '/robots.txt'; $domain = $_SERVER['HTTP_HOST'] ?? 'localhost'; $isHttps = ( (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || ($_SERVER['SERVER_PORT'] ?? 80) == 443 ); $protocol = $isHttps ? 'https://' : 'http://'; $sitemapUrl = $protocol . $domain . '/wp-sitemap.xml'; $robotsContent = <<<ROBOTS User-agent: * Disallow: /wp-admin/ Disallow: /wp-includes/ Disallow: /readme.html Disallow: /wp-login.php Allow: /wp-admin/admin-ajax.php Sitemap: {$sitemapUrl} ROBOTS; if($dryRun){ log_msg("DRY-RUN: robots.txt would be created/overwritten"); } else { file_put_contents($robotsFile,$robotsContent); chmod($robotsFile,0644); log_msg("robots.txt created/updated successfully"); } // ---------------- END ---------------- echo "Cleanup completed\n"; if($dryRun) echo "DRY-RUN mode. Use --run to apply changes.\n";