Skip to content

Use execle instead of popen in tacas nss to avoid shell escape exploits #15284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 5, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
From 9e46c167abeb461456b0c432d6a75559013a79ce Mon Sep 17 00:00:00 2001
From: Eric Seifert <[email protected]>
Date: Wed, 31 May 2023 09:08:07 -0700
Subject: [PATCH] Replace popen shell execution with safer execle

---
nss_tacplus.c | 65 +++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 53 insertions(+), 12 deletions(-)

diff --git a/nss_tacplus.c b/nss_tacplus.c
index cd73870..8db8f58 100644
--- a/nss_tacplus.c
+++ b/nss_tacplus.c
@@ -34,6 +34,9 @@
#include <netdb.h>
#include <nss.h>
#include <limits.h>
+#include <unistd.h>
+#include <sys/wait.h>
+

#include <libtac/libtac.h>

@@ -439,6 +442,39 @@ static int delete_conf_line(const char *name)
return 0;
}

+int user_mod_add(const char* cmd, const char* name, char* gid, char* sec_grp, char* gecos, char* home, char* shell) {
+
+ pid_t pid;
+ int wstatus;
+
+ pid = fork();
+
+ if(pid > 0) {
+ do {
+ if (waitpid(pid, &wstatus, WUNTRACED | WCONTINUED) == -1) {
+ int errsv = errno;
+ char serr[256] = {0};
+ strerror_r(errsv, serr, 256);
+ syslog(LOG_ERR, "%s: exec of %s failed with error %d: %s", nssname, cmd, errsv, serr);
+ return -1;
+ }
+ } while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
+ if WIFEXITED(wstatus)
+ return WEXITSTATUS(wstatus);
+ else
+ return -1;
+ // Child
+ } else if(pid == 0) {
+ execl(cmd, cmd, "-G", sec_grp, name, "-g", gid, "-c", gecos, "-d", home, "-m", "-s", shell, NULL);
+ syslog(LOG_ERR, "%s: exec of %s failed!", nssname, cmd);
+ exit(EXIT_FAILURE);
+ // Error
+ } else {
+ syslog(LOG_ERR, "%s: error forking the child\n", nssname);
+ return -1;
+ }
+}
+
/*
* If not found in local, look up in tacacs user conf. If user name is not in
* conf, it will be written in conf and created by command 'useradd'. When
@@ -454,6 +490,11 @@ static int create_or_modify_local_user(const char *name, int level, bool existin
bool found = false;
const char* command = existing_user ? "/usr/sbin/usermod": "/usr/sbin/useradd";

+ if(strlen(name) > 32) {
+ syslog(LOG_ERR, "%s: Username too long", nssname);
+ return -1;
+ }
+
fp = fopen(user_conf, "ab+");
if(!fp) {
syslog(LOG_ERR, "%s: %s fopen failed", nssname, user_conf);
@@ -495,18 +536,18 @@ static int create_or_modify_local_user(const char *name, int level, bool existin
while(lvl >= MIN_TACACS_USER_PRIV) {
user = &useradd_grp_list[lvl];
if(user->info && user->secondary_grp && user->shell) {
- snprintf(buf, len, "%s -G %s \"%s\" -g %d -c \"%s\" -d /home/%s -m -s %s",
- command, user->secondary_grp, name, user->gid, user->info, name, user->shell);
- if(debug) syslog(LOG_DEBUG, "%s", buf);
- fp = popen(buf, "r");
- if(!fp || -1 == pclose(fp)) {
- syslog(LOG_ERR, "%s: %s popen failed errno=%d %s",
- nssname, command, errno, strerror(errno));
- delete_conf_line(name);
- return -1;
- }
- if(debug)
- syslog(LOG_DEBUG, "%s: %s %s success", nssname, command, name);
+ char sgid[10] = {0};
+ char home[64] = {0};
+ snprintf(sgid, 10, "%d", user->gid);
+ snprintf(home, 63, "/home/%s", name);
+ if(0 != user_mod_add(command, name, sgid, user->secondary_grp, user->info, home, user->shell)) {
+ if(debug)
+ syslog(LOG_ERR, "%s: %s %s failed", nssname, command, name);
+ delete_conf_line(name);
+ return -1;
+ }
+
+
delete_conf_line(name);
return 0;
}
--
2.39.3

1 change: 1 addition & 0 deletions src/tacacs/nss/patch/series
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
0008-do-not-create-or-modify-local-user-if-there-is-no-pr.patch
0009-fix-compile-error-strncpy.patch
0010-Send-remote-address-in-TACACS-authorization-message.patch
0011-Replace-popen-shell-execution-with-safer-execle.patch