Yaamlabs

Threat intel

SysGoRAT: Linux spies stole sudo passwords with an alias

Unit 42's CL-UNK-1211 hit government Linux servers with PHP web shells, a Go RAT and a fake sudo prompt. How it worked and the exact checks to run.

Palo Alto Networks Unit 42 published a report on October 15, 2026 about an espionage cluster it tracks as CL-UNK-1211. From October 2025 to April 2026 the group broke into Linux web, mail and database servers belonging to government entities and state-affiliated infrastructure. It got in through PHP web shells, controlled hosts with a custom Go remote access trojan (RAT) called SysGoRAT, and went after mailboxes and databases. The "UNK" in the name means Unit 42 has not decided whether the operators work for a state or for profit.

If you run Linux servers with PHP applications, Plesk or qmail, the techniques here apply to you whether or not you work in government. The detail most worth copying into your own hunting is how the group took sudo passwords: an alias in .bashrc that showed a fake prompt, logged the password, then ran the real command so nothing looked wrong.

How it works

The web shell foothold. Besides dropping custom and open-source PHP web shells, the attackers edited the auto_prepend_file setting in PHP configuration under /etc/php/ and /opt/plesk/php/. That directive tells PHP to run a named file before every script it serves. Pointing it at a web shell, in the reported case /usr/lib/php/plesk_sys_driver.php, means every page request on the site also runs attacker code, and deleting the visible shell from the web root does not remove the foothold.

The sudo alias. The group replaced users' .bashrc files with copies that defined an alias for sudo. Bash expands aliases before it looks for a program, so typing sudo ran the attacker's code instead of /usr/bin/sudo. That code printed a prompt that imitated the real one, captured what the admin typed, wrote it to a file named Solarwinds.StatusLog.txt, then passed the password to the real sudo. The command succeeded, so the admin had no reason to look twice. Unit 42 found no evidence that SolarWinds products were compromised; the name was cover.

The sudo binary itself is never touched, which is why file integrity monitoring on /usr/bin/sudo would miss this. The sudo log records an ordinary successful session. The only changed file is a shell startup script, and few teams monitor .bashrc, .bash_aliases or /etc/profile.d/ the way they monitor binaries.

SysGoRAT. The RAT is written in Go and runs on Linux and Windows. It talks to its controller over WebSocket, with a hard-coded default of 104.194.158.65 on port 443. Its seven command types cover running shell commands, an interactive shell, directory listing and three proxy commands that let the operator tunnel TCP connections through the infected host. A control command adds four sub-actions: start a shell, take a screenshot, download a file and install persistence. Unit 42 counts six persistence methods across both systems; on Linux they include a systemd service and a cron job that runs every five minutes. The sample was first seen under the file name sys-control-client.

What the attackers did

After the web shell, the group harvested credentials three ways: a logger injected into a PHP login page to catch admin usernames and passwords, searches of configuration files and shell history for cleartext mail, SMTP and database passwords, and the sudo alias. It added its own SSH key to authorized_keys as a further way back in. Unit 42 counted at least seven command and control servers used for reverse shells, three of them reached through netcat with a named pipe, others through Bash TCP redirects and Python.

The targets were mail and data. The operators enumerated /var/qmail/mailnames/, and a script called search_social.php searched mail headers for social media messages, showing the sender, recipient, subject and file path of each. A script meant to zip whole mailboxes, zip_mails.sh, had syntax errors and would have failed. On databases they first pulled up to 100 rows from each of four tables into a local SQLite file, then tried full dumps.

They also cleaned up: deleting logs, changing file timestamps, running scripts once and removing them, and planting fake red-team markers so the intrusion might pass for a penetration test. Attempts to kill Cortex XDR processes were detected and blocked, according to Unit 42.

Unit 42 also found scripts full of conversational, step-by-step comments addressed to an operator. Its reading is that the code was either copied from a large language model's output or deployed by an automated AI agent. That is an assessment from coding patterns. Unit 42 did not confirm an autonomous agent ran the intrusion.

What to do

There is no patch here; the entry was through web applications, and the rest is abuse of normal Linux features. On any Linux server that serves PHP or holds mail or databases:

  1. Check PHP for a prepend file. Run grep -rn auto_prepend_file /etc/php /opt/plesk/php and confirm every non-empty value is one you set. Also run php -i | grep auto_prepend_file for each PHP version in use, since the effective value can come from another file. Look for /usr/lib/php/plesk_sys_driver.php and any other PHP file outside a package's file list in that directory (dpkg -S or rpm -qf on it says whether a package owns it).
  2. Check every shell startup file for a sudo alias. Run grep -n "alias sudo" /root/.bashrc /home/*/.bashrc /root/.bash_aliases /home/*/.bash_aliases /etc/bash.bashrc /etc/profile.d/*.sh. In a live session, type sudo should print a path such as sudo is /usr/bin/sudo, not an alias. Search for the log with find / -name 'Solarwinds.StatusLog.txt' 2>/dev/null. Until you have checked, typing \sudo skips any alias.
  3. Check persistence. Review /etc/systemd/system/ for unit files you did not create (ls -lt shows recent ones), run crontab -l -u for each account in /etc/passwd, and read every authorized_keys file for keys you cannot account for.
  4. Check the network. Run ss -tnp | grep 104.194.158.65 and search firewall and proxy logs for that address. Unit 42's report lists the full set of IP addresses, domains and file hashes; load them into your blocklists and EDR. Web and database servers rarely need to start outbound connections, so a default-deny egress rule on them breaks reverse shells and WebSocket control channels.
  5. Watch the files this group changed. auditd watch rules make edits visible: -w /etc/php/ -p wa -k php_conf, -w /opt/plesk/php/ -p wa -k php_conf, -w /root/.bashrc -p wa -k shell_rc (plus one rule per admin's .bashrc, since watches do not take wildcards), -w /etc/systemd/system/ -p wa -k systemd_units and -w /var/spool/cron/ -p wa -k cron. Query them with ausearch -k shell_rc. Forward audit and auth logs to a separate system, because this group deletes local logs.

If you find any of this, treat the host as compromised. Every sudo password typed on it since the .bashrc change is stolen, along with any password stored in configuration files or shell history on that host. Rotate them from a clean machine, since a new password typed into the same prompt goes straight to the log. Then rebuild the server rather than cleaning it, given the timestamp tampering, and review the mail accounts and databases it could reach.

Our security operations team hunts for this kind of persistence on Linux estates, and our safeguarding and hardening work sets up egress rules, audit rules and log forwarding so changes like these are caught. Open the chat and Yaali, our AI agent, will pass your question to an engineer.


Sources: Unit 42: CL-UNK-1211 report, The Hacker News, Gridinsoft, Neoteo, SecNews.

Back to the blog, or read this post on the full site.