Unix Shell Configuration Modification (MITRE ATT&CK T1546.004) is a persistence and privilege escalation technique on Linux and macOS. Shells read configuration scripts at set points in a session. If an adversary adds a command to one of them, the command runs whenever that point is reached.
Anyone who has ever added an alias to a dotfile already knows how this works. The same convenience makes it a favorite hiding place.
How attackers use it
A login shell starts when a user opens a command line interface or logs in remotely, for example over SSH. It runs scripts from the system (/etc) and from the user's home directory (~/) to set up the environment. Those scripts usually set environment variables, create aliases and customize the session. They run at the permission level of their directory. When the shell exits, further scripts run to wrap up.
On Linux with bash, MITRE gives these examples:
/etc/profileand files in/etc/profile.drun each time any shell on the system launches. They typically need root to change.~/.bash_profile,~/.bash_loginand~/.profileare sourced when a user opens a command line or connects remotely. The system runs only the first one that exists, in that order, so adversaries have used~/.bash_profileto be sure theirs runs.~/.bashrcalso runs if the connection is remote or another interactive shell starts, such as a new terminal tab.~/.bash_logoutruns when a session ends. Some malware uses it to trigger on termination.
On macOS the idea is the same, but the default shell since macOS 10.15 is zsh. Terminal.app starts a zsh login shell and a zsh interactive shell. The login shell uses /etc/profile, /etc/zshenv, /etc/zprofile and /etc/zlogin, then ~/.zprofile and ~/.zlogin. The interactive shell uses ~/.zshrc. On exit, /etc/zlogout and ~/.zlogout run. For legacy programs, macOS runs /etc/bashrc on startup.
System files give a persistence that hits every user. User files give persistence at user level only, with no root needed.
How to detect it
MITRE's strategy has a Linux analytic and a macOS analytic:
- Linux. Modifications to shell startup and logout scripts such as
~/.bashrc,~/.bash_profileor/etc/profile, followed by odd process execution or network connections when a shell starts interactively or remotely. - macOS. Changes to zsh files such as
~/.zshrc,~/.zloginand/etc/zprofile, followed by unauthorized binaries or unexpected network traffic when Terminal.app opens.
An auditd watch on the files catches the write, in a rules file:
-w /etc/profile -p wa -k shell_profile
-w /etc/profile.d/ -p wa -k shell_profile
-w /root/.bashrc -p wa -k shell_profile
Watching home directories for every user is noisier, so many teams cover privileged accounts and service accounts first.
How to reduce the risk
MITRE lists one mitigation. Make these files immutable and changeable only by certain administrators. That limits how easily an adversary can set up user level persistence.
On shared servers, you can also keep configuration under central management, so the correct contents of a profile are known and drift is easy to spot.
Check your own environment
Read-only commands, Linux and macOS:
ls -la /etc/profile /etc/profile.d/ ~/.bash_profile ~/.bash_login ~/.profile ~/.bashrc ~/.bash_logout ~/.zprofile ~/.zshrc ~/.zlogin ~/.zlogout 2>/dev/null
grep -nE 'curl|wget|nc |base64|/tmp/|/dev/shm' /etc/profile /etc/profile.d/* ~/.bash_profile ~/.bashrc ~/.profile ~/.zshrc 2>/dev/null
The first shows which files exist and when they changed. The second searches for patterns that rarely belong in a shell startup file, such as downloaders and encoded strings. Neither command changes anything.
Then a short list:
- Do any startup files have modification times that do not match your last change window?
- Does any line start a program in the background?
- Does any line reach out to the network?
- For macOS, have you looked at zsh files as well as bash files?
Quick check
Why do adversaries pick ~/.bash_profile on Linux?
The system executes only the first existing file among .bash_profile, .bash_login and .profile, so using .bash_profile makes sure the commands run.
Which shell does macOS use by default on 10.15 and later?
zsh, so its files such as .zprofile, .zshrc and .zlogin are the ones to watch.