Exploit Microsoft Windows NT 4.0/2000 Predictable LPC Message Identifier - Multiple Vulnerabilities


18 Дек 2022
Проверка EDB
  1. Пройдено
Тип уязвимости
Дата публикации
source: https://www.securityfocus.com/bid/1748/info

LPC (Local Procedure Call) is a message-passing service that allows threads and processes to communicate with each other on a local machine as opposed to RPC (Remote Procedure Call) that takes place between different hosts.

The structure of a message is as follows (taken from the Bindview Security Advisory under the 'Credit' tab):

typedef struct lpc_msg {
unsigned short data_len;
unsigned short msg_len; /* normally data_len + sizeof (struct lpc_msg) */
unsigned short msg_type;
unsigned short address_range_offset;
unsigned long pid; /* process id of client */
unsigned long tid; /* thread id of client */
unsigned long mid; /* message id for this message */
unsigned long callback_id; /* callback id for this message */
/* unsigned char buff[0]; data_len bytes of data for this message */

The underlying problem exists in the way NT's LPC ports implementation verifies the original source of the message. When a client attempts to connect to the server, the server will receive a new handle from NtAcceptConnectPort. Although, the server will not use the handle and will use the original handle it had received from the NtCreatePort call. It will utilize the PID (Process Identifier), TID (Thread Identifier), and MID (Message Identifier) as illustrated above. The MID of a LPC message is predictable and any process that knows the MID can use it. This opens up the possibility of a number of exploits such as Denial of Service, Session Hijacking, Eavesdropping, and Privilege Escalation.

Vulnerability #1: This vulnerability only affects Windows NT 4.0 and not 2000. Hijacking of port connections is made possible because any process can call NtAcceptConnectPort. The NtAcceptConnectPort API only requires LPC_MSG and PID, TID, and MID rather than an existing port handle. If all three identifiers are specified for an existing connection request, then the process is given a handle to that particular port. Process requests from that client can now take place.

Vulnerability #2: It is possible to transmit data between LPC clients and servers through NtReadRequestData and NtWriteRequestData. These two functions allow servers to read and write to client address space specified by the client. An example of the client structure is as follows:

struct addr_ranges {
unsigned long num_entries;
struct addr_entry {
void *addr;
size_t len;
} addrs[N]; /* where N is num_entries */

This structure would be inserted into the data portion of the client message and the address_range_offset of the LPC_MSG would be set to the offset of the structure. The server can then read or write to the specified address ranges with NtReadRequestData and NtWriteRequestData. However, a client of a port can utilize one of these calls as a server and access portions of memory from another client, given that the other client is utilizing address_range_offset and that the original client can provide the correct PID, TID, and MID.

Vulnerability #3: By making a large number of LPC requests using the address_range_offset feature, it is possible to use up all available MIDs in the system (2^32). When this happens, the server will 'wrap' and assign outstanding requests a MID belonging to an existing request. In this manner it is possible for one client to cause the server to send an innapropriate reply to another client.

These vulnerabilities can only be launched against a machine a user can interactively log onto, therefore remote exploitation is not possible.

Vulnerability #1:

start porttool -s \BaseNamedObjects\Foo
start porttool -c \BaseNamedObjects\Foo
porttool -s1
(enter PID, TID, and MID printed by porttool -s)

Vulnerability #2:

start porttool -s5a \BaseNamedObjects\Foo
start porttool -c5a-1 \BaseNamedObjects\Foo
porttool -c5a-2 \BaseNamedObjects\Foo
(enter PID, TID, MID, CID from porttool -s5)

Vulnerability #3:

start porttool -s5b \BaseNamedObjects\Foo
start porttool -s5b-2 \BaseNamedObjects\Foo2
porttool -c5b \BaseNamedObjects\Foo \BaseNamedObjects\Foo2
(wait until MIDs wrap around)

start porttool -s \BaseNamedObjects\Foo3
porttool -c \BaseNamedObjects\Foo3

(in window for porttool -s5b)
Enter PID, TID, MID, CID from porttool -s 


Похожие темы