dnstwist-ing in Sublime Security
Automate the detection of potentially malicious domains and associated emails targeting your organization
You can use dnstwist to find potentially malicious domains targeting your organization and automatically add them to a list in Sublime Security. We will create a detection rule in Sublime that uses this list to find any sender addresses or email body links related to those domains and flags them for review.
What is dnstwist?
dnstwist
is a DNS fuzzer that generates a list of permutations on a given domain to find potentially malicious domains targeting your organization. It performs WHOIS checks to see if these domains are registered and when they were created. Additionally, it checks for A or MX records, which can provide insight into how an attacker might use the domain (e.g., sending emails or hosting malicious content).
Quick dnstwist Demo
Installation
$ python3 -m venv venv
$ source venv/bin/activate
$ pip install "dnstwist[full]"
Checking a Domain
Using axs.com
as an example with low permutations, dnstwist
will generate a list of permutations on that domain and check if they are registered using the following command:
❯ dnstwist --registered --whois axs.com
Output example:
started 12 scanner threads
permutations: 100.00% of 299 | found: 270 | eta: 0m 00s | speed: 30 qps
WHOIS: oxs.com (100.00%)
*original axs.com 34.205.213.171 NS:ns-1047.awsdns-02.org MX:axs-com.mail.protection.outlook.com REGISTRAR:Network Solutions, LLC CREATED:1997-02-27
addition axsj.com !ServFail !ServFail NS:!ServFail REGISTRAR:Sav.com, LLC CREATED:2000-10-24
addition axsd.com 103.238.226.248 NS:hkd001.ddddns.net REGISTRAR:DDD TECHNOLOGY PTE. LTD. CREATED:2001-01-27
addition axst.com 104.247.81.51 NS:ns1.parkingcrew.net MX:mail.h-email.net REGISTRAR:BigRock Solutions Ltd CREATED:2005-03-19
Pro tip:
grep
on"CREATED:2024"
(or current year) to show only newly-registered domains.
Workflow
List of Domains
While you should use your organization’s domains, it’s also a good idea to check pairings of other enterprise tools with your domain, as these are commonly abused:
domains = [
"acmecorp.com",
"acmecorp-microsoft.com",
"acmecorp-apple.com",
"acmecorp-google.com",
"acmecorp-amazon.com",
"acmecorp-okta.com",
"acmecorp-aws.com",
"acmecorp-azure.com",
"acmecorp-gcp.com",
"acmecorp-salesforce.com",
"acmecorp-slack.com",
"microsoft-acmecorp.com",
"apple-acmecorp.com",
"google-acmecorp.com",
"amazon-acmecorp.com",
"okta-acmecorp.com",
"aws-acmecorp.com",
"azure-acmecorp.com",
"gcp-acmecorp.com",
"slack-acmecorp.com"
]
Python API
It’s not recommended to use the CLI for automated workflows. Instead, dnstwist
has a Python API that can format results as JSON. Here’s a sample script:
import dnstwist
import time
def main(domain):
start_time = time.time()
data = dnstwist.run(domain=domain, whois=True, registered=True, threads=20, nameservers='1.1.1.1,8.8.8.8', format='json')
end_time = time.time()
execution_time = end_time - start_time
return {"result": data, "execution_time": execution_time}
Adjust threads
as needed
dnstwist
returns an array of JSON objects that look something like this:
{
"fuzzer": "vowel-swap",
"domain": "ocmecorp.com",
"dns_ns": ["ns1.asdf.com"],
"dns_a": ["1.2.3.4"],
"dns_mx": ["mail.asdf.net"],
"whois_created": "2005-08-15",
"whois_registrar": "GoDaddy.com, LLC"
}
Filtering and Adding to Sublime List
For this workflow, we care about newly-registered domains with A or MX records. Here’s some pseudocode logic to decide whether to add the domain to the Sublime list:
IF item has 'dns_mx' or 'dns_a' record
AND item whois_created within 3 months
THEN add to dnstwist_domains list in Sublime
Python Script Example
Here’s a full example script that filters domains and sends qualifying ones to the dnstwist_domains
list in Sublime:
✍️ Note: You will need to manually set your base URL and list ID. More on that below.
import dnstwist
import time
import datetime
import requests
import os
# Sublime API key
sublime_api_key = os.environ.get('SUBLIME_API_KEY')
# List of domains to process
domains = [
"acmecorp.com",
"acmecorp-microsoft.com",
"acmecorp-apple.com",
"acmecorp-google.com",
"acmecorp-amazon.com",
"acmecorp-okta.com",
"acmecorp-aws.com",
"acmecorp-azure.com",
"acmecorp-gcp.com",
"acmecorp-salesforce.com",
"acmecorp-slack.com",
"microsoft-acmecorp.com",
"apple-acmecorp.com",
"google-acmecorp.com",
"amazon-acmecorp.com",
"okta-acmecorp.com",
"aws-acmecorp.com",
"azure-acmecorp.com",
"gcp-acmecorp.com",
"slack-acmecorp.com"
]
# Function to process a single domain
def process_domain(domain):
start_time = time.time()
data = dnstwist.run(domain=domain, whois=True, registered=True, threads=20, nameservers='1.1.1.1,8.8.8.8', format='json')
end_time = time.time()
execution_time = end_time - start_time
return {"result": data, "execution_time": execution_time}
# Function to check if a domain meets the criteria
def is_recently_created(whois_created):
if whois_created:
creation_date = datetime.datetime.strptime(whois_created, '%Y-%m-%dT%H:%M:%S')
return (datetime.datetime.now() - creation_date).days <= 90
return False
# Function to send a domain to Sublime
def add_to_sublime_list(domain):
url = "https://[your_sublime_base_url]/v0/lists/[list_id]/entries/entry"
payload = {"string": domain}
headers = {"Content-Type": "application/json", "authorization": f"Bearer {sublime_api_key}"}
response = requests.post(url, json=payload, headers=headers)
return response.status_code
# Function to get current list entries
def get_sublime_entries():
url = "https://[your_sublime_base_url]/v0/lists/[list_id]/entries"
headers = {"Content-Type": "application/json", "authorization": f"Bearer {sublime_api_key}"}
response = requests.get(url, headers=headers)
return response.json()
# Main logic to process domains and filter based on criteria
entries = get_sublime_entries()
for domain in domains:
result = process_domain(domain)
data = result["result"]
for item in data['domains']:
if item['domain'] in entries['entries']:
continue
if 'dns_mx' in item or 'dns_a' in item:
if is_recently_created(item.get('whois_created')):
response_code = add_to_sublime_list(item['domain'])
print(f"Sent {item['domain']} to Sublime list, response code: {response_code}")
print("Processing completed.")
Creating the List in Sublime
Create a new list in Sublime Security by navigating to Lists > Create New List
. Name the list dnstwist_domains
and set the list type to string
. Retrieve the list ID using the Retrieve Lists endpoint and search for your list name to get the ID.
Create the Detection Rule in Sublime
Create a detection rule in Sublime with the following MQL:
type.inbound
and
// dnstwist list matches
1 of (
any(body.links, .href_url.domain.root_domain in $dnstwist_domains),
sender.email.domain.root_domain in $dnstwist_domains
)
// add any exclusions found through backtesting below
This rule searches for email body links or sender addresses that match the domains within the dnstwist_domains
list. You could take the Sublime rule even further by checking attachment links against the dnstwist
list as well.
It’s highly recommended to backtest any new rule in Sublime and add necessary exclusions to avoid false positives (e.g., you would exclude the sender address/domain of a threat intel service that is sending you the same domains via email).
Summary
This workflow effectively uses dnstwist
and Sublime Security together to automate the detection of potentially malicious domains and associated emails targeting your organization.
Ideally, you would run this workflow as a scheduled task on your preferred platform. If you’re using Tines, you can run the process_domain
function above in the Run Python Script action and parse out the rest of the logic into Tines actions. Keep in mind you might run into execution time limits depending on the amount of permutations generated on a domain.d