Introduction

The log-user-session is intended to provide tamper-proof logging of SSH commands. Therefore it has to be installed as SUID-executable to write one logfile per session to a trusted location. It is invoked by acting as an login shell for each user and intercepts all shell traffic for auditing purposes.

Problem description:

The program uses the SSH_CLIENT environment variable, usually set by the SSH server to extract the remote host name and use it to derive the name of the logfile. An unprivileged user may invoke log-user-session with a crafted environment variable to create files at arbitrary locations with user-supplied content.

Vulnerable code from log-user-session.c (3b535f4a3ccbb9f9908afe6fbf70fe63dacb8f11):

# Environment variable is split copied without sanitation: void process_options(int argc, char **argv) { ... /* client host */ char *ssh_client = getenv("SSH_CLIENT"); if (ssh_client && 0 != strcmp("(null)",ssh_client)) { int i; for (i = 0; ssh_client[i] && !isspace(ssh_client[i]); i++); opt_client = strndup(ssh_client, i); # The unsanitized opt_client name is appended to the logfile name string: char *prepare_log_file_name(const char *template) { ... /* add client host */ else if ('c' == *pos_t) { if (opt_client) { int r = snprintf(pos_l, remaining, "%s", opt_client); if (r >= remaining) break; while('\0' != *pos_l) pos_l++; } ... opt_logfile = prepare_log_file_name(DEFAULT_LOG_FILE); # ... and used to create directories, open the file. The later # is done without using O_EXCL or O_NOFOLLOW. int prepare_log_file(const char *log_file, const char *original_command) { char* dir = dirname(strdup(log_file)); print_config_file_warning(CONFIG_FILE, dir); prepare_dir(dir); free(dir); int fd_log = open(log_file, O_WRONLY|O_APPEND|O_CREAT, S_IRUSR);

All versions up to 0.7 are vulnerable.

Methods

The tool LogMore demonstrates various escalation approaches, depending on the hardening state of the machine. Escalation will work immediately on systems without symlink protection, libc missing __libc_enable_secure, unprivileged USERNS clone and will always work after initramfs update and reboot.

Results, Discussion

Timeline

Material, References

Last modified 20181220
Contact e-mail: me (%) halfdog.net