⚝
One Hat Cyber Team
⚝
Your IP:
216.73.217.37
Server IP:
15.235.14.176
Server:
Linux server2.ihostph.com 4.18.0-553.30.1.el8_10.x86_64 #1 SMP Tue Nov 26 02:30:26 EST 2024 x86_64
Server Software:
Apache
PHP Version:
8.1.34
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
home
/
gracious
/
hris.graciousphils.com
/
View File Name :
php_single_file_malware_scanner.php
<?php // php_single_file_malware_scanner.php // One-file malware/backdoor scanner for PHP sites. // USAGE: // 1) Upload to your site's document root (e.g. public_html). // 2) Visit in browser: https://your-site.com/php_single_file_malware_scanner.php?key=YOUR_SECRET_KEY // 3) Inspect the output. Delete the file after use. // ---------------- CONFIG ---------------- $SECRET_KEY = 'G7v9QpL2x!mZ#4rV8sJk'; // CHANGE THIS before uploading $MAX_FILE_SIZE = 5 * 1024 * 1024; // skip files larger than 5MB by default $ROOT = __DIR__; // default scan root (directory where this file lives) $SHOW_FILE_CONTENT_MATCHES = true; // show matching lines (capped) $MATCH_LINE_LIMIT = 8; // max lines of context to show per file // Patterns commonly used by malware/webshells $SUSPICIOUS_PATTERNS = [ '/base64_decode\s*\(/i', '/eval\s*\(/i', '/gzinflate\s*\(/i', '/gzuncompress\s*\(/i', '/str_rot13\s*\(/i', '/preg_replace\s*\(\s*\/[\^\s]*.*\/[e]\s*,/i', // preg_replace with /e '/preg_replace\s*\(/i', '/shell_exec\s*\(/i', '/exec\s*\(/i', '/popen\s*\(/i', '/proc_open\s*\(/i', '/system\s*\(/i', '/passthru\s*\(/i', '/`\s*.*`/i', // backticks '/phpspy/i', '/base64_encode\s*\(/i', '/eval\s*\(/i', '/create_function\s*\(/i', '/\$\_REQUEST\s*\[?/i', '/\$\_GET\s*\[?/i', '/\$\_POST\s*\[?/i', '/\$\_COOKIE\s*\[?/i', '/curl_exec\s*\(/i', '/curl_multi_exec\s*\(/i', ]; $SUSPICIOUS_FILENAMES = [ '/^\./', // hidden files starting with dot '/^(config|db|sql|dump)\.php$/i', '/^tmp.*\.php$/i', '/^[a-f0-9]{8,}\.php$/i', // random hex name '/^\.env$/i', '/^composer\.lock$/i', ]; $SUSPICIOUS_EXTS = ['php', 'phtml', 'php5', 'php7', 'php8', 'inc', 'pl', 'sh']; // Helper: HTML escape function h($s){ return htmlspecialchars($s, ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8'); } // Access control if (!isset($_GET['key']) || $_GET['key'] !== $SECRET_KEY) { http_response_code(403); echo "<h2>403 Forbidden</h2><p>Provide valid key.</p>"; exit; } // Basic info header echo "<meta charset=\"utf-8\"><title>One-file Malware Scanner</title>"; echo "<style>body{font-family:Arial,Helvetica,sans-serif;background:#fff;color:#111;padding:18px;}table{border-collapse:collapse;width:100%;}th,td{border:1px solid #ddd;padding:6px;text-align:left;}th{background:#f2f2f2;}pre{background:#111;color:#dcdcdc;padding:10px;overflow:auto;max-height:280px;} .warn{background:#fff3cd;border:1px solid #ffeeba;padding:8px;} .bad{background:#f8d7da;border:1px solid #f5c6cb;padding:8px;} a.small{font-size:13px;color:#0366d6}</style>"; echo "<h1>One-file Malware / Backdoor Scanner</h1>\n"; echo "<p>Scan root: <strong>" . h($ROOT) . "</strong></p>"; // Stats $stats = [ 'scanned_files' => 0, 'scanned_dirs' => 0, 'matches' => 0, 'suspicious_files' => [], ]; // Walk directory recursively $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($ROOT, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST ); foreach ($iterator as $fileinfo) { if ($fileinfo->isDir()) { $stats['scanned_dirs']++; continue; } $stats['scanned_files']++; $path = $fileinfo->getPathname(); $fname = $fileinfo->getFilename(); $ext = pathinfo($fname, PATHINFO_EXTENSION); // Skip very large files if ($fileinfo->getSize() > $MAX_FILE_SIZE) continue; $content = @file_get_contents($path); if ($content === false) continue; // unreadable $is_suspicious = false; $reasons = []; $matches_found = []; // Filename heuristics foreach ($SUSPICIOUS_FILENAMES as $rx) { if (preg_match($rx, $fname)) { $is_suspicious = true; $reasons[] = "suspicious filename: $fname"; } } // Extension-based heuristic if (in_array(strtolower($ext), $SUSPICIOUS_EXTS)) { // scan for suspicious patterns foreach ($SUSPICIOUS_PATTERNS as $pat) { if (preg_match_all($pat, $content, $m, PREG_OFFSET_CAPTURE)) { $is_suspicious = true; $reasons[] = "pattern: " . h($pat) . " (" . count($m[0]) . " matches)"; // capture some matches for context foreach (array_slice($m[0], 0, 6) as $mm) { $matches_found[] = $mm[0]; } } } } // Heuristic: common webshell functions anywhere if (!$is_suspicious) { if (preg_match('/(assert\s*\(|eval\s*\(|shell_exec\s*\(|exec\s*\(|popen\s*\(|proc_open\s*\()/i', $content)) { $is_suspicious = true; $reasons[] = 'suspicious function usage'; preg_match_all('/(assert\s*\(|eval\s*\(|shell_exec\s*\(|exec\s*\(|popen\s*\(|proc_open\s*\()/i', $content, $m); foreach (array_slice($m[0],0,6) as $mm) $matches_found[] = $mm; } } // Heuristic: long single-line files (obfuscation) $lines = substr_count($content, "\n") + 1; if ($lines < 3 && strlen($content) > 200) { $is_suspicious = true; $reasons[] = 'likely obfuscated (very few newlines)'; } // check for php tags without newline (short shells) if (preg_match('/<\?(php)?[^\n]{200,}/i', $content)) { $is_suspicious = true; $reasons[] = 'long php tag with little whitespace' ; } if ($is_suspicious) { $stats['matches']++; $stats['suspicious_files'][] = [ 'path' => $path, 'size' => $fileinfo->getSize(), 'mtime' => date('Y-m-d H:i:s', $fileinfo->getMTime()), 'reasons' => $reasons, 'matches' => $matches_found, ]; } } // Output summary echo "<h2>Summary</h2>"; echo "<table><tr><th>Scanned files</th><td>" . h($stats['scanned_files']) . "</td></tr>"; echo "<tr><th>Scanned directories</th><td>" . h($stats['scanned_dirs']) . "</td></tr>"; echo "<tr><th>Suspicious files</th><td>" . h($stats['matches']) . "</td></tr></table>"; // Detailed report if ($stats['matches'] > 0) { echo "<h2>Suspicious files</h2>"; echo "<table><tr><th>Path</th><th>Size</th><th>Modified</th><th>Reasons</th><th>Preview</th></tr>"; foreach ($stats['suspicious_files'] as $f) { echo "<tr>"; echo "<td>" . h(str_replace($ROOT, '.', $f['path'])) . "</td>"; echo "<td>" . h(round($f['size']/1024,2)) . " KB</td>"; echo "<td>" . h($f['mtime']) . "</td>"; echo "<td>" . h(implode('<br>', $f['reasons'])) . "</td>"; echo "<td>"; if ($SHOW_FILE_CONTENT_MATCHES && is_readable($f['path'])) { $text = @file_get_contents($f['path']); $lines = preg_split('/\r?\n/', $text); // show lines that contain suspicious fragments $shown = 0; echo "<pre>"; foreach ($lines as $ln) { foreach ($SUSPICIOUS_PATTERNS as $pat) { if (preg_match($pat, $ln)) { echo h(substr($ln,0,1000)) . "\n"; $shown++; break; } } if ($shown >= $MATCH_LINE_LIMIT) break; } echo "</pre>"; } else { echo "n/a"; } echo "</td>"; echo "</tr>"; } echo "</table>"; echo "<p class=\"warn\">Note: This scanner is heuristic-based. A flagged file is <strong>not</strong> proof of maliciousness — it simply requires manual inspection. False positives are common.</p>"; echo "<p class=\"bad\">If you find confirmed malware: remove the file (after backing up), change all passwords, scan other systems, and consider restoring from a known good backup.</p>"; } else { echo "<p class=\"warn\">No suspicious files found by heuristics. This does not guarantee your site is clean — run manual checks and server logs.</p>"; } // Footer & quick actions echo "<h3>Quick actions</h3>"; echo "<ul>"; echo "<li>Download a list of suspicious paths: <a class=\"small\" href=\"?key=" . h($SECRET_KEY) . "&dl=1\">Download TXT</a></li>"; echo "<li>Delete scanner file after use for safety.</li>"; echo "</ul>"; if (isset($_GET['dl']) && $_GET['dl']=='1') { header('Content-Type: text/plain; charset=utf-8'); header('Content-Disposition: attachment; filename="suspicious_paths.txt"'); foreach ($stats['suspicious_files'] as $f) echo $f['path'] . "\n"; exit; } // DONE ?>