Skip to content

maitret/WordPress_MalwareScanner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WordPress Malware Scanner & Remediation Toolkit

🌐 Language / Idioma: English (current) | Español

Complete toolkit for detecting, analyzing, and remediating PHP malware on Linux web hosting servers (CWP/cPanel/aaPanel) with WordPress. Includes forensic auditing, post-compromise hardening, and executive HTML report generation.

Toolkit Components

Detection & Remediation

Script Description Action
malware_scanner.py Main heuristic engine — 6 signature layers, scoring, entropy Scan, quarantine, clean, disable
remediate.sh Pipeline orchestrator — chains 7 remediation phases Runs full cycle automatically
wp_backup_db.sh WordPress database backup Dump + gzip per wp-config.php
wp_db_scan.sh Database scanning — injections, spam, malicious admins Detects and cleans transients
cron_check.sh Malicious crontab detection (16 patterns) Detects and disables
wp_reemplaza.sh WP core restoration via rsync from clean copy Backup + rsync + permissions
fix_permissions.sh Hosting permission correction (auto-detects group) 755/644/600/711
malware_scan.sh Quick triage with grep/find (report only) Read-only
wp_security_scan.sh Basic quarantine by grep signatures Moves files
wp_reinfection_audit.sh Reinfection vector audit — 52 checks in 10 categories Read-only, generates TXT + JSON

Forensic Auditing & Hardening (CWP)

Script Description Action
cwp_forensic_audit.sh CWP server forensic audit — 27 analysis sections Read-only, generates TXT + JSON report
cwp_harden.sh Post-compromise hardening for CWP — 7 correction phases Applies fixes with --dry-run available

Forensic Auditing & Remediation (aaPanel)

Script Description Action
aapanel_forensic_audit.sh aaPanel server forensic audit — 28 analysis sections Read-only, generates TXT + JSON report
aapanel_remediate.sh Remediation pipeline for aaPanel — 6 phases Full cycle with --clean/--disable

Reports

Script Description Action
generate_html_report.py Executive HTML report generator from scanner JSON Generates HTML with charts and recommendations
malware_watcher.py Real-time resident antivirus daemon — monitors /home with inotify Alerts on each PHP change, no polling
install_watcher.sh Installer/uninstaller for the malware_watcher daemon Install, uninstall, update, status

Quick Start

1) Minimal Setup

mkdir -p /home_D0/fixes/logs /home_D0/fixes/quarantine /home_D0/fixes/backups

2) Full Diagnostic (no changes)

./remediate.sh /home

3) Full Remediation

./remediate.sh --clean /home

Tool Reference

malware_scanner.py — Main Heuristic Engine

Heuristic detection engine with 6 signature layers, entropy analysis, intelligent scoring, and false positive deduction.

Options:

Option Description
--scan DIR Directory to scan (default: /home)
--clean Clean simple injections with regex
--disable Disable malware: chmod 000 + rename .DISABLED
--no-quarantine Report only, don't move or touch files
--report FMT Format: text, json, both (default: both)
--threshold N Minimum score to report (default: 60)
--validate-wp Validate WordPress core integrity
--verify Re-scan after cleanup
--workers N Parallel workers (default: 0 = sequential)
--download-wp [VER] Download clean WP from wordpress.org

Action Modes:

Mode Command What it does
Report only --no-quarantine Scans and generates reports without touching files
Quarantine (default) Moves malware to /home_D0/fixes/quarantine/
Cleanup --clean Removes injections with regex, quarantines if fails
Disabled --disable chmod 000 + .DISABLED, log per user

Scoring System:

Threshold Verdict Meaning
< 60 CLEAN No action
≥ 60 SUSPICIOUS Investigate context
≥ 80 LIKELY_MALWARE Auto-cleanable
≥ 90 MALWARE High confidence, act

Examples:

# Report only, don't touch files
python3 malware_scanner.py --scan /home --no-quarantine

# Scan a specific site
python3 malware_scanner.py --scan /home/user/public_html --no-quarantine

# Clean injections and verify result
python3 malware_scanner.py --scan /home --clean --verify

# Disable malware in-place
python3 malware_scanner.py --scan /home --disable

# Validate WordPress core integrity
python3 malware_scanner.py --scan /home --validate-wp --report both

# Lower threshold (more sensitive, more findings)
python3 malware_scanner.py --scan /home --threshold 40

# Parallel scanning with 4 workers
python3 malware_scanner.py --scan /home --workers 4

# Download clean WP and validate core
python3 malware_scanner.py --scan /home --download-wp --validate-wp

# Download specific WP version
python3 malware_scanner.py --scan /home --download-wp 6.4.2 --validate-wp

# Aggressive scan: low threshold, parallel, cleanup + verification
python3 malware_scanner.py --scan /home --threshold 40 --workers 8 --clean --verify

Reports generated in /home_D0/fixes/logs/:

