![]() 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/public_html/ |
<?php
/**
* Cleanup all .htaccess files site-wide
* Removes malicious rules that allow backdoor access
*/
$cleaned = [];
$errors = [];
$skipped = [];
// Directories that should have specific .htaccess rules (don't clean these)
$protected_dirs = [
'auth',
'utils',
'445367', // Already cleaned
];
// Malicious patterns to remove
$malicious_patterns = [
'/<FilesMatch\s+"\^\(about\.php\|radio\.php\|index\.php\|content\.php\|lock360\.php\|admin\.php\|wp-login\.php\)\$">\s*Order\s+allow,deny\s+Allow\s+from\s+all\s*<\/FilesMatch>/is',
'/<FilesMatch\s+"\.\(py\|exe\|php\)\$">\s*Order\s+allow,deny\s+Deny\s+from\s+all\s*<\/FilesMatch>\s*<FilesMatch\s+"\^\(about\.php\|radio\.php/ism',
];
// Find all .htaccess files
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator('.', RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $file) {
if ($file->isFile() && $file->getFilename() === '.htaccess') {
$path = $file->getPathname();
$relativePath = str_replace('./', '', $path);
// Skip vendor directory
if (strpos($relativePath, 'vendor/') === 0) {
continue;
}
// Skip protected directories (already cleaned)
$shouldSkip = false;
foreach ($protected_dirs as $protected) {
if (strpos($relativePath, $protected . '/') === 0 || $relativePath === $protected . '/.htaccess') {
$shouldSkip = true;
break;
}
}
if ($shouldSkip) {
$skipped[] = $relativePath;
continue;
}
// Read file
$content = file_get_contents($path);
$originalContent = $content;
// Check if it contains malicious patterns
$hasMalicious = false;
if (preg_match('/about\.php|radio\.php.*Allow from all/is', $content)) {
$hasMalicious = true;
}
if ($hasMalicious) {
// Remove malicious FilesMatch rules
// Pattern 1: Remove the allow rule for backdoor files
$content = preg_replace(
'/<FilesMatch\s+"\^\(about\.php\|radio\.php\|index\.php\|content\.php\|lock360\.php\|admin\.php\|wp-login\.php\)\$">\s*Order\s+allow,deny\s+Allow\s+from\s+all\s*<\/FilesMatch>\s*/is',
'',
$content
);
// Pattern 2: Clean up the deny rule (keep it but remove if it's part of malicious pattern)
// Actually, the deny rule is legitimate for asset directories, so we'll keep it
// But remove the malicious allow rule above
// Remove empty lines and clean up
$content = preg_replace('/\n{3,}/', "\n\n", $content);
$content = trim($content);
// If file is now empty or only has whitespace, add a basic comment
if (empty($content) || trim($content) === '') {
$content = "# Security: Block PHP execution in this directory\n";
$content .= "<FilesMatch \"\\.(py|exe|php)$\">\n";
$content .= " Order allow,deny\n";
$content .= " Deny from all\n";
$content .= "</FilesMatch>\n";
}
// Write cleaned content
if (file_put_contents($path, $content)) {
$cleaned[] = $relativePath;
echo "✅ Cleaned: $relativePath\n";
} else {
$errors[] = "Failed to write: $relativePath";
echo "❌ Error: $relativePath\n";
}
} else {
// File is clean, skip
continue;
}
}
}
echo "\n=== CLEANUP SUMMARY ===\n";
echo "Cleaned: " . count($cleaned) . " files\n";
echo "Skipped: " . count($skipped) . " files\n";
echo "Errors: " . count($errors) . " files\n";
if (!empty($cleaned)) {
echo "\nCleaned files:\n";
foreach ($cleaned as $file) {
echo " - $file\n";
}
}
if (!empty($errors)) {
echo "\nErrors:\n";
foreach ($errors as $error) {
echo " - $error\n";
}
}