GoPhish at scale
In my previous life as a billable cybersec consultant / technical lead, I was looking for a way to deliver phishing tests across our customers in a consistent and repeatable manner. Many options existed such as those supplied by KnowBe4, Defender for M365, Trend - but we couldn’t warrant the cost burden of those solutions until we’d proven the value of the service.
I set about finding a way to do this “on the cheap”.
GoPhish is an OSS “Phishing Toolkit” which provides facilities for creating, running, and reporting on phishing campaigns. You can read more about GoPhish and what it can do here. GoPhish was absolutely what I needed to move forward with running some phishing tests on our customers, but provisioning and configuring it was clunky and took time. GoPhish wasn’t designed with multiple target organisations in mind either.
If it doesn’t exist, build it.
I set about building GoPhish in a way that could:
- Be spun up quickly, then spun down when the campaign was complete (saving cloud platform costs)
- Isolate customer data into a single instance and prevent cross-contamination
- Securely deliver landing pages with TLS
- Send emails securely and with the greatest chance of bypassing filters (saves time on adjusting filters)
- Allow for creativity with email/landing page domain names
Azure was the platform of choice for this work, not for any other reason than we had free credits available and I intended to use them.
ThrowPhish
I built a bash script and some Terraform code to accomplish what I had in mind. The aim of ThrowPhish is to enable rapid deployment of a GoPhish instance in Azure, along with all the bits and pieces required for it to work.
ThrowPhish will:
- Build a linux virtual machine
- Install GoPhish, configure it, and install it as a service
- Apply a public IP to the VM
- Create an Azure DNS zone for a supplied domain name
- Obtain a Let’s Encrypt free SSL certificate and install it on the VM
It’ll also firewall the VM to allow:
- Public access over HTTP/HTTPS (for the landing page)
- Access to SSH and the GoPhish admin port (TCP 3333) from your current public IP
Once you’re done with a phishing campaign, you can simply run throwphish again with the destroy
parameter to tear down all resources provisioned for a customer.
Preparing ThrowPhish
You can grab throwphish from the GitHub repository with the following command.
git clone https://github.com/nmanzi/throwphish.git
Prerequisites
You can run ThrowPhish on Windows (with WSL) or Linux.
You’ll need to install Azure CLI and run az login
to get things ready for Terraform. ThrowPhish will take care of downloading the Terraform binary for you.
Other things you’ll need:
- A domain name
- A SendGrid account
- An AzureAD Service Principal
We’ll cover those next.
Register a domain
You’ll want to register a new domain - something creative, maybe customer-specific…
Think about the campaign you intend to run for the customer. Let’s say the customer uses the popular HR21/Chris21 cloud app for managing HR resources. Employees typically receive email notifications from this system for things like leave applications. Pick a domain name that’s close enough to the domain used for that customer’s app tenancy, something like customername-chris21.com
as a bad example.
Don’t worry about DNS records for the domain, as ThrowPhish will take care of that for you.
Get a SendGrid account
SendGrid is an SMTP service that we’ll be using with GoPhish to send campaign emails out to the target customer/staff.
Head over to the SendGrid signup page and create a new account in the “Free” tier.
Create AzureAD Service Principal for Let’s Encrypt
An Azure Service Principal is required to allow the Terraform Let’s Encrypt (ACME) module communicate with the Azure DNS service and create the validation record for the domain.
You can easily create this using the following script:
az ad sp create-for-rbac --name TerraformAcmeDNS --skip-assignment
You can change “TerraformAcmeDNS” to whatever name works best for you.
For example:
hadricus@epsilon:~/throwphish$ az ad sp create-for-rbac --name TerraformAcmeDNS --skip-assignment
Changing "TerraformAcmeDNS" to a valid URI of "http://TerraformAcmeDNS", which is the required format used for service principal names
The output includes credentials that you must protect. Be sure that you do not include these credentials in your code or check the credentials into your source control. For more information, see https://aka.ms/azadsp-cli
{
"appId": "8b11d76a-ed95-4482-b4a8-deadbeeffeed",
"displayName": "TerraformAcmeDNS",
"name": "http://TerraformAcmeDNS",
"password": "fbv_rK6TK61aUNotTodaySatan_NZD",
"tenant": "3d02f87c-dd4c-4b6f-bee6-deadbeeffeed"
}
Save the appId
and password
for later.
Build the customer config
ThrowPhish uses json-based configuration files representing a ‘customer’ to determine how to build the Azure resources.
In the /config
folder of the repo you’ll find domain.json.example
Edit the fields in the file using the following table as a reference.
Field | Description |
---|---|
domain | The domain you registered for use with this customer / GoPhish instance (eg. test.com ) |
hostname | Hostname for the GoPhish server. This sets the server name and results in the full FQDN for the landing page/admin portal. (eg. gophish which results in gophish.test.com ) |
customer | The name of the customer this instance is being built for. This is used for tagging Azure resources. (eg. Acme Corp ) |
sendgrid_server | You can leave this as smtp.sendgrid.com unless you’ve got a reason to change it. |
sendgrid_user | Fill in your SendGrid username. |
sendgrid_pass | Fill in your SendGrid password. |
support_email | Enter your email address. This is used for the SSL Certificate registration. |
azure_client_id | The Azure service principal appId you created earlier. |
azure_client_secret | The App Password (password ) for the service principal you created earlier. |
Once you’re done, save the file as <customername>.json
in the /config
folder.
Running ThrowPhish
Now that all the prep work is done, we’re ready to run the script and get things moving!
The throwphish.sh script has a few parameters, detailed below:
hadricus@epsilon:~/throwphish$ ./throwphish.sh
_____ _ _____ _ _ _
|_ _| |_ ___ ___ _ _ _| _ | |_|_|___| |_
| | | | _| . | | | | __| | |_ -| |
|_| |_|_|_| |___|_____|__| |_|_|_|___|_|_|
ERROR: Invalid number of parameters
Description: Creates and destroys GoPhish campaigns.
Usage: throwphish.sh [customer_name] [command]
customer_name:
- customer name, matching name of config file in the config/ directory
command:
- one of the following: createdns, createvm, destroy
command description
createdns - Creates Azure RG, prereq networking, and DNS Zone
Returns a list of DNS Nameservers to be applied at the
domain registrar prior to running 'createvm'
createvm - Creates a LetsEncrypt certificate and the GoPhish VM
destroy - Destroys all Azure resources created for the customer
First ThrowPhish will prepare Azure for the GoPhish instance and build a DNS zone. Once this is complete, you’ll go to your registrar and configure the domain to use the Azure DNS Nameservers.
Run the following command from the repo folder, replacing <customername>
with the name of the JSON file you created earlier (without the .json
on the end, of course).
## Make the script executable
chmod +x throwphish.sh
## Run the first stage to prepare Azure Resource Group, DNS Zone, and Networking
./throwphish.sh <customername> createdns
This will take a little while, but once complete it’ll spit out the nameserver FQDNs. Log into your registrar and configure the domain to use these nameservers - you might need to wait a couple hours before proceeding to Step 2 to allow the nameserver change to replicate through DNS.
When you’re ready, run throwphish with the createvm
parameter to complete the setup.
./throwphish.sh <customername> createvm
This does the following:
- Validates the domain, and creates a publicly-trusted SSL certificate for the GoPhish instance
- Creates the Azure VM, and installs/configures GoPhish
Once complete, GoPhish will be ready for use! Simply browse to https://whatever.you.configured:3333 and log into the GoPhish admin panel with the default credentials.
Feedback?
I’m keen to hear all feedback on this project. It’s not something I’m paying much attention to at the moment, but if something is broken or you’re having issues - I’m happy to help out. You can use the comments form below, or reach out to me on twitter/email/whatever.
Alternatively, feel free to fork the repository and submit some pull requests!