File Content
scan_*.log Human-readable log with matches, hashes, scores
scan_*.json Structured JSON with findings, stats, verdicts
scan_*_files.txt Quick triage: MALWARE/LIKELY/SUSPICIOUS by score
scan_*.rm_ALL.txt Bash script with all rm commands
scan_*.rm_<SIG>.txt One script per detection type

remediate.sh — Pipeline Orchestrator

Chains the 7 remediation phases in a single command.

Options:

Option Description
--clean Activate regex cleanup
--disable Activate disable mode (chmod 000 + .DISABLED)
--dry-run Report only, don't execute actions
--skip-restore Skip WP core restoration
--threshold N Minimum score (default: 60)
--workers N Parallel workers (default: 0)

Pipeline Phases:

Phase Description When executed
1 Database backup Always
2 Heuristic scan (report only) Always
2b Database scan Always
2c Crontab verification Always
3 Findings classification Always
4 Malware cleanup + DB transients Only with --clean/--disable
5 WordPress core restoration Only with --clean/--disable
6 Verification re-scan Only with --clean/--disable
7 Permission correction Only with --clean/--disable

Examples:

# Full diagnostic (no changes)
./remediate.sh /home

# A specific site
./remediate.sh /home/user/public_html

# Full pipeline with cleanup
./remediate.sh --clean /home

# In-place disable (safer than --clean)
./remediate.sh --disable /home

# Dry-run: see what it would do without executing
./remediate.sh --dry-run /home

# Cleanup without restoring WP core
./remediate.sh --clean --skip-restore /home

# Parallel with low threshold
./remediate.sh --workers 4 --threshold 40 /home

wp_backup_db.sh — Database Backup

Finds all wp-config.php files, extracts DB credentials, and runs mysqldump + gzip.

Options:

Option Description
[directory] Path to search (default: /home)

Examples:

# Backup all databases in /home
./wp_backup_db.sh

# Single site only
./wp_backup_db.sh /home/user/public_html

# Backup + scan
./wp_backup_db.sh /home && python3 malware_scanner.py --scan /home --no-quarantine

Backups in: /home_D0/fixes/backups/db_<slug>_<timestamp>.sql.gz


wp_db_scan.sh — Database Scanning

Detects malware injections in WordPress databases.

Options:

Option Description
--fix Delete malicious transients from DB
[directory] Path to search (default: /home)

What it detects:

  1. wp_options — siteurl/home modified to external domains
  2. wp_options — options with eval(), base64_decode(), <script>, <iframe>
  3. wp_options — transients with malicious content
  4. wp_posts — posts with SEO spam, hidden iframes, injected scripts
  5. wp_users — admins created in the last 30 days with disposable emails

Examples:

# Scan all databases (report only)
./wp_db_scan.sh

# Scan a single site
./wp_db_scan.sh /home/user/public_html

# Scan and clean malicious transients
./wp_db_scan.sh --fix /home

# Backup first, then scan DB
./wp_backup_db.sh /home && ./wp_db_scan.sh /home

cron_check.sh — Malicious Crontab Detection

