Talos Vulnerability Report

TALOS-2022-1680

Weston Embedded uC-FTPs Authentication authentication bypass vulnerability

May 10, 2023
CVE Number

CVE-2022-41985

SUMMARY

An authentication bypass vulnerability exists in the Authentication functionality of Weston Embedded uC-FTPs v 1.98.00. A specially crafted set of network packets can lead to authentication bypass and denial of service. An attacker can send a sequence of unauthenticated packets to trigger this vulnerability.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

Weston Embedded uC-FTPs v 1.98.00

PRODUCT URLS

uC-FTPs - https://weston-embedded.com/micrium/overview

CVSSv3 SCORE

8.6 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H

CWE

CWE-303 - Incorrect Implementation of Authentication Algorithm

DETAILS

uC-FTPs is Micrium’s FTP server. It is designed to be used on embedded systems running the µC/OS-II or µC/OS-III RTOS kernels. This FTP server implements part of the following RFCs: RFC 959, RFC 2389, Draft IETF.

When a FTP client connects to uC-FTPs and sends the USER command, this causes the internal state variable ftp_session.CtrlState to change from FTPs_STATE_LOGOUT to FTPs_STATE_GOTUSER. If the command following the USER command is any command whose context state within the FTPs_Cmd structure is DEF_OFF for the FTPs_STATE_GOTUSER state, the uC-FTPs will reply to the client indicating that there was a bad command sequence, but will proceed to set the internal state variable ftp_session.CtrlState to FTPs_STATE_LOGIN, bypassing the authentication function. Any following commands requiring authentication will be executed as if by an authenticated user. For commands that require the function BuildPath to be called, this sequence of packets will result in a DoS of the server, because the authentication callback function which was never called is responsible for setting the variables ftp_session->BasePath and ftp_session->RelPath.

Consider the following code snippet when the USER command is processed:

case FTP_CMD_USER:
            p_cmd_arg = FTPs_FindArg(&ftp_session->CtrlCmdArgs);
            if (*p_cmd_arg != (CPU_CHAR)0) {
                Str_Copy_N(ftp_session->User, p_cmd_arg, sizeof(ftp_session->User));
                ftp_session->CtrlState = FTPs_STATE_GOTUSER;
                FTPs_SendReply(ftp_session->CtrlSockID, FTP_REPLY_NEEDPASSWORD, (CPU_CHAR *)0);
            } else {
                FTPs_SendReply(ftp_session->CtrlSockID, FTP_REPLY_PARMSYNTAXERR, (CPU_CHAR *)0);
            }
            break

Next, if a command is not authorized with the state FTPs_STATE_GOTUSER, the internal state will be set to FTPs_STATE_LOGIN after responding with an error message to the client:

if (FTPs_Cmd[ftp_session.CtrlCmd].CmdCntxt[ftp_session.CtrlState] == DEF_OFF) {
            if (ftp_session.CtrlState == FTPs_STATE_LOGOUT) {
                FTPs_SendReply(ftp_session.CtrlSockID, FTP_REPLY_NOTLOGGEDIN, (CPU_CHAR *)0);
            } else {
                FTPs_SendReply(ftp_session.CtrlSockID, FTP_REPLY_CMDBADSEQUENCE, (CPU_CHAR *)0);
                ftp_session.CtrlState = FTPs_STATE_LOGIN;
            }
            continue;
        }

Crash Information

Thread 3 "app" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff759d700 (LWP 13533)]
__strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:65
65	../sysdeps/x86_64/multiarch/strlen-avx2.S: No such file or directory.
(gdb) i r
rax            0x20                32
rbx            0x7ffff7e18b13      140737352141587
rcx            0x1                 1
rdx            0x1                 1
rsi            0x7ffff759c738      140737343244088
rdi            0x1                 1
rbp            0x7ffff759c770      0x7ffff759c770
rsp            0x7ffff759c1f8      0x7ffff759c1f8
r8             0xffffffff          4294967295
r9             0x0                 0
r10            0x55555555f993      93824992278931
r11            0x1                 1
r12            0x7ffff759c790      140737343244176
r13            0x55555555f992      93824992278930
r14            0x7ffff759c910      140737343244560
r15            0x73                115
rip            0x7ffff7f2a6e5      0x7ffff7f2a6e5 <__strlen_avx2+21>
eflags         0x10287             [ CF PF SF IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
k0             0x0                 0
k1             0x0                 0
k2             0x0                 0
k3             0x0                 0
k4             0x0                 0
k5             0x0                 0
k6             0x0                 0
k7             0x0                 0
(gdb) bt
#0  __strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:65
#1  0x00007ffff7e1ad15 in __vfprintf_internal (s=s@entry=0x7ffff759c790, format=format@entry=0x55555555f992 "%s", 
    ap=ap@entry=0x7ffff759c910, mode_flags=mode_flags@entry=0) at vfprintf-internal.c:1688
#2  0x00007ffff7e2df9a in __vsnprintf_internal (string=0x55555556450a <Mem_Heap+810> "", maxlen=<optimized out>, 
    format=0x55555555f992 "%s", args=args@entry=0x7ffff759c910, mode_flags=mode_flags@entry=0) at vsnprintf.c:114
#3  0x00007ffff7e03df6 in __GI___snprintf (s=<optimized out>, maxlen=<optimized out>, format=<optimized out>)
    at snprintf.c:31
#4  0x0000555555557904 in FTPs_BuildPath (full_abs_path=0x5555555641e0 <Mem_Heap> "", full_abs_path_len=260, 
    full_rel_path=0x555555564300 <Mem_Heap+288> "", full_rel_path_len=260, 
    parent_abs_path=0x555555564405 <Mem_Heap+549> "", parent_abs_path_len=260, 
    cur_entry=0x55555556450a <Mem_Heap+810> "", cur_entry_len=260, base_path=0x7ffff759cbe4 "", 
    rel_path=0x7ffff759cce4 "", new_path=0x55555555f98e ".") at Source/ftp-s.c:1384
#5  0x000055555555886d in FTPs_ProcessCtrlCmd (ftp_session=0x7ffff759cb70) at Source/ftp-s.c:2052
#6  0x000055555555741f in FTPs_CtrlTask (p_arg=0x7ffff7d9dec0) at Source/ftp-s.c:1007
#7  0x00007ffff7f9c609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#8  0x00007ffff7ec1133 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb)

Mitigation

Modify the check in ftp-s.c to check that ftp_session.CtrlState != FTPs_STATE_LOGIN rather than the previous comparison, which was ftp_session.CtrlState == FTPs_STATE_LOGOUT. This change allows for proper handling of the FTPs_STATE_GOTUSER state.

TIMELINE

2022-12-13 - Vendor Disclosure
2023-02-24 - Vendor Patch Release
2023-05-10 - Public Release

Credit

Discovered by Kelly Leuschner of Cisco Talos.