Hi, On Thu, Dec 23, 2021 at 09:17:45PM +0800, AiDai wrote: > # NULL Pointer Dereference in unsetcmd() at inetutils/telnet/commands.c:1227
Thanks for fuzzing GNU inetutils! > ## Description > > A NULL Pointer Dereference was discovered in unsetcmd() at > inetutils/telnet/commands.c:1227. The vulnerability causes a segmentation > fault and application crash. This happens when the "unset" command is used with a single space as argument, because the "Setlist" contains entries for empty lines that use a single space as key, but the setlist.handler is 0 and the setlist.charp is NULL: {" ", "", 0, NULL}, There are several (identical) such entries, but since the " " entry is matched exactly, isprefix() does not return an ambiguous match, but an exact match. The unsetcmd() function then interprets the "empty line" command and tries to find something to reset to the default. It does not find anything and thus follows the "else" branch, but this dereferences the NULL pointer in the last field of the " " Setlist entry. The poc file found through fuzzing is just one way to reach this code path, it can be reached by entering "u \ " at the telnet prompt as well: $ telnet/telnet telnet> u \ Segmentation fault (core dumped) The attached patch fixes this: $ telnet/telnet telnet> u \ ' ': invalid argument ('unset ?' for help). telnet> q The arguments to unsetcmd() are built using makeargv() which supports quoting with backslash (\), doublequote ("), and singlequote ('). (This quoting is more similar to Python string quoting than to Shell quoting.) I do not think that the makeargv() function can be changed to not allow providing a single space as an argument to a command without risking to lose valid functionality. Thus I'd say that all commands must be able to cope with unexpected arguments, as done for unsetcmd() in the attached patch. Thanks, Erik -- To a first approximation, we can say that accidents are almost always the result of incorrect estimates of the likelihood of one or more things. -- C. Michael Holloway, NASA
diff --git a/telnet/commands.c b/telnet/commands.c index 9e04944f..fab5dcf2 100644 --- a/telnet/commands.c +++ b/telnet/commands.c @@ -1222,6 +1222,12 @@ unsetcmd (int argc, char *argv[]) (*ct->handler) (0); printf ("%s reset to \"%s\".\n", ct->name, (char *) ct->charp); } + else if (!ct->charp) + { + fprintf (stderr, "'%s': invalid argument ('unset ?' for help).\n", + name); + return 0; + } else { *(ct->charp) = _POSIX_VDISABLE;