Skip to content

main: wipe SSH password/passphrase from environment memory#46

Open
acts-1631 wants to merge 1 commit into
upa:mainfrom
acts-1631:fix/ssh-password-env-leak
Open

main: wipe SSH password/passphrase from environment memory#46
acts-1631 wants to merge 1 commit into
upa:mainfrom
acts-1631:fix/ssh-password-env-leak

Conversation

@acts-1631

Copy link
Copy Markdown

mscp reads MSCP_SSH_AUTH_PASSWORD and MSCP_SSH_AUTH_PASSPHRASE with getenv() and keeps using that pointer for the life of the process. On Linux, /proc/PID/environ exposes the original environment block to any process running as the same user, so the secret stays readable there the whole time mscp is running.

Just calling unsetenv() doesn't fix this, I checked: /proc/PID/environ reflects the raw memory the kernel set up at exec time, not libc's environ[] array that unsetenv() updates. The fix has to overwrite the actual bytes.

This copies the value with strdup() and then memsets the original bytes to zero, plus calls unsetenv() for good measure. Scripts and CI that set these env vars keep working exactly the same; the only difference is the secret no longer lingers in /proc/PID/environ. Verified this end to end against a local sshd: mid-transfer, /proc//environ shows MSCP_SSH_AUTH_PASSPHRASE= with an empty value instead of the passphrase.

mscp read MSCP_SSH_AUTH_PASSWORD and MSCP_SSH_AUTH_PASSPHRASE via
getenv() and kept using the returned pointer for the process
lifetime. On Linux, /proc/PID/environ exposes the original exec-time
environment block to any local process running as the same uid, so
the secret remained readable there for as long as the mscp process
ran.

Note that unsetenv() alone does not fix this: /proc/PID/environ
reflects the raw memory the kernel copied at execve() time, not
libc's environ[] bookkeeping that unsetenv()/setenv() manipulate.
Verified experimentally: unsetenv() alone leaves the secret fully
visible in /proc/PID/environ, while memset()'ing the bytes returned
by getenv() actually clears it from that view.

Copy the secret to the heap with strdup() and memset() the original
environment bytes to zero. This keeps non-interactive usage (scripts,
CI pipelines) working exactly as before while removing the secret
from /proc/PID/environ for the remainder of the process's life.

Verified end-to-end against a local sshd: while a passphrase-gated
key-based transfer is in flight, /proc/<mscp-pid>/environ shows
MSCP_SSH_AUTH_PASSPHRASE= with an empty value instead of the
passphrase.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant