The Reality of Modern SSH Exploitation
During a recent forensic audit for a Mumbai-based fintech firm, we observed over 45,000 failed SSH login attempts within a single six-hour window. These weren't simple dictionary attacks; they were sophisticated, multi-staged probes targeting the recent CVE-2024-6387 (regreSSHion) vulnerability. This critical signal handler race condition in OpenSSH's server (sshd) allows unauthenticated remote code execution as root on glibc-based Linux systems. If your infrastructure still relies on default configurations provided by budget VPS providers like E2E Networks or Netmagic, you are likely running vulnerable versions of OpenSSH with PasswordAuthentication enabled by default.
The threat landscape has shifted from simple brute-force to protocol-level manipulation. The Terrapin Attack (CVE-2023-48795) proved that even encrypted channels are susceptible to prefix truncation, allowing attackers to downgrade connection security by manipulating sequence numbers during the handshake. Securing the Secure Shell (SSH) is no longer about choosing a strong password; it requires a complete cryptographic overhaul and real-time telemetry integration to meet the 180-day log retention mandates set by CERT-In Cyber Security Directions (2022).
Core Principles of SSH Security Hardening
Hardening is the process of reducing the attack surface by removing unnecessary functional capabilities and enforcing the principle of least privilege. In the context of SSH, this means treating the sshd_config file as a security policy rather than a configuration script. For a deeper dive into workstation protection, see our guide on preventing PHANTOMPULSE RAT via secure SSH workflows. We start by stripping away legacy compatibility. Modern Linux environments do not need to support SSH Protocol 1 or weak CBC-based ciphers that were standard a decade ago.
The /etc/ssh/sshd_config file is the primary point of failure for most systems. I frequently see administrators make the mistake of adding rules without verifying the effective configuration. Always use the test mode to validate syntax before restarting the service:
$ sudo sshd -t $ echo $?
If the output is 0, the configuration is syntactically correct. If not, the daemon will fail to start, potentially locking you out of a remote production node.
The Role of Cryptographic Agility
We must explicitly define which Key Exchange (KEX) algorithms, Ciphers, and Message Authentication Codes (MACs) the server will accept. By default, OpenSSH often permits older algorithms for backward compatibility. In a hardened environment, we prioritize Edwards-curve Digital Signature Algorithm (Ed25519) and ChaCha20-Poly1305. These are not only more secure but also more performant on modern hardware.
Essential SSH Hardening Best Practices
The first step in any hardening sprint is the elimination of password-based entry. Passwords are the weakest link in the identity chain, susceptible to phishing, credential stuffing, and local interception. For organizations looking for a shared SSH key alternative that centralizes identity, a zero-trust gateway is often more effective. I recommend generating Ed25519 keys with a high iteration count for the Key Derivation Function (KDF) to protect the private key at rest.
Generating a high-entropy Ed25519 key
$ ssh-keygen -t ed25519 -a 100 -f ~/.ssh/bastion_key -C "admin@warnhack-gateway"
The -a 100 flag increases the number of KDF rounds, making it significantly harder for an attacker to brute-force the passphrase if they obtain the private key file.
Disabling Root Login and Password Auth
We must enforce a two-step entry process: login as a standard user with sudo privileges, then escalate if necessary. This creates an audit trail that identifies exactly which human operator performed an action. Modify the following parameters in /etc/ssh/sshd_config:
Disable direct root access
PermitRootLogin no
Disable password authentication
PasswordAuthentication no ChallengeResponseAuthentication no UsePAM yes
While UsePAM is set to yes, the PasswordAuthentication no directive ensures that the PAM password module is bypassed for SSH sessions, forcing the use of public keys.
Changing the Default Port: Obscurity vs. Utility
While changing the default port (22) is not a primary security control, it is an effective "noise reduction" tactic. In the Indian context, regional IP blocks (APNIC) are frequently scanned by automated bots. Moving SSH to a non-standard port like 2222 or 443 (if not used by HTTPS) can reduce log volume by 90%, making it easier for SIEM tools to identify genuine threats.
Edit /etc/ssh/sshd_config
Port 4242
Update your local firewall immediately after this change to avoid a lockout.
Advanced SSH Hardening Techniques
Standard key-based authentication is strong, but adding a second factor (2FA) provides a critical safety net for the DPDP Act 2023 compliance, aligning with OWASP Top 10 recommendations for robust access control. We use the google-authenticator PAM module to enforce Time-based One-Time Passwords (TOTP).
$ sudo apt-get install libpam-google-authenticator $ google-authenticator
Once configured, update /etc/pam.d/sshd to include auth required pam_google_authenticator.so and modify sshd_config to require both methods:
Require both public key AND TOTP
AuthenticationMethods publickey,keyboard-interactive
Configuring Idle Timeout Intervals
Orphaned SSH sessions are a major risk in shared office environments. If an administrator leaves their terminal unlocked, an attacker can hijack the active session. We enforce server-side timeouts to terminate inactive connections.
Terminate session after 5 minutes of inactivity
ClientAliveInterval 300 ClientAliveCountMax 0
Setting ClientAliveCountMax to 0 ensures that the server sends a "keep-alive" request and drops the connection immediately if the client does not respond, rather than allowing multiple failed checks.
Restricting Access with AllowUsers
Instead of allowing every account on the system to use SSH, we implement a whitelist. This is particularly important for systems that have service accounts (like www-data or postgres) which should never be accessible remotely.
Only allow specific users or groups
AllowGroups ssh-gate-users AllowUsers sysadmin-rahul dev-priya
Network-Level SSH Security Measures
The host-based configuration is only one layer of the stack. We must implement active defense mechanisms to handle the volume of automated attacks. Fail2Ban is the standard tool for this, but it must be configured with aggressive banning policies for production gateways.
/etc/fail2ban/jail.local
[sshd] enabled = true port = 4242 filter = sshd logpath = /var/log/auth.log maxretry = 3 bantime = 86400 findtime = 600
This configuration bans any IP address that fails three login attempts within 10 minutes for a full 24 hours. Given the low cost of IP rotation for attackers, a long bantime is essential.
Firewall Restrictions and Jump Hosts
Exposing SSH to the entire internet is a risk that can be mitigated by restricting access to known static IPs or using a VPN (WireGuard/OpenVPN). If your team operates from multiple locations, a browser based SSH client can replace traditional jump hosts to simplify connectivity. The internal servers only accept SSH connections from the Bastion's internal IP.
UFW rule to allow SSH only from a specific IP (e.g., Office VPN)
$ sudo ufw allow from 203.0.113.45 to any port 4242 proto tcp
SIEM Integration and Real-time Alerting
For compliance with the DPDP Act and CERT-In guidelines, logs must be moved off the local host to a centralized SIEM (Security Information and Event Management) system like ELK, Graylog, or a cloud-native solution. We configure sshd to provide verbose logging to capture more metadata about the connection attempt.
In /etc/ssh/sshd_config
SyslogFacility AUTHPRIV LogLevel VERBOSE
VERBOSE level logs the fingerprint of the public key used for login, which is critical for attribution during an incident response. To monitor these logs in real-time, we can use a simple script to parse journalctl and send alerts to a Slack or Microsoft Teams webhook.
import subprocess import json import requests
def monitor_ssh(): # Watch journalctl for failed SSH attempts process = subprocess.Popen( ['journalctl', '-u', 'ssh', '-f', '-o', 'json'], stdout=subprocess.PIPE )
for line in iter(process.stdout.readline, b''): log_entry = json.loads(line) message = log_entry.get("MESSAGE", "") if "Failed password" in message or "Invalid user" in message: payload = {"text": f"SSH Alert: {message} on {log_entry.get('_HOSTNAME')}"} # Replace with your actual webhook URL # requests.post("https://hooks.slack.com/services/...", json=payload) print(f"Alert Sent: {message}")
if __name__ == "__main__": monitor_ssh()
Auditing with Lynis
We don't guess if our hardening is effective; we audit it. Lynis is an open-source security auditing tool that provides a "Hardening Index" score. It checks for SSH configuration weaknesses, file permissions, and outdated packages.
$ sudo lynis audit system --tests-from-group ssh
I aim for a Lynis SSH hardening score of 90+. Anything lower indicates that the server is still utilizing weak cryptographic primitives or has insecure file permissions on the .ssh directories.
Hardened sshd_config Template
The following configuration summarizes the research and testing we conducted to mitigate both the Terrapin and regreSSHion vulnerabilities. This should be deployed across all Linux nodes via Ansible or SaltStack.
/etc/ssh/sshd_config Hardening ###
Protocol 2 PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes MaxAuthTries 3 ClientAliveInterval 300 ClientAliveCountMax 0 AllowGroups ssh-gate-users
Mitigation for Terrapin & regreSSHion
We exclude SHA1 and 96-bit MACs
KexAlgorithms [email protected],diffie-hellman-group-exchange-sha256 Ciphers [email protected],[email protected],[email protected] MACs [email protected],[email protected]
Logging for SIEM ingestion and CERT-In compliance
SyslogFacility AUTHPRIV LogLevel VERBOSE
Security Headers
Banner /etc/ssh/banner.txt
Implementing the Legal Banner
In Indian law, providing explicit notice that a system is private and monitored can be a prerequisite for legal action against unauthorized access. Create a file at /etc/ssh/banner.txt with a clear warning:
WARNING: AUTHORIZED ACCESS ONLY. This system is the property of [Company Name]. All activities are logged and monitored in accordance with the DPDP Act 2023. Unauthorized access will be prosecuted to the fullest extent of the law.
Maintaining the Defense Posture
Security hardening is not a "set and forget" task. As new CVEs like regreSSHion emerge, the window between disclosure and exploitation shrinks. We use auditd to monitor the integrity of the SSH configuration file itself. If an attacker gains temporary access and tries to weaken the configuration, an alert is triggered immediately.
Monitor sshd_config for changes
$ sudo auditctl -w /etc/ssh/sshd_config -p wa -k sshd_tampering
To view tampering attempts:
$ sudo ausearch -k sshd_tampering
Regularly check for outdated OpenSSL libraries, as the SSH daemon relies on them for underlying cryptographic operations. On Debian/Ubuntu systems, we automate this with unattended-upgrades, but specifically pin the openssh-server package to ensure it receives security patches without delay.
$ sudo apt-get update && sudo apt-get install openssh-server -y
Identify the most targeted users on your gateway to refine your AllowUsers list:
$ grep -E "Failed|Invalid" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -nr | head -n 10
Next Command: Run openssl dhparam -out /etc/ssh/dhparams.pem 4096 to generate custom Diffie-Hellman parameters, then configure sshd to use them to prevent Logjam-style attacks.
