|
Overview Robert Grahamās release of Sidestep in early February 2001 identified basic Intrusion Detection System (IDS) evasion techniques in the BackOrifice application, DNS (Domain Name Service), FTP (File Transfer Protocol), HTTP (Hyper-Text Transfer Protocol), RPC (Remote Procedure Call), and SNMP (Simple Network Management Protocol). Sidestep demonstrates only one method of evading signature-based IDSes using the RPC protocol. This paper goes deeper into RPC to show how it operates, its inherent weaknesses in terms of network security, a full disclosure of all known evasion techniques, and solution sets to counter these weaknesses for both network-level security and IDS technology. We will present this information "in plain English" first - the technical details will be included in the Appendices. "" The key points of this discussion are:
What the RPC Protocol Does According to the Merriam-Webster Dictionary, a protocol is "a set of conventions governing the treatment and especially the formatting of data in an electronic communications system". Put simply, a protocol defines the rules a client must follow to communicate with a server (and vice-versa) for a particular type of network service offering. The chain of events for the RPC protocol begins in OSI Layer 5 (Session Layer) with the core code of the RPC communication conventions. At OSI Layer 6 (Presentation), XDR (eXternal Data Representation) encodes the input to and decodes output from the portmap/rpcbind server at OSI Layer 7 (Application). For the purposes of this paper, portmap and rpcbind are equivalent services with different names because they run on different versions of UNIX. They both run on TCP and UDP port 111 and/or 32771 through 32779. You can think of portmap/rpcbind as a phone book that RPC-based programs must use to talk with each other. The portmap (Linux, xBSD) / rpcbind (Solaris) serverās purpose is to act as a central registration facility for all other RPC-based services, such as NFS (Network File System) and NIS (Network Information System). When these services start up, they register the ports they will be listening on with portmap/rpcbind. When an RPC call comes in from another application or service, it must ask portmap/rpcbind for the port of the service it wants to talk with. When portmap/rpcbind returns this information to the caller, the caller will use it to begin direct communication with the service it was seeking. The evasion and attack techniques we will discuss target portmap/rpcbind. A Normal RPC Request-for-Information "Conversation" The rpcinfo utility is provided in UNIX for querying portmap/rpcbind for information it has about the RPC-based services registered with it. The -p option to rpcinfo asks portmap/rpcbind to return all of the information available about every service registered with it. rpcinfo -p is often used by hackers or system crackers to gather information about what RPC services are offered by a given host so that they can decide which, if any, RPC-based attack methods they have at the ready will apply to the targeted host. A normal rpcinfo -p command equates to the following English conversation: rpcinfo: "This is the last fragment of data I have to send you. The data fragment is 40 bytes long. I want to use this tracking number to keep our conversation synchronized. I am placing a call message. I am using RPC Version number 2. I need to speak to portmap/rpcbind and I expect its program version number to also be 2. I am asking portmap/rpcbind to give all the information it has about every registered service on the local host. I am not using any authentication or verification mechanism." portmap/rpcbind: "Because the data you are sending me represents the last fragment of data you have to send I can begin processing it. This is the last fragment of data I will be sending to you and it is 988 bytes in length. I acknowledge your conversation tracking number by sending it back to you. I am sending a reply message to your request. Because your input was formatted properly I am accepting your call message. Because you presented me no authentication or verification data, I wonāt use any, either. Your call message executed successfully. I have the information you requested. Each piece of information will be of different lengths. When I have completed sending you all of the information I have, I will tell you that there is no information left to send and our conversation will be concluded." A Sidestep RPC Request-for-Information "Conversation" The Sidestep program also performs an rpcinfo -p request, but by a different method that attempts to evade IDSes by changing the pattern of the conversation. Sidestep: "This is not the last fragment of data I have to send you. This data fragment is one byte long. Here is that data byte. I will repeat this message 39 more times" portmap/rpcbind: "Because the data you are sending me does not represent the last fragment of data you have to send, I will not be able to begin processing your request until you tell me that you have sent the last data fragment" Sidestep: ..this is the last data fragment. It is one byte long. Here is that byte. My message is complete." portmap/rpcbind: ..it took a little longer than usual, but I now have all of the data you sent me, so I can begin processing it. This is the last fragment of data I will be sending to you and it is 988 bytes in length. I acknowledge your conversation tracking number by sending it back to you. I am sending a reply message to your request. Because your input was formatted properly I am accepting your call message. Because you presented me no authentication or verification data, I wonāt use any, either. Your call message executed successfully. I have the information you requested. Each piece of information will be of different lengths. When I have completed sending you all of the information I have, I will tell you that there is no information left to send and our conversation will be concluded." Beyond Sidestep The conversation pattern used by Sidestep is static from one invocation to the next. That fact allows a signature-based IDS to identify its technique and generate an alert. Unfortunately, the static technique used by Sidestep is not the only one possible. Here is a variation on the evasion theme. Hacked-up RPC Client: "This is not the last fragment of data I have to send you. This data fragment is seven bytes long. Here are those bytes. This is not the last fragment of data I have to send you. This data fragment is three bytes long. Here are those bytes. This is not the last fragment of data I have to send you. This data fragment is five bytes long. Here are those bytes. This is not the last fragment of data I have to send you. This data fragment is nine bytes long. Here are those bytes. This is not the last fragment of data I have to send you. This data fragment is two bytes long. Here are those bytes. This is not the last fragment of data I have to send you. This data fragment is six bytes long. Here are those bytes. This is not the last fragment of data I have to send you. This data fragment is seven bytes long. Here are those bytes. This is the last data fragment. It is one byte long. Here is that byte. My message is complete." portmap/rpcbind: "Because the data you are sending me does not represent the last fragment of data you have to send, I will not be able to begin processing your request until you tell me that you have sent the last data fragment" portmap/rpcbind: ..it took a little longer than usual, but I now have all of the data you sent me, so I can begin processing it. This is the last fragment of data I will be sending to you and it is 988 bytes in length. I acknowledge your conversation tracking number by sending it back to you. I am sending a reply message to your request. Because your input was formatted properly I am accepting your call message. Because you presented me no authentication or verification data, I wonāt use any, either. Your call message executed successfully. I have the information you requested. Each piece of information will be of different lengths. When I have completed sending you all of the information I have, I will tell you that there is no information left to send and our conversation will be concluded." From the Sidestep conversation and a variant, it becomes clear that any conversation (evasion) pattern can be created, provided the following rules are followed:
The Toxic RPC Request-for-Information "Conversation" a.k.a. "Null-Byte Encoding" In the preceding discussions, we have always assumed a set of logical conditions for RPC fragment messages - that we were or were not sending the last fragment of data and that the data bytes had some length greater than zero. What happens when you set data length to zero? Hereās what that conversation looks like - think Jack Nicholson in The Shining ;-) Hacked-up RPC Client: "This is not the last fragment of data I have to send you. This data fragment is zero bytes long. This is not the last fragment of data I have to send you. This data fragment is zero bytes long. This is not the last fragment of data I have to send you. This data fragment is zero bytes long ... (Millions of such messages later) This is not the last fragment of data I have to send you. This data fragment is zero bytes long. This is not the last fragment of data I have to send you. This data fragment is zero bytes long. This is not the last fragment of data I have to send you. This data fragment is zero bytes long. This is not the last fragment of data I have to send you. This data fragment is zero bytes long.... (While this is happening, portmap/rpcbind is thinking ...) portmap/rpcbind: "I cannot do anything but wait until you notify me that the last data fragment has been sent. I cannot talk to anyone else until your conversation has been completed." The conversation constitutes a denial-of-service attack against both the remote portmap/rpcbind server and the IDS that is attempting to decode the conversation. In our experiments with "null-byte" conversations, we have found that portmap/rpcbind will deny connections to any other RPC-based application that needs its services while the toxic conversation is taking place. We have not found that portmap/rpcbind will crash, but we have not pushed the limits very hard. The largest single null-byte encoded stream we have tried came in at 400 million bytes. This attack denied service to or from portmap/rpcbind for about 10 minutes. If you think of this conversation as a module that can plug in to DDoS programs like TFN, Trin00, or Stacheldraht, youāll see that the null-byte technique quickly and easily scales out to a network-spanning DoS attack that could consume significant bandwidth. In single-host DoS and network DDoS cases, the IDSes attempting protocol decode on this technique are likely to be overwhelmed. Further, we have found that legitimate queries and evasions can be embedded in null-byte message streams. If the query or evasion is formed correctly, portmap/rpcbind will respond eventually. The embedding can be inserted as either a single "chunk", or it can be interspersed throughout the null encoded stream. That capability increases the number of possible evasions to infinity, for all practical purposes. Observations, Solutions, etc.
At most, Iād assess the risk of the vulnerabilities described in this paper as medium. There are too many good existing workarounds to warrant anything more alarmist. Block TCP and UDP ports 111 and 32771 through 32779 at the head-end and intranet-to-intranet, deploy Wietseās portmap/rpcbind replacement and youāll be in pretty good shape at the local level. That doesnāt help the long-haul networks much, but thereās (arguably) a lot of junk on the wire already masquerading as valid content. ;-) This attack is just another brick in the DoS/DDoS wall from the perspective of practical network security. For IDSes that employ strict protocol decoding, dealing with RPC protocol evasion techniques will be problematic. Null-byte streams could lead to resource starvation within the IDS itself. If a strict decode approach is pursued, we would expect the IDS to wait for a corresponding reply to the inbound query - and as we have demonstrated, that wait could be a long one. If numerous null-byte streams are sent simultaneously, the affected IDS will have numerous threads tied up in the decode process, hence the potential for resource starvation. Our results indicate that a modified protocol decode approach should be taken to avoid resource consumption. In essence, an IDS RPC decoder needs only to identify evasive fragmentation encoding techniques, flag that evasion attempt, and let its signature engine detect outbound replies to encoded queries. This modified decoding approach solves the resource-starvation problem, identifies evasion attempts, and detects query replies. "as through a glass, and darkly" Just some unanswered questions and other related thoughts:
Appendix A: Citation of Sources / List of References
|