Detects crontabs that reinstall malware (reinfection cause #1).

Options:

Option Description
--fix Comment out malicious lines (prefix # DISABLED_BY_CRON_CHECK:)
[directory] Base path to find users (default: /home)

Locations checked:

  • crontab -l -u <user> — user crontab
  • /var/spool/cron/<user> — CentOS/RHEL
  • /var/spool/cron/crontabs/<user> — Debian/Ubuntu
  • /etc/cron.d/* — system crontabs
  • /etc/cron.hourly/, daily/, weekly/, monthly/
  • /etc/crontab

Suspicious patterns (16): wget/curl with flags, python/php/perl inline, execution from /tmp/ or /dev/shm/, base64 decode, pipe to bash/sh, chmod 777, echo to .php.

Examples:

# Check all users (report only)
./cron_check.sh

# Check a single user
./cron_check.sh /home/user

# Detect and disable malicious crontabs
./cron_check.sh --fix

# Clean crontabs BEFORE cleaning files (important)
./cron_check.sh --fix && python3 malware_scanner.py --scan /home --clean

wp_reemplaza.sh — WP Core Restoration

Restores wp-admin/, wp-includes/, and root .php files using rsync from a clean copy.

Requirement: Clean WordPress copy in /home_D0/fixes/wordpress/

# Prepare clean copy
wget https://wordpress.org/latest.tar.gz
tar xzf latest.tar.gz -C /home_D0/fixes/

# Or with malware_scanner.py
python3 malware_scanner.py --download-wp --scan /dev/null --no-quarantine

What it does per site:

  1. Finds wp-config.php in /home recursively
  2. Validates WP structure, detects Multisite, compares versions
  3. DB backup (mysqldump + gzip)
  4. Backup of current core (tar.gz)
  5. rsync -a --checksum --delete (excludes wp-content and wp-config.php)
  6. Fixes permissions and ownership

What it does NOT touch: wp-content/, wp-config.php, the database.

Examples:

# Repair all WP installations in /home
./wp_reemplaza.sh

# Backup DB first (recommended)
./wp_backup_db.sh /home && ./wp_reemplaza.sh

# Restore core + fix permissions
./wp_reemplaza.sh && ./fix_permissions.sh --all

fix_permissions.sh — Permission Correction

Fixes permissions and ownership for hosting accounts. Compatible with CWP and cPanel.

Options:

Option Description
-a, --all Process all accounts in /home
-u, --user USER Process only this user (repeatable)
-n, --dry-run Show without executing changes
-v, --verbose Detailed output

Permissions applied:

Resource Permissions
Directories 755
Files 644
wp-config.php 600
.htaccess 644
/home/user (base) 711
public_html 755
Owner user:<group> recursive (auto-detected)

Group auto-detection: The script automatically detects the correct group for each user:

  • If a group with the same name as the user exists (CWP with PHP-FPM: user:user), it uses it
  • If not, falls back to nobody (CWP with suPHP / cPanel)
  • This is needed because PHP-FPM on CWP runs with group = <username>, and using nobody would break PHP execution

Non-blocking chown: If chown -R encounters immutable files (e.g., .user.ini with chattr +i), it logs a warning and continues applying all remaining permission steps (chmod 755/644/600/711) instead of aborting. This ensures permissions are corrected even when individual files can't change ownership.

Examples:

# Fix all users
./fix_permissions.sh --all

# Single user only
./fix_permissions.sh -u john

# Simulate without changes
./fix_permissions.sh --dry-run --all

# Multiple users
./fix_permissions.sh -u john -u peter

# Verbose
./fix_permissions.sh --verbose -u john

malware_scan.sh — Quick Triage

Lightweight reconnaissance script with grep/find. Does not modify files.

What it checks (5 checks):

  1. Suspicious signatures — base64_decode, eval(), gzinflate, str_rot13, shell_exec
  2. PHP in uploads — .php files inside */uploads/
  3. Recent files — modified in last 2 days
  4. Suspicious names — wp-log, shell, cmd, adminer, etc.
  5. 777 permissions

Examples:

# Quick triage of all /home
./malware_scan.sh

# A specific directory
./malware_scan.sh /home/user/public_html

# Triage first, deep analysis after
./malware_scan.sh /home
python3 malware_scanner.py --scan /home --no-quarantine

wp_security_scan.sh — Basic Quarantine

Moves suspicious PHP files to quarantine and compares WP core with diff.

Warning: This script MOVES files. For report-only, use malware_scan.sh or malware_scanner.py --no-quarantine.

What it does:

  1. Detects by grep signature → moves to quarantine (except wp-includes/wp-admin)
  2. PHP in uploads → moves
  3. Suspicious names → moves
  4. Validates WP core with diff -qr
  5. Lists recent .php files (does not move)

Examples:

# Quarantine suspicious files in /home
./wp_security_scan.sh

# Backup before quarantining (RECOMMENDED)
./wp_backup_db.sh /home && ./wp_security_scan.sh /home

Quarantined files in: /home_D0/fixes/quarantine/


wp_reinfection_audit.sh — Reinfection Vector Audit

READ-ONLY audit of WordPress reinfection vectors. Detects the entry points and persistence mechanisms that allow malware to return after cleanup.

10 detection categories (52 vectors):

  1. File persistence — mu-plugins, drop-ins, auto_prepend, index.php @include, double extensions
  2. Database persistence — WP-Cron hooks, ghost plugins (BD vs disk), injected options
  3. Server persistence — LD_PRELOAD, .bashrc, at jobs, systemd services/timers
  4. Config poisoning — .htaccess AddHandler abuse, local php.ini, Nginx auto_prepend, .user.ini
  5. Upload bypass — uploads/ without PHP execution protection
  6. Plugins & themes — WP versions, outdated plugins, inactive themes, WP-CRON
  7. Credentials — wp-config permissions, shared DB credentials, exposed files (.env, .sql, phpinfo)
  8. PHP hardening — allow_url_include, disable_functions, display_errors, session cookies
  9. Network — exposed ports (MySQL/Redis/Memcached), xmlrpc.php, DNS mismatch
  10. Recent files — PHP files modified in last 7 days

Output: logs/reinfection_audit_*.txt + logs/reinfection_audit_*.json

Examples:

# Audit all users
./wp_reinfection_audit.sh

# Audit single user
./wp_reinfection_audit.sh /home/user/public_html

# Recommended: scan + audit together
python3 malware_scanner.py --scan /home --no-quarantine && ./wp_reinfection_audit.sh

Complementary to malware_scanner.py: The scanner finds malware already present; this audit finds HOW the malware gets in.


cwp_forensic_audit.sh — CWP Server Forensic Audit

READ-ONLY forensic investigation of compromised CWP servers. Analyzes 27 attack vectors to identify the root cause of mass infections (all users infected simultaneously).

Usage: ./cwp_forensic_audit.sh [/home]

Requires: root, bash 4+

27 analysis sections:

# Section What it investigates
1 /home permissions Account isolation, 777/775 permissions
2 PHP-FPM pools Shared vs isolated pool, open_basedir, disable_functions
3 Apache security FollowSymLinks, mod_ruid2, open_basedir, suexec
4 CWP version/config CWP version, exposed ports, panel accessible
5 /tmp and PHP sessions PHP in /tmp, shared sessions, /dev/shm
6 Cron jobs Crontabs with wget/curl/base64, propagation vectors
7 .htaccess auto_prepend_file, injections, malicious redirects
8 WordPress status Outdated versions, vulnerable plugins, xmlrpc, uploads
9 SSH authentication PermitRootLogin, passwords, failed attempts
10 Firewall/ports firewalld status, unnecessary open ports
11 Temporal analysis Patient zero, infection timeline
12 SUID/SGID binaries Binaries with anomalous elevated permissions
13 Suspicious processes Cryptominers, reverse shells, hidden processes
14 Network connections C&C connections, IRC/crypto ports
15 Hidden files .ico/.jpg with PHP, hidden files in /home
16 wp-config.php Integrity: eval/base64/require /tmp injected
17 FTP/ProFTPD Insecure configuration, anonymous access
18 Apache logs Brute force, exploit paths, suspicious POSTs
19 MySQL/MariaDB Anonymous users, remote root access, test DB
20 Apache modules mod_cgi, mod_suphp, dangerous modules
21 SELinux Status (enforcing/permissive/disabled)
22 Kernel/updates Pending security updates
23 Cross-account symlinks Symlinks reading other users' files
24 authorized_keys SSH keys injected by attackers
25 File capabilities Binaries with elevated capabilities (getcap)
26 Monitoring auditd, fail2ban, integrity status
27 Executive summary CRITICAL/WARNING/INFO count + verdict

Reports generated:

File Content
forensic_audit_*.txt Human-readable report with categorized findings
forensic_audit_*.json Structured JSON with severity, category, message

Examples:

# Full audit (READ-ONLY, modifies nothing)
./cwp_forensic_audit.sh

# Specify alternate base directory
./cwp_forensic_audit.sh /home

# Review the report
cat /home_D0/fixes/logs/forensic_audit_*.txt

# Review critical findings in JSON
python3 -c "
import json
data = json.load(open('/home_D0/fixes/logs/forensic_audit_*.json'))
for f in data['findings']:
    if f['severity'] == 'CRITICAL':
        print(f['category'], '-', f['message'])
"

cwp_harden.sh — Post-Compromise Hardening for CWP

Applies the corrections identified by cwp_forensic_audit.sh. Each phase is independent and supports --dry-run to preview changes.

Usage: ./cwp_harden.sh [options]

Requires: root, bash 4+

Options:

Option Description
--dry-run Show what would be done without applying changes
--fix-perms Fix permissions: /home→711, public_html→755, wp-config→600
--fix-fpm Generate per-user PHP-FPM pools with open_basedir and disable_functions
--fix-apache SymLinksIfOwnerMatch, security headers, ServerTokens Prod
--fix-ssh PermitRootLogin without-password, MaxAuthTries 3, auto-rollback with sshd -t
--fix-mysql Remove anonymous users, revoke remote root access, DROP test DB
--fix-tmp Clean PHP from /tmp and /dev/shm, remount with noexec/nosuid/nodev
--fix-firewall Configure firewalld: only HTTP/HTTPS/SSH(custom)/CWP
--all Apply all corrections
-h, --help Show help

7 hardening phases:

Phase Flag What it fixes
1 --fix-perms /home→711, home/user→711, public_html→755, wp-config.php→600, ownership
2 --fix-fpm Generates per-user PHP-FPM pool with open_basedir, disable_functions, isolated session
3 --fix-apache FollowSymLinks→SymLinksIfOwnerMatch, security headers, ServerTokens, vhosts
4 --fix-ssh PermitRootLogin, MaxAuthTries 3, LoginGraceTime 30, Protocol 2, sshd -t validation
5 --fix-mysql Anonymous users, remote root, test DB, bind-address→127.0.0.1, backup my.cnf
6 --fix-tmp Clean .php from /tmp and /dev/shm, remount noexec/nosuid/nodev, add to fstab
7 --fix-firewall Enable firewalld, allow HTTP/HTTPS/SSH(custom port)/CWP, remove extra services

Examples:

# ALWAYS start with dry-run
./cwp_harden.sh --dry-run --all

# Fix permissions only
./cwp_harden.sh --fix-perms

# SSH + MySQL hardening
./cwp_harden.sh --fix-ssh --fix-mysql

# PHP-FPM isolation (most important fix for cross-account infection)
./cwp_harden.sh --fix-fpm

# Full hardening (all phases)
./cwp_harden.sh --all

# Recommended flow: audit → dry-run → apply
./cwp_forensic_audit.sh
./cwp_harden.sh --dry-run --all
./cwp_harden.sh --all

Log generated: /home_D0/fixes/logs/harden_*.log


aapanel_forensic_audit.sh — aaPanel Server Forensic Audit

READ-ONLY forensic investigation of compromised aaPanel servers. Full adaptation of the CWP script for the aaPanel (BaoTa panel) architecture, with 28 analysis sections covering paths, services, and configurations specific to this panel.

Usage: ./aapanel_forensic_audit.sh [/www/wwwroot]

Requires: root, bash 4+

Key differences from CWP:

Aspect CWP aaPanel
Sites directory /home/user/public_html /www/wwwroot/sitename/
Web user Per-user (with FPM pool) www (shared)
Web server Apache (default) Nginx (default)
Panel path /usr/local/cwpsrv/ /www/server/panel/
PHP config /opt/alt/phpXX/ /www/server/php/XX/
MySQL config /etc/my.cnf.d/ /www/server/mysql/etc/
Web logs /var/log/httpd/ /www/wwwlogs/
Panel DB PHP-based SQLite (default.db)
Vhost configs Apache vhosts /www/server/panel/vhost/nginx/
PHP injection .htaccess + auto_prepend .user.ini + auto_prepend

28 analysis sections:

# Section What it investigates
1 Directory permissions Site isolation, 777, wp-config, root ownership
2 aaPanel version/config Version, port, security entrance, IP restrict, BasicAuth, API, plugins
3 Web server security Nginx (disable_symlinks, vhosts, open_basedir) or Apache (SymLinks, vhosts)
4 PHP-FPM pools PHP versions, shared pools, open_basedir, disable_functions
5 /tmp and sessions PHP in /tmp, noexec, shared sessions, /dev/shm
6 Cron jobs www/root crontabs, aaPanel cron scripts, /etc/cron.d
7 .user.ini / .htaccess auto_prepend/append, local php.ini, malicious redirects
8 WordPress status Versions, xmlrpc, vulnerable plugins, PHP in uploads
9 SSH authentication SSH config, authorized_keys, failed attempts
10 Firewall/ports firewalld/ufw/iptables, aaPanel firewall plugin
11 Temporal analysis Patient zero, cross-site propagation, identical files
12 SUID/SGID Binaries with elevated permissions in /www
13 Suspicious processes Cryptominers, reverse shells, standalone PHP
14 Network connections C&C connections, suspicious ports
15 Hidden files .ico with PHP, hidden directories, dotfiles PHP
16 wp-config.php Integrity, eval/base64/require /tmp injections
17 FTP (Pure-FTPd) Config, anonymous access, TLS, PHP upload logs
18 Web access logs Brute force wp-login, xmlrpc, exploit paths
19 MySQL/MariaDB Passwordless users, remote access, bind-address
20 Web server modules Nginx autoindex / Apache mod_proxy, mod_info
21 SELinux / AppArmor MAC (Mandatory Access Control) status
22 Kernel/updates Version, distro, pending updates
23 Malicious symlinks Cross-site, to sensitive files, outside wwwroot
24 authorized_keys SSH key integrity verification
25 File capabilities Binaries with elevated capabilities
26 Monitoring auditd, fail2ban, integrity tools
27 aaPanel-specific Panel SSL, panel logs, WAF plugin, backups, modified files
28 Executive summary CRITICAL/WARNING/INFO count + diagnosis + actions

Reports generated:

File Location
forensic_audit_*.txt /www/backup/forensic_logs/
forensic_audit_*.json /www/backup/forensic_logs/

Examples:

# Full audit (READ-ONLY, modifies nothing)
./aapanel_forensic_audit.sh

# Specify alternate directory
./aapanel_forensic_audit.sh /www/wwwroot

# Review critical findings
grep CRITICAL /www/backup/forensic_logs/forensic_audit_*.txt

aapanel_remediate.sh — aaPanel Remediation Pipeline

Full pipeline orchestrator adapted for aaPanel. Obtains MySQL credentials from the panel SQLite DB, handles .user.ini (primary vector on Nginx), and applies www:www permissions.

Usage: ./aapanel_remediate.sh [options] [directory]

Requires: root, bash 4+, Python 3.7+

Options:

Option Description
--clean Clean injections with regex
--disable chmod 000 + rename .DISABLED
--dry-run Report only, don't execute actions
--threshold N Minimum score (default: 60)
--workers N Parallel workers (0=sequential)
--skip-db-backup Skip DB backup
--skip-perms Skip permission correction

6 phases:

Phase Description
1 DB backup (credentials from panel SQLite or fallback wp_backup_db.sh)
2 Heuristic scan with malware_scanner.py
2b .user.ini / .htaccess scan + DB (wp_db_scan.sh)
2c Crontabs (www, root, aaPanel cron scripts)
3 Classification: MALWARE / LIKELY / SUSPICIOUS
4 Cleanup: scanner + malicious .user.ini + DB transients
5 Post-cleanup verification
6 Permissions: www:www, dirs 755, files 644, wp-config 600

Examples:

# Diagnostic only (no changes)
./aapanel_remediate.sh /www/wwwroot

# A specific site
./aapanel_remediate.sh /www/wwwroot/mydomain.com

# Full pipeline with cleanup
./aapanel_remediate.sh --clean /www/wwwroot

# In-place disable (safer, reversible)
./aapanel_remediate.sh --disable /www/wwwroot

# Dry-run with more workers
./aapanel_remediate.sh --dry-run --workers 4 /www/wwwroot

# Recommended flow for aaPanel
./aapanel_forensic_audit.sh                              # 1. Diagnosis
./aapanel_remediate.sh /www/wwwroot                      # 2. Scan (report only)
cat /www/backup/forensic_logs/scan_*_files.txt           # 3. Review findings
./aapanel_remediate.sh --disable /www/wwwroot            # 4. Disable malware
./aapanel_forensic_audit.sh                              # 5. Re-audit

Log generated: /www/backup/forensic_logs/remediate_*.log


generate_html_report.py — HTML Report Generator

Generates executive HTML reports from scanner JSON files. Includes executive summary, detection statistics, detailed findings, action recommendations, and risk matrix by malware type.

Options:

Option Description
JSON_FILE Scanner JSON file(s) (positional, required)
--output DIR Output directory (default: logs/)
--theme THEME Visual theme: light, dark (default: light)
--lang LANG Language: es, en (default: es)
--include-fp Include confirmed false positive matrix
--no-remediation Omit remediation section
--client-name NAME Client name for the header
--scan-date DATE Scan date (default: taken from JSON)

Examples:

# Generate HTML report from a scan
python3 generate_html_report.py logs/scan_2026-03-24_03-41-04.json

# All scans, dark theme
python3 generate_html_report.py logs/scan_*.json --theme dark

# Report for client, in English
python3 generate_html_report.py logs/scan_*.json --client-name "Acme Corp" --lang en

# Without remediation section (findings only)
python3 generate_html_report.py logs/scan_*.json --no-remediation

# Output to specific directory
python3 generate_html_report.py logs/scan_*.json --output /tmp/reports/

Report generated: logs/report_scan_<timestamp>.html


malware_watcher.py — Real-time Resident Antivirus Daemon

Monitors a directory with inotify (Linux kernel-level file events) and runs malware_scanner.py on every PHP/JS/.htaccess file that is created, modified, or renamed — the same mechanism commercial antivirus products use. No polling, near-zero CPU at rest.

Requirements:

pip3 install watchdog

Options:

Option Description
--watch DIR Directory to monitor recursively (default: /home)
--scanner-path PATH Path to malware_scanner.py (default: same directory)
--log-dir DIR Directory for per-scan JSON logs (default: ./logs)
--threshold N Minimum score to report a finding (default: 60)
--debounce SECS Wait N seconds after last event before scanning (default: 3)
--max-file-mb N Skip files larger than N MB (default: 10)
--max-per-min N Maximum scans per minute — rate limiter (default: 120)
--alert-webhook URL POST JSON alert to this URL for each MALWARE verdict
--log-file FILE Also write watcher log to this file
-v, --verbose Show inotify events and scanner debug output

Detected events:

Event Detected? Mechanism
New PHP file uploaded (FTP/SFTP) inotify IN_CLOSE_WRITE
Modified PHP file (injection) inotify IN_MODIFY
Rename .tmp → .php (dropper) inotify IN_MOVED_TO
PHP runtime execution ⚠️ Partial Covered if the file was written first
Binary/shell execution Requires fanotify (more complex)

Installation as systemd service:

# 1. Install dependency
pip3 install watchdog

# 2. Copy files to the server
scp malware_watcher.py malware_watcher.service root@server:/opt/malscanner/

# 3. Edit paths in the service file
nano /opt/malscanner/malware_watcher.service
# → Adjust: WorkingDirectory, ExecStart --scanner-path, --log-dir

# 4. Install and start the service
cp /opt/malscanner/malware_watcher.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now malware-watcher

# 5. Check live status
systemctl status malware-watcher
journalctl -u malware-watcher -f

Manual test (before installing as service):

# Basic test — verbose, watch /home
python3 malware_watcher.py --watch /home --verbose

# With alert webhook (Slack, Discord, custom API)
python3 malware_watcher.py --watch /home --alert-webhook https://hooks.example.com/alerts

# With log to file + higher threshold
python3 malware_watcher.py --watch /home --threshold 75 --log-file /var/log/malwatch.log

# Lower rate limit (conserve CPU on high-traffic servers)
python3 malware_watcher.py --watch /home --max-per-min 30 --debounce 5

Service management:

# View live alerts
journalctl -u malware-watcher -f

# Stop service
systemctl stop malware-watcher

# Restart after updating malware_scanner.py or signatures/
systemctl restart malware-watcher

# Disable on server shutdown (leave installed)
systemctl disable malware-watcher

Configuration file (malware_watcher.service):

[Service]
ExecStart=/usr/bin/python3 /opt/malscanner/malware_watcher.py \
    --watch         /home                              \
    --scanner-path  /opt/malscanner/malware_scanner.py \
    --log-dir       /opt/malscanner/logs               \
    --threshold     60                                 \
    --debounce      3                                  \
    --max-file-mb   10                                 \
    --max-per-min   120                                \
    --log-file      /var/log/malware_watcher.log
CPUQuota=40%
PrivateTmp=true
NoNewPrivileges=true

install_watcher.sh — Service Installer

Automatic installer for malware_watcher.py as a systemd service. Handles dependency installation, file deployment, and service configuration.

Modes:

Mode Description
./install_watcher.sh Interactive install — prompts for each setting
./install_watcher.sh --install Non-interactive install with defaults
./install_watcher.sh --uninstall Remove service and optionally delete files
./install_watcher.sh --update Update toolkit files, preserve configuration
./install_watcher.sh --status Show service state and installation info

Defaults (overridable in interactive mode):

Setting Default
Install directory /opt/malscanner
Watch directory /home
Score threshold 60
Debounce (seconds) 3
Max file size (MB) 10
Rate limit (scans/min) 120
CPU quota 40%

Usage examples:

# Interactive install (recommended first time)
sudo ./install_watcher.sh

# Non-interactive with all defaults
sudo ./install_watcher.sh --install

# Update after pulling new scanner signatures
sudo ./install_watcher.sh --update

# Check service health
./install_watcher.sh --status

# Full removal
sudo ./install_watcher.sh --uninstall

Recommended Workflow

Option A: Automated pipeline (recommended)

# 1. Full diagnostic (no changes)
./remediate.sh /home

# 2. Review reports in /home_D0/fixes/logs/
# 3. Execute cleanup
./remediate.sh --clean /home

Option B: Manual step by step

# 1. Backup databases
./wp_backup_db.sh /home

# 2. Heuristic scan (report only)
python3 malware_scanner.py --scan /home --no-quarantine

# 3. Database scan
./wp_db_scan.sh /home

# 4. Check crontabs (clean first = prevent reinfection)
./cron_check.sh --fix

# 5. Clean malware + verify
python3 malware_scanner.py --scan /home --clean --verify

# 6. Clean malicious DB transients
./wp_db_scan.sh --fix /home

# 7. Restore WP core
./wp_reemplaza.sh

# 8. Re-verify
python3 malware_scanner.py --scan /home --no-quarantine

# 9. Fix permissions
./fix_permissions.sh --all

Option C: Forensic audit + Hardening (compromised CWP server)

When all users on a CWP server were infected simultaneously.

# 1. Upload scripts to server from Windows
scp -P 2222 cwp_forensic_audit.sh cwp_harden.sh root@SERVER:/root/
scp -P 2222 malware_scanner.py remediate.sh root@SERVER:/root/
scp -P 2222 wp_backup_db.sh wp_db_scan.sh cron_check.sh root@SERVER:/root/
scp -P 2222 fix_permissions.sh wp_reemplaza.sh root@SERVER:/root/
scp -rP 2222 signatures/ root@SERVER:/root/signatures/

# 2. On the Linux server, set execute permissions
chmod +x /root/*.sh

# 3. Create working directories
mkdir -p /home_D0/fixes/{logs,quarantine,backups,wordpress}

# 4. Run forensic audit (READ-ONLY, modifies nothing)
./cwp_forensic_audit.sh

# 5. Review the report — identify root cause
cat /home_D0/fixes/logs/forensic_audit_*.txt

# 6. Backup databases
./wp_backup_db.sh /home

# 7. Heuristic malware scan (report only)
python3 malware_scanner.py --scan /home --no-quarantine --report both

# 8. Review findings and false positives
cat /home_D0/fixes/logs/scan_*_files.txt

# 9. Apply hardening with dry-run first
./cwp_harden.sh --dry-run --all

# 10. Apply real hardening (phase by phase recommended)
./cwp_harden.sh --fix-perms
./cwp_harden.sh --fix-fpm
./cwp_harden.sh --fix-apache
./cwp_harden.sh --fix-ssh
./cwp_harden.sh --fix-mysql
./cwp_harden.sh --fix-tmp
./cwp_harden.sh --fix-firewall

# 11. Clean malware and verify
./cron_check.sh --fix
python3 malware_scanner.py --scan /home --clean --verify --report both

# 12. Restore WordPress core + permissions
./wp_reemplaza.sh
./fix_permissions.sh --all

# 13. Generate executive HTML report
python3 generate_html_report.py /home_D0/fixes/logs/scan_*.json --client-name "My Server"

Server Deployment

From Windows (development) → Linux (server)

# Upload entire toolkit to server
scp -P 2222 -r . root@SERVER:/root/malware_toolkit/

# Or upload only essential scripts
scp -P 2222 malware_scanner.py remediate.sh cwp_forensic_audit.sh cwp_harden.sh \
    wp_backup_db.sh wp_db_scan.sh cron_check.sh fix_permissions.sh \
    wp_reemplaza.sh generate_html_report.py root@SERVER:/root/

scp -rP 2222 signatures/ root@SERVER:/root/signatures/

Server Preparation

# Set execute permissions
chmod +x /root/*.sh

# Create working directories
mkdir -p /home_D0/fixes/{logs,quarantine,backups,wordpress}

# Verify Python dependencies
python3 -c "import json, sys, re, hashlib; print('OK')"

# Verify system tools
for cmd in mysqldump mysql gzip find rsync stat chown chmod; do
    command -v "$cmd" &>/dev/null && echo "$cmd" || echo "$cmd MISSING"
done

Signature Layers

Layer File Signatures
1. Core Embedded in malware_scanner.py ~70
2. Internal signatures/internal_knowledge.json 6
3. Community signatures/community.json 6
4. Local IOC signatures/local_iocs.json 9
5. YARA signatures/yara/php_webshells_curated.yar 5
6. Fallback signatures/yara_fallback.json 5

If yara-python is not installed, regex fallback activates automatically.

To add detections:

  • New IOCs → signatures/local_iocs.json
  • Internal signatures → signatures/internal_knowledge.json
  • YARA rules → signatures/yara/php_webshells_curated.yar
  • Fallback → signatures/yara_fallback.json

Requirements

  • Python 3.7+
  • Linux/CentOS (default paths point to /home_D0/fixes)
  • Bash 4+ (CentOS 7+, Ubuntu 16.04+)
  • Root for most scripts
  • System tools: mysqldump, mysql, gzip, find, flock, rsync, stat, chown, chmod

Optional dependency:

  • yara-python for real YARA rule compilation

Path Configuration

Base paths are defined in the main scripts:

Variable Default Used in Description
QUARANTINE_DIR /home_D0/fixes/quarantine malware_scanner.py Quarantined files
LOG_DIR /home_D0/fixes/logs All Logs and reports
WP_CLEAN_DIR /home_D0/fixes/wordpress malware_scanner.py Clean WP copy
SIGNATURES_DIR ./signatures malware_scanner.py External signatures
HOME_BASE /home cwp_forensic_audit.sh, cwp_harden.sh User base directory

Adjust these paths before running in production.

Project Structure

malware_scanner.py          # Main heuristic engine (6 signature layers)
remediate.sh                # 7-phase pipeline orchestrator
cwp_forensic_audit.sh       # CWP forensic audit (27 sections)
cwp_harden.sh               # Post-compromise CWP hardening (7 phases)
aapanel_forensic_audit.sh   # aaPanel forensic audit (28 sections)
aapanel_remediate.sh        # aaPanel remediation pipeline (6 phases)
generate_html_report.py     # Executive HTML report generator
wp_backup_db.sh             # WordPress database backup
wp_db_scan.sh               # Database scanning (injections)
cron_check.sh               # Malicious crontab detection
wp_reemplaza.sh             # WordPress core restoration
fix_permissions.sh          # Hosting permission correction
malware_scan.sh             # Quick triage (read-only)
wp_security_scan.sh         # Basic quarantine by signatures
wp_reinfection_audit.sh     # Reinfection vector audit (52 checks, 10 categories)
malware_watcher.py          # Real-time resident daemon (inotify antivirus)
malware_watcher.service     # systemd unit for malware_watcher
install_watcher.sh          # Installer for malware_watcher service
signatures/
  ├── internal_knowledge.json   # 6 internal signatures
  ├── community.json            # 6 community signatures
  ├── local_iocs.json           # 9 local IOCs (extensible)
  ├── yara/                     # 5 YARA rules (optional)
  └── yara_fallback.json        # 5 regex fallback rules
malware_refs/               # Reference malware samples for testing
logs/                       # Scan reports (JSON, TXT, HTML, rm_*.txt)
SKILL.md                    # Complete operational guide

Anti-Patterns (DON'T)

  • DON'T run --clean on the first pass without reviewing findings
  • DON'T delete files without a prior DB backup
  • DON'T blindly trust scan_*.rm_ALL.txt — review false positives
  • DON'T ignore SUSPICIOUS findings
  • DON'T forget to clean crontabs before cleaning files (causes reinfection)
  • DON'T leave 777 permissions after remediation
  • DON'T restore WP core without verifying the correct version

License

This project is licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0).

You may share the material with attribution, but not for commercial use and without derivative works.

See the LICENSE file for the full text.

Disclaimer

This project is provided for incident analysis and response tasks. Use is at the user's own risk.

No se garantiza la recuperación total de sitios WordPress comprometidos. En incidentes severos (persistencia profunda, backdoors múltiples, corrupción de BD o reinfección activa), puede no ser posible restaurar completamente el sitio.

Recomendaciones:

  • Mantener respaldos íntegros y verificados (archivos + base de datos)
  • Probar primero en entornos de staging
  • Validar manualmente cambios críticos antes de aplicar en producción

About

Toolkit completo para detectar, analizar y remediar malware PHP en servidores Linux de web hosting (CWP/cPanel) con WordPress. Incluye auditoría forense, hardening post-compromiso y generación de reportes HTML ejecutivos.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors