Ransomware gets in through predictable paths: weak credentials, unpatched services, overly permissive file access, and missing backups. Once inside, it spreads using the same privilege escalation and lateral movement techniques we've been defending against for years. The difference is speed and automation.
I've worked ransomware recovery tickets where the first sign of trouble was a PHP error because the web root had been encrypted. By then it's too late. Defense happens before the encryption binary runs, and it starts with controlling who and what can touch your server.
Lock down remote access first
SSH is the front door. Disable password authentication completely.
Edit /etc/ssh/sshd_config and set:
PasswordAuthentication no
PermitRootLogin prohibit-password
PubkeyAuthentication yes
Restart SSH with systemctl restart sshd. From that point forward, only users holding the matching private key can authenticate. Brute force attacks against passwords become irrelevant.
Move SSH off port 22 if you want to cut down log noise, but don't rely on obscurity as a defense. The real protection is key-based auth. I keep a hardware key for production servers and a separate passphrase-protected key for staging.
For cPanel or Plesk environments, use two-factor authentication on the control panel itself. Most ransomware crews pivot from compromised hosting accounts, not SSH directly. If your panel login can be guessed, everything underneath is exposed.
Segment user file permissions aggressively
A compromised website shouldn't be able to write to other sites on the same server. Set up separate Linux users per domain or application.
On cPanel this happens automatically if you use the default account isolation, but verify it:
ls -la /home/
Each account should be owned by its respective user, not nobody or root. Web processes should run under that same user via suPHP, PHP-FPM pools, or LVE.
For VPS or bare metal, create a dedicated user per application:
useradd -m -s /bin/bash appuser
chown -R appuser:appuser /var/www/app
Then configure your web server to run PHP as that user. If one site is breached, the attacker is jailed to that user's home directory and can't write to /var/www/othersite.
I've seen ransomware spread across fifty WordPress installs on a single shared hosting account because they all ran as the same user. Separation stops lateral movement cold.
Disable unnecessary services and close ports
Every listening service is a potential entry point. Run ss -tuln and audit what's open.
Common culprits: FTP on port 21, Telnet on 23, old RDP setups, MySQL exposed on 3306, and random management panels on high ports. If you're not actively using it, stop the service and block the port.
For MySQL or PostgreSQL, bind only to localhost unless you specifically need remote database access:
# /etc/my.cnf or /etc/mysql/my.cnf
bind-address = 127.0.0.1
Restart the database service. Now SQL injection or credential stuffing attempts can only originate from the local machine, which drastically shrinks the attack surface.
If you must expose SSH, MySQL, or another service, whitelist IPs with a firewall rule. On systems with firewalld:
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" port port="3306" protocol="tcp" accept'
firewall-cmd --reload
Substitute your actual trusted IP range. Attackers scanning the internet will hit a closed port and move on.
Keep software patched without delay
Ransomware groups watch CVE feeds and weaponize exploits within hours. If your CMS, control panel, kernel, or web server has a known vulnerability, you're racing the clock.
On Debian or Ubuntu, enable unattended-upgrades for security patches:
apt install unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades
On CentOS or RHEL, dnf-automatic does the same job:
dnf install dnf-automatic
systemctl enable --now dnf-automatic.timer
For cPanel, use the built-in update system and check /var/cpanel/updatelogs/ to confirm recent updates. For WordPress or Joomla, I've seen successful ransomware attacks through year-old plugin vulnerabilities that had patches available. Automate updates where possible or set a weekly schedule to review and apply them manually.
Kernels require a reboot to activate. Check uptime with uptime and plan a maintenance window if you're running months behind.
Off-site backups that ransomware can't encrypt
Backups are your last line of defense, but only if the attacker can't reach them. Ransomware will encrypt any mounted filesystem or accessible cloud bucket.
Use a backup system that writes to append-only or immutable storage. Options:
- rclone with Wasabi, Backblaze B2, or S3 Glacier, configured with object lock.
- restic with append-only mode and a separate retention policy.
- Borg Backup to a remote server that only accepts new archives, not deletions.
Here's a simple daily restic job:
#!/bin/bash
export RESTIC_REPOSITORY="s3:s3.amazonaws.com/my-backup-bucket"
export RESTIC_PASSWORD_FILE="/root/.restic-pass"
restic backup /var/www /home /etc \
--exclude /var/www/cache \
--exclude /home/*/tmp
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
Run it via cron at 2 AM. The key is that the backup destination isn't a writable mount on the server being backed up. If an attacker owns the server, they can't retroactively delete old snapshots.
Test restores quarterly. I've watched teams discover their backups were empty or missing critical databases only after an incident.
Monitor file integrity and log unusual writes
Ransomware leaves fingerprints: mass file modifications, new executables in temp directories, unexpected cron jobs, and rapid disk I/O.
Install AIDE (Advanced Intrusion Detection Environment) to baseline filesystem state:
apt install aide
aideinit
mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
Run aide --check daily via cron. You'll get alerts when binaries in /usr/bin, configs in /etc, or web roots are modified. False positives happen during legitimate updates, but catching an unauthorized binary drop is worth the noise.
For real-time monitoring, auditd logs file access:
auditctl -w /var/www -p wa -k webroot_changes
Search logs with ausearch -k webroot_changes. You'll see which process and user touched which files. When a PHP script spawns a process that starts encrypting JPEGs in fifteen directories, the audit trail shows it.
Centralize logs to an external syslog server or SIEM so an attacker can't erase evidence after the fact.
Restrict command execution in web directories
Web shells and ransomware payloads both need to execute code. Deny that ability wherever uploads land.
For Apache, add to your virtual host or .htaccess in the uploads directory:
<Directory /var/www/html/wp-content/uploads>
<FilesMatch "\.(?i:php|phtml|php3|php4|php5|pl|py|jsp|asp|sh|cgi)$">
Require all denied
</FilesMatch>
</Directory>
For Nginx, block execution in the uploads location:
location ~* ^/wp-content/uploads/.*\.(php|php3|php4|php5|phtml|pl|py|jsp|asp|sh|cgi)$ {
deny all;
}
Reload your web server. Now even if an attacker uploads shell.php through a form vulnerability, the web server will refuse to run it. They can write the file but can't execute it, which breaks the attack chain.
I've reversed incidents where the attacker uploaded a web shell into /wp-content/uploads/2023/01/ and used it to deploy ransomware. If execution had been blocked, the compromise would have ended at the upload.
Use application firewalls to block known payloads
ModSecurity with the OWASP Core Rule Set catches common exploit patterns: SQL injection, directory traversal, command injection, and suspicious file uploads.
On Apache:
apt install libapache2-mod-security2
cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
Edit /etc/modsecurity/modsecurity.conf and set:
SecRuleEngine On
Download the OWASP CRS and enable it:
cd /usr/share/modsecurity-crs
git clone https://github.com/coreruleset/coreruleset.git
cp coreruleset/crs-setup.conf.example /etc/modsecurity/crs-setup.conf
Include it in Apache config and restart. You'll block many of the POST requests that try to drop ransomware payloads via vulnerable plugins.
For Cloudflare users, enable WAF rules and rate limiting at the edge. An attacker hitting your site from a residential proxy or VPN gets blocked before they reach your server.
Limit privilege escalation paths
Ransomware often lands as a low-privilege user and then escalates to root to encrypt system files or disable backups. Harden sudo and SUID binaries.
Audit SUID binaries:
find / -perm -4000 -type f 2>/dev/null
You'll see a list of executables that run with elevated privileges. Remove the SUID bit from anything you don't recognize or need:
chmod u-s /usr/bin/suspicious-binary
For sudo, configure /etc/sudoers with least privilege. Avoid ALL=(ALL) NOPASSWD: ALL. Grant only specific commands:
appuser ALL=(root) NOPASSWD: /usr/bin/systemctl restart nginx
Monitor sudo usage with journalctl -u sudo and watch for unexpected escalation attempts.
Enforce immutable flags on critical configs
Linux has an immutable attribute that prevents any user, including root, from modifying a file until the flag is removed.
Set it on files you never want changed:
chattr +i /etc/ssh/sshd_config
chattr +i /etc/passwd
chattr +i /etc/sudoers
Now even if an attacker gets root, they can't edit those files without first running chattr -i, which is an extra step that stands out in audit logs.
I use this on production servers where SSH config and user accounts should never change outside scheduled maintenance. It's saved me once when a compromised script tried to add a backdoor user to /etc/passwd and failed.
What to check first
Start with SSH keys and disable password auth today. Then audit listening services and close anything you're not using. Set up off-site backups if you haven't already, because recovering from a good backup beats negotiating with attackers.
File permissions and least privilege come next. Ransomware spreads because users and processes have write access they don't need. Tighten that before the next vulnerability drops.
Patching and monitoring are ongoing. Automate security updates, test your backups, and watch your logs. The defenses that stop ransomware are the same ones that stop every other server compromise. They just need to be in place before the attack starts.
