Some back ground on DCE RPC:
RPC (Remote Procedure Call) mechanism is used for distributed computing. Developers of applications on RPC mechanism need not worry about the underlying transport system. They only need to define the application methods, arguments and return values. RPC mechanism takes care of every thing else such as transporting the method and arguments to the server in the remote system and giving back the results to application after receiving results from the remote system. RPC Server also need not worry about transporting the results after executing the method.
Predominantly there are two RPC systems that became popular. Conceptually both are similar, but underlying implementation is different. Hence they are not interoperable.
ONE/RPC : Also called SUN RPC. It is specified in RFC 5531.
DCE RPC : Distributed Computing Environment / Remote Procedure Call - This is adopted by Microsoft and hence is also called as MS RPC. There is no RFC specifying this specifications. But open group published kind of specification. You can find it here.
Protocol information on DCE RPC:
DCE RPC transport can be TCP based (Connection Oriented), UDP (Connection Less) and on SMB (CIFS). Any IDS/IPS device detecting attacks on DCE-RPC based applications need to look deep in the packets coming from any of the transport. Though many protocol messages are same across TCP and UDP transports, protocol data is different between them.
IDS/IPS devices need to worry about following PDUs: BIND (Type 11), BIND_ACK (Type 12), ALTER_CONTEXT (14), ALTER_CONTEXT_RESP (15) , REQUEST (Type 0) and RESPONSE (Type 2) PDUs.
Each DCE RPC application (Client & Server) is identified by UUID (of 16 bytes). Client machines when it makes the connection to the Server machine, it indicates the applications it is interested in communicating by sending UUIDs of the applications in BIND and ALTER_CONTEXT PDUs. Note that, client machine may not know all UUIDs at one time. It may come to know during run time. What it means is that the UUIDs need not be sent at one time. They can be sent any time during the RPC connection. BIND-ACK, ALTER_CONTEXT_RESPONSE return the context IDs for each UUID. These context IDs are used by client application and server application to execute methods (and correspond arguments and return values) on the servers. Client application send method (identified by context ID, opnum) and its arguments to the Server application via REQUEST PDU. Server application, once it executes the methods, it sends the results via RESPONSE PDU.
Each PDU has RPC header as shown below. (Copied from open group specification)
u_int8 rpc_vers = 5; /* 00:01 RPC version */ u_int8 rpc_vers_minor; /* 01:01 minor version */ u_int8 PTYPE = bind; /* 02:01 bind PDU */ u_int8 pfc_flags; /* 03:01 flags */ byte packed_drep[4]; /* 04:04 NDR data rep format label*/ u_int16 frag_length; /* 08:02 total length of fragment */ u_int16 auth_length; /* 10:02 length of auth_value */ u_int32 call_id; /* 12:04 call identifier */BIND specific data:
u_int16 max_xmit_frag; /* 16:02 max transmit frag size, bytes */ u_int16 max_recv_frag; /* 18:02 max receive frag size, bytes */ u_int32 assoc_group_id; /* 20:04 incarnation of client-server * assoc group */ /* presentation context list */ p_cont_list_t p_context_elem; /* variable size */ /* optional authentication verifier */ /* following fields present iff auth_length != 0 */ auth_verifier_co_t auth_verifier;
p_cont_list_t :
typedef struct { u_int8 n_context_elem; /* number of items */ u_int8 reserved; /* alignment pad, m.b.z. */ u_short reserved2; /* alignment pad, m.b.z. */ p_cont_elem_t [size_is(n_cont_elem)] p_cont_elem[]; } p_cont_list_t;
- typedef struct {
- p_context_id_t p_cont_id;
- u_int8 n_transfer_syn; /* number of items */
- u_int8 reserved; /* alignment pad, m.b.z. */
- p_syntax_id_t abstract_syntax; /* transfer syntax list */
- p_syntax_id_t [size_is(n_transfer_syn)] transfer_syntaxes[];
- } p_cont_elem_t;
- typedef u_int16 p_context_id_t;
- typedef struct {
- uuid_t if_uuid;
- u_int32 if_version;
- } p_syntax_id_t;
Some important points to note are:
- Multiple UUIDs can be bound using one BIND PDU. n_context_elem gives the number of UUIDs that are being requested.
- Normally n_transfer_syn is 1, but it can be more than 1. It provides the transfer encoding of the UUID in multiple forms.
- BIND_ACK will provide context IDs for each UUID of the BIND PDU.
- If there are more UUIDs need to be bound at later time, they can be bound using ALTER_CONTEXT PDUs.
- Context IDs of new UUIDs are given by Server machine using ALTER_CONTEXT response PDU.
- DCE-RPC protocol itself has fragmentation supported. This is beyond the IP layer fragmentation. pfc_flags bit 0 and bit 1 tells the receiving implementation on whether it is FIRST fragmentation or LAST fragmentation. If both bits are 0, then it is MIDDLE fragment.
- Pipe lining: DCE RPC allows multiple requests in transit. That is, DCE RPC can send multiple REQUESTS before getting the RESPONSE messages. My understanding is that these multiple requests in transit belong to different contexts. For a given context, only one REQUEST would be pending. When pipelining is combined with fragmentation, it is possible that the fragments belonging to REQUEST messages (or RESPONSE messages) can go in any order. That is, on the wire you can see frag1 of REQUEST 1, frag 1 of REQUEST2, frag2 of REQUEST1 and frag2 of REQUEST2 or any order.
- IDS/IPS devices typically look in the stub data for a specific pattern. Stub data is specific to each application and method number. So, any protection signature that searches for the content in the stub data should have other keywords such as UUID, method number. Unfortunately UUID is not present along with method and stub data. That is UUID is not present in REQUEST PDU or RESPONSE PDU. REQUEST and RESPONSE PDUs only have Context ID. Hence IDS/IPS device need to maintain the UUID versus context ID mapping by interpreting BIND (Alter_Context) and BIND-ACK (Alter-Context-Resp) PDUs for each TCP or UDP connection. This mapping information needs to be used when the signatures are analyzed as part of attack detection on methods and its stub data processing. Note that, these mappings should be maintained on per connection basis. Across the connections, for same UUID, there could be different context ID value. IDS/IPS devices might be evaded by sending large number of UUIDs in the BIND/Alter-Context PDUs to overwhelm the mapping table. There is no easy solution here, but IDS/IPS devices should have ability to generate log when this happens. It is also good to have some kind of configuration/anomaly-signature to control this behavior.
- In some IDS/IPS devices, interpretation of UUIDs goes wrong if there are more than one transfer encoding of UUID, that is, if 'n_transfer_syn' is more than one. It is necessary to skip right amount of transfer encoded data to go to the next UUID in the BIND/Alter-Context PDUs.
- Some IDS/IPS devices fail to detect attacks when PDUs are fragmented. It is necessary that IDS/IPS devices interpret the data across multiple fragments. It is required to build UUID-to-context ID mapping table or to analyze the stub data of REQUEST and RESPONSE PDUs.
- Some IDS/IPS devices also fail when there is pipelining of REQUEST ( orRESPONSE PDUs). IDS/IPS devices while reassembling the fragmented PDU must ensure to reassemble right fragments by comparing not only checking the fragment flags, but also the type of message and context ID in case of REQUEST/RESPONSE messages.
- Some IDS/IPS devices also fail when the stub data is sent in a different form. Stub data can be encoded in little endian form and big endian form. IPS devices need to ensure to check the stub data based on the format. 'packed_drep' field in the header indicates the format used.
No comments:
Post a Comment