Skip to content
Back to Blog
Security11 min read

Ransomware Attack Prevention: 9 Server Defenses That Work

Stop ransomware before encryption starts with access controls, configuration hardening, and monitoring that blocks attack paths at the server level.

Written by Abdul AbrorTechnical Hosting Support Engineer
Ransomware Attack Prevention: 9 Server Defenses That Work
On this page

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.

FAQ

Does disabling root login completely prevent SSH attacks?

No, but it forces attackers to guess a valid username and key. Most automated tools only try root. Combine it with key-based auth and you're orders of magnitude safer.

How often should I rotate SSH keys?

Rotate when an employee leaves or a machine is decommissioned. For active keys, annual rotation is reasonable. The key itself is less important than never exposing the private half.

Can ransomware encrypt backups if they're on a separate server?

Yes, if the backup server is reachable via SSH or mounted as a filesystem. Use append-only storage, object lock, or a pull model where the backup server initiates the connection.

What if I need to allow password authentication for one user?

Don't. Issue that user an SSH key and enforce it server-wide. If you absolutely must, create a separate SSH config with Match User and require 2FA for that user only.

Is ModSecurity enough to stop ransomware?

No. It stops web-based delivery of payloads but won't help if an attacker uses SSH or a compromised email account. Defense is layered.