Lazarus Group and the ClickFix Campaign: A Technical Analysis
We recently analyzed a series of macOS malware samples linked to the Lazarus Group’s "Operation Dream Job." These campaigns specifically target developers in Indian tech hubs like Bengaluru and Hyderabad. To further compromise these environments, attackers often look for ways of detecting malicious VS Code extensions that can be used to exfiltrate source code. The attack vector, dubbed "ClickFix," involves a sophisticated social engineering chain where attackers pose as recruiters from global financial firms. They invite developers to a technical interview and provide a link to a fake meeting application (Zoom or Webex clones). These installers contain a heap buffer overflow exploit (CVE-2023-4863) in libwebp to achieve remote code execution on macOS systems.
I observed that once the initial payload executes, the malware's primary objective is the exfiltration of the ~/.ssh/ directory. In many Indian MSPs, developers use personal macOS devices for corporate access without robust Mobile Device Management (MDM) enforcement. This "Shadow IT" environment allows Lazarus to steal unpassphrased SSH keys, providing them with lateral movement capabilities into production environments. We found that the malware specifically searches for id_rsa, id_ed25519, and known_hosts to map the victim's infrastructure.
To identify if a macOS system has been compromised or if the TCC (Transparency, Consent, and Control) database has been tampered with to allow unauthorized file access, we use the following command to query the TCC database:
sqlite3 ~/Library/Application\ Support/com.apple.TCC/TCC.db "SELECT client, service, allowed FROM access WHERE service='kTCCServiceSystemPolicyAllFiles';"
If you see unfamiliar binaries with allowed = 1 for SystemPolicyAllFiles, the system's integrity is compromised. Lazarus often uses Node.js or Python scripts disguised as "coding assessments" (e.g., "CapitalQuiz") to automate this exfiltration. Hardening the SSH daemon (sshd) on the server side is the only way to mitigate the impact of these stolen credentials.
Introduction to SSH Hardening in Linux
Why SSH Hardening is Critical for Server Security
SSH is the most targeted service on any internet-facing Linux server. We see thousands of brute-force attempts within minutes of a new IP being assigned to a VPS. However, brute force is no longer the primary threat. The Lazarus ClickFix campaign demonstrates that credential theft via client-side exploitation is a more potent risk. To eliminate the risk of local key theft entirely, organizations are increasingly moving toward a browser based SSH client that manages access without storing sensitive keys on end-user devices. When an attacker possesses a legitimate SSH key, traditional security measures like IP whitelisting are often bypassed if the attacker uses the victim's local machine as a SOCKS proxy.
In the context of the Digital Personal Data Protection (DPDP) Act 2023, Indian organizations are now legally mandated to implement reasonable security practices to prevent data breaches. A compromised SSH gateway leading to a data leak could result in penalties up to ₹250 crore. Hardening SSH is not just a technical requirement; it is a compliance necessity under Section 8 of the DPDP Act.
Common SSH Vulnerabilities and Attack Vectors
- Credential Theft: Phishing developers for SSH private keys, as seen in Lazarus "Operation Dream Job."
- Supply Chain Attacks: CVE-2024-3094 (the XZ Utils backdoor) targeted
sshdvialiblzma, specifically impacting systems wheresshdis patched to support systemd notification. - Weak Ciphers: Use of legacy algorithms like
ssh-dssor3des-cbcwhich are susceptible to birthday attacks and plaintext recovery. - Agent Forwarding Exploitation: If a developer connects to a compromised jump box with SSH agent forwarding enabled, the attacker can use the forwarded socket to authenticate to other servers.
The Ultimate SSH Hardening Guide for Ubuntu and Debian
Step-by-Step SSH Hardening for Ubuntu 24.04
Ubuntu 24.04 (Noble Numbat) ships with relatively sane defaults, but it still allows password authentication and root login by default in many cloud images. Our first step is to modify /etc/ssh/sshd_config. I recommend creating a backup before making changes. We focus on disabling legacy protocols and enforcing strictly modern cryptographic primitives.
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sudo nano /etc/ssh/sshd_config
Apply these settings to mitigate the risk of stolen keys and downgrade attacks:
# /etc/ssh/sshd_config - Hardened for Lazarus/ClickFix MitigationProtocol 2 IgnoreRhosts yes HostbasedAuthentication no PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes MaxAuthTries 3
Restrict to modern, secure algorithms
KexAlgorithms [email protected],diffie-hellman-group-exchange-sha256 Ciphers [email protected],[email protected] MACs [email protected],[email protected]
Key Differences in SSH Hardening for Debian Systems
Debian (especially older versions like Debian 11/12) may not include all modern ciphers in the default openssh-server package. On Debian, we must verify that the KexAlgorithms we specify are actually supported by the installed version of OpenSSH. Use ssh -Q kex to list supported exchange algorithms. Debian systems also tend to have PermitRootLogin prohibit-password as a default, which allows root login via keys. We must explicitly set this to no to force the use of unprivileged accounts and sudo.
Disabling Root Login and Password Authentication
Disabling root login forces an attacker to first guess a valid username, doubling the complexity of a brute-force attack. More importantly, it ensures that there is an audit trail of which specific user accessed the system. When we disable PasswordAuthentication, we effectively neutralize all automated brute-force scripts. We must ensure that ChallengeResponseAuthentication is also set to no, as it can sometimes fall back to password prompts.
# Disable all password-based entryPasswordAuthentication no ChallengeResponseAuthentication no UsePAM yes
PermitRootLogin no is non-negotiable
PermitRootLogin no
Implementing SSH Key-Based Authentication
We only use Ed25519 keys. RSA is acceptable if the bit length is 4096, but Ed25519 is faster and provides better security with shorter keys. When generating keys for your team, enforce the use of strong passphrases. This is the primary defense against the Lazarus ClickFix exfiltration; even if the id_ed25519 file is stolen, it is useless without the passphrase.
# Generate a secure key on the client side
ssh-keygen -t ed25519 -a 100 -C "[email protected]"
To audit the keys currently authorized on a server, I use this command to list the fingerprint and hashing algorithm of every key in authorized_keys:
ssh-keygen -l -E sha256 -f ~/.ssh/authorized_keys
Automating Security: SSH Hardening Ansible and Scripts
Using SSH Hardening Ansible Roles for Scalable Security
Managing SSH configurations manually across 500+ instances in an AWS Mumbai (ap-south-1) environment is impossible. We use Ansible to enforce a desired state. The dev-sec.ssh-hardening role is the industry standard, but I prefer a custom, minimalist playbook to reduce dependencies. This ensures that every new instance provisioned for our developers adheres to the hardened spec immediately.
- hosts: allbecome: yes tasks: - name: Configure sshd_config copy: dest: /etc/ssh/sshd_config content: | Protocol 2 PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes KexAlgorithms [email protected] Ciphers [email protected],[email protected] MACs [email protected] AuthenticationMethods publickey mode: '0600' owner: root group: root notify: restart ssh
handlers: - name: restart ssh service: name: ssh state: restarted
Finding and Auditing SSH Hardening Scripts on GitHub
While GitHub is full of "one-click" hardening scripts, I advise caution. Many scripts are outdated and may include ciphers that are now considered weak (like diffie-hellman-group1-sha1). When auditing a script, check for the sshd -t command. A professional hardening script will always validate the syntax of the generated configuration before restarting the service to prevent lockouts.
Developing a Custom SSH Hardening Script for Your Infrastructure
A custom script allows us to integrate local requirements, such as adding the corporate CA (Certificate Authority) for SSH Certificate-based authentication. We use certificates instead of static keys to provide time-bound access, which effectively mitigates the Lazarus threat. If a stolen certificate is only valid for 8 hours, the window for exploitation is minimal.
#!/bin/bashMinimalist SSH Hardening Script
set -e CONFIG_FILE="/etc/ssh/sshd_config" sed -i 's/^#\?PermitRootLogin./PermitRootLogin no/' $CONFIG_FILE sed -i 's/^#\?PasswordAuthentication./PasswordAuthentication no/' $CONFIG_FILE
Validate and restart
sshd -t systemctl restart ssh echo "SSH Hardening Applied Successfully."
Advanced SSH Configuration Best Practices
Changing Default Ports and Protocol Versions
Changing the default port from 22 to a random high port (e.g., 4422) is often dismissed as "security by obscurity." However, in practice, it reduces log noise by 99%. This allows our SOC (Security Operations Center) to focus on actual targeted attacks rather than the constant background radiation of botnet scans. We must ensure the new port is allowed in the security groups (AWS/Azure) and local firewall (ufw/iptables).
# Change port in sshd_configPort 4422
Update UFW
sudo ufw allow 4422/tcp sudo ufw delete allow 22/tcp
Restricting User Access and Implementing Idle Timeouts
We use the AllowUsers directive to whitelist specific individuals. This prevents an attacker from accessing the system even if they compromise a service account (like www-data) that shouldn't have SSH access. Additionally, implementing ClientAliveInterval ensures that idle sessions are terminated, preventing session hijacking of abandoned terminals.
# Only allow specific adminsAllowUsers ubuntu-admin sys-deployer
Terminate idle sessions after 5 minutes
ClientAliveInterval 300 ClientAliveCountMax 0
Integrating Multi-Factor Authentication (MFA)
MFA is the single most effective control against the Lazarus ClickFix campaign. Even if an attacker steals the SSH key and the passphrase, they cannot bypass the TOTP (Time-based One-Time Password) challenge. For more advanced threats, implementing SIEM rules for MFA proxy bypass can help detect sophisticated AiTM attacks. We use libpam-google-authenticator on our Ubuntu bastions. The configuration requires setting AuthenticationMethods publickey,keyboard-interactive in sshd_config.
sudo apt install libpam-google-authenticatorRun the setup for the user
google-authenticator
Update /etc/pam.d/sshd to include the MFA requirement. We must comment out the standard @include common-auth to prevent it from asking for a password in addition to the TOTP code if we only want Key + TOTP.
# /etc/pam.d/sshd
auth required pam_google_authenticator.so
Verification and Compliance: The SSH Hardening Test
How to Perform a Comprehensive SSH Hardening Test
After applying configurations, we must verify that the server is not offering weak algorithms. We use sshd -T to dump the effective configuration. This is crucial because sshd_config can have include directives that override your settings. I use this command to check the four most critical parameters:
sudo sshd -T | grep -E 'permitrootlogin|passwordauthentication|pubkeyauthentication|kexalgorithms'
The output should strictly show permitrootlogin no and passwordauthentication no. If it shows yes, there is a conflicting configuration file in /etc/ssh/sshd_config.d/.
Top Tools for Auditing SSH Security Configurations
We rely on ssh-audit for deep inspection of the crypto stack. It identifies weak key exchange methods and provides specific recommendations for hardening based on the OpenSSH version.
# Install and run ssh-audit
pip3 install ssh-audit ssh-audit
For network-level auditing, nmap with the ssh2-enum-algos script is invaluable for scanning large internal subnets to find non-compliant servers that might have been spun up by developers in "Shadow IT" projects.
$ nmap -p 22 --script ssh2-enum-algos 192.168.1.0/24
Maintaining Security Posture with Continuous Monitoring
Hardening is a point-in-time activity; continuous monitoring is required for compliance with the DPDP Act. We monitor /var/log/auth.log (on Ubuntu) for suspicious patterns. On macOS, where the Lazarus infection starts, we use log show to track SSH daemon activity and identify if any unauthorized keys were used to tunnel back into the machine.
log show --predicate 'process == "sshd"' --last 24h
In Indian enterprise environments, we integrate these logs into a centralized SIEM. Any instance of Accepted publickey for root should trigger an immediate P1 incident, as it indicates a violation of the hardening policy and a potential compromise.
To verify the physical location of .ssh folders across a fleet of macOS devices (to ensure developers aren't storing keys in insecure locations), we use this find command:
find /Users/ -name ".ssh" -exec ls -la {} \;
Next Command: To verify the exact version of the liblzma library and ensure you are not vulnerable to the CVE-2024-3094 backdoor, run strings $(which lzma) | grep 'xz' and check against the known malicious version strings (5.6.0 and 5.6.1).
