|
Message-ID: <20171213192155.GA21805@localhost.localdomain> Date: Wed, 13 Dec 2017 11:21:55 -0800 From: Qualys Security Advisory <qsa@...lys.com> To: oss-security@...ts.openwall.com Subject: Bugs in iscsiuio Hi all, We took a quick look at iscsiuio (from the iscsi-initiator-utils), discovered several bugs, and sent a brief report of our findings to linux-distros (on Monday, December 11). It was then decided that we should send this report to oss-security on Wednesday, December 13: please see below. Notes: we did not have the time to draft a proper advisory, so this is rather raw material, but hopefully it will be useful and detailed enough; also, we did not fully investigate the exploitability (or unexploitability) of these issues; and this was by no means an exhaustive audit, so there may be more bugs to be found. Thank you very much! With best regards, -- the Qualys Security Advisory team ======================================================================== Source: iscsi-initiator-utils-6.2.0.874-6.git86e8892.fc27.src.rpm ------------------------------------------------------------------------ In iscsid_loop(), new connections are accepted on the abstract socket @ISCSID_UIP_ABSTRACT_NAMESPACE, but the source of the connection is not checked: any local user can connect and send messages, thus triggering the bugs below; this may or may not be the intended behavior. (iscsid for example processes only root's messages, in mgmt_ipc_handle()). ------------------------------------------------------------------------ In process_iscsid_broadcast(), payload_len is read directly from the user's message, without checks, and then used in an fread() to a fixed- size buffer: a straight heap overflow (arbitrary size, arbitrary bytes). This would probably be exploitable, but every distribution we checked compiles iscsiuio with FORTIFY, and __fread_chk() catches the heap overflow before it happens, and aborts: $ echo -e '\1\0\0\0\x41\x41\x41\x41' | socat - ABSTRACT-CONNECT:ISCSID_UIP_ABSTRACT_NAMESPACE Process 32442 (iscsiuio) of user 0 dumped core. Stack trace of thread 32445: #0 0x00007f15redacted raise (libc.so.6) #1 0x00007f15redacted abort (libc.so.6) #2 0x00007f15redacted __libc_message (libc.so.6) #3 0x00007f15redacted __fortify_fail (libc.so.6) #4 0x00007f15redacted __chk_fail (libc.so.6) #5 0x00007f15redacted __fread_chk (libc.so.6) #6 0x0000555dredacted process_iscsid_broadcast (iscsiuio) #7 0x0000555dredacted iscsid_loop (iscsiuio) #8 0x00007f15redacted start_thread (libpthread.so.0) #9 0x00007f15redacted __clone (libc.so.6) Stack trace of thread 32443: #0 0x00007f15redacted sigwait (libpthread.so.0) #1 0x0000555dredacted signal_handle_thread (iscsiuio) #2 0x00007f15redacted start_thread (libpthread.so.0) #3 0x00007f15redacted __clone (libc.so.6) Stack trace of thread 32442: #0 0x00007f15redacted socket (libc.so.6) #1 0x0000555dredacted nic_nl_open (iscsiuio) #2 0x0000555dredacted main (iscsiuio) #3 0x00007f15redacted __libc_start_main (libc.so.6) #4 0x0000555dredacted _start (iscsiuio) ------------------------------------------------------------------------ In process_iscsid_broadcast(), rsp is not initialized, and the ISCSID_UIP_IPC_GET_IFACE and default cases do not initialize its ping_sc member: because rsp is then sent back to the connected user, this may leak useful information to an attacker. ------------------------------------------------------------------------ At the end of process_iscsid_broadcast() there is an fclose(fd) where fd is fdopen(s2); but after the return, iscsid_loop() calls close(s2): this double-closes s2, which may not always be a problem, but here, iscsiuio is multi-threaded and it is theoretically possible that another thread recycles the file descriptor s2 after the fclose(fd) but before the close(s2), which would therefore close the wrong file. Note: at the beginning of process_iscsid_broadcast() there is a return that does not close s2; care must be taken with the double-close patch, or it may leak a file descriptor instead. ------------------------------------------------------------------------ At the beginning of decode_cidr(), where in_ipaddr_str is from the message sent by the user/attacker: char ipaddress[NI_MAXHOST]; the following code has two problems: char ipaddr_str[NI_MAXHOST]; ... if (strlen(in_ipaddr_str) > NI_MAXHOST) strncpy(ipaddr_str, in_ipaddr_str, NI_MAXHOST); else strcpy(ipaddr_str, in_ipaddr_str); 1/ strlen(in_ipaddr_str) > NI_MAXHOST is possible, because the user's ipaddress is not necessarily null-terminated, but in that case strncpy() does not null-terminate ipaddr_str; Note: other "strings" in the message sent by the user/attacker also suffer from this (non) null-termination problem. 2/ if strlen(in_ipaddr_str) == NI_MAXHOST, the strcpy() triggers an off-by-one overflow. Note: this strncpy()/strcpy() pattern of bugs is repeated many times throughout the codebase. ------------------------------------------------------------------------ In decode_cidr(), the strcpy(ipaddr_str, tok) is invalid, because tok points to ipaddr_str, and "strings may not overlap" (man strcpy). ------------------------------------------------------------------------ In decode_cidr(), int keepbits = atoi(tmp) may be negative (it comes from the message sent by the user/attacker), which may bypass checks and have other consequences in other parts of the code. ------------------------------------------------------------------------ In perform_ping(), int datalen comes from the message sent by the user/attacker, but it is not checked at all: it looks like this could lead to a heap overflow in fill_payload_data() (through do_ping_from_nic_iface() -> prepare_icmpv6_req_pkt()). (It seems that packet buffers are malloc()ated by alloc_packet(), called only with alloc_packet(1500, 1500), and uip_slen in fill_payload_data() is an u16_t, originally from the attacker-controlled int datalen, so it may very well overflow this 1500-byte buffer -- but we did not double- check this conclusion, and the lack of datalen checks may have other consequences as well, but we did not explore them fully.) ========================================================================
Powered by blists - more mailing lists
Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.