#seceng
### Automate the detection of potentially malicious domains and associated emails targeting your organization
You can use [dnstwist](https://github.com/elceef/dnstwist?ref=akatz.org) to find potentially malicious domains targeting your organization and automatically add them to a list in [Sublime Security](https://sublime.security/?ref=akatz.org). 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
```sh
$ 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:
```sh
❯ 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
```
> [!protip] 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:
```python
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:
```python
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:
```json
{
"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:
```python
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:
> [!info] ✍️ Note: You will need to manually set your base URL and list ID. More on that below.
```python
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](https://docs.sublimesecurity.com/reference/getlists-1?ref=akatz.org) 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:
```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](https://www.tines.com/docs/actions/templates/templates/frequently-used-templates/run-python-script?ref=akatz.org) 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.