A low-budget DNSTwist Analysis Script Set to see who's typo-squatting your domain
A little while back we ran into a situation where "bad actors" were essentially typo-squatting or spoofing our domain. We get get correspondence from customers or business partners telling us they received emails from us that, after some investigation, we discovered that our no one at our company ever sent.
Rather than getting an email from someone\@ourdomain.com, our business partner got an email from someone@ourdomaín.com. It was an extremely subtle difference; a case of homoglyph-abuse to typo-squat on our domain to impersonate our company for the purpose of stealing product, but it was more than sufficient to fool the recipient.
p>In the domain registration world, to register ourdomaín.com, you would use the punycode xn--ourdoman-i2a.com. Completely legit but when it comes down to it, it's simple typo-squatting on a similar (VERY similar) domain name.So, it raises questions... Who's typo-squatting my domain? How do I track them down and what can I do?
DNSTwist is a tool that will take a domain name, create permutations of that domain name and then check for domain registrations for those permutations. The code for DNSTwist is available via GitHub at https://github.com/elceef/dnstwist.
I took that utility and wrote some script that will take a list of domains in a plain text file, like this...
DNSTwistTargets.txt
ourdomain.com
ourotherdomain.com
anotherdomain.com
and a list of top-level domains (TLD's) in a another plain text file, like this...
TLD.txt
com
net
org
io
biz
... and run permutations of the domains with the list of top-level domains and create json output of all of the registered domains that might be typo-squatting your domains list.
You do have to have the DNSTwist utility installed on the syste where the script will run.
The first script will generate a list of potentially typo-squatting domains, pull the A, MX and NS records well as the registrar info for the domains. Most registrars will have an abuse@ email or form that you can appeal to as long as you have solid evidence of typo-squatting abuse.
The second script adds to the json output by the first by doing some very rudimentray checks for the use of PHP, CPanel, Wordpress, domain parking, etc.
If you wanted you can take the json output to format email or html reports.
Here's the first - DomTwist.ps1
Powershell
# Input file with target domains
$inputFile = "Path to your\dnstwisttargets.txt"
$tldfile = "Path to your\tld.txt"
# Output file (JSON)
$outputFile = "Path to your\DNSTwist.json"
# Clear output file
Set-Content -Path $outputFile -Value "[]"
# Read target domains
$targets = Get-Content -Path $inputFile
# Initialize array to hold matching records
$registeredDomains = @()
Write-Host "Number of targets found: $($targets.Count)"
foreach ($target in $targets) {
Write-Host "Running dnstwist on $target..."
try {
$jsonOutput = & dnstwist -r --tld $tldfile --format json $target | ConvertFrom-Json
if ($null -eq $jsonOutput) {
Write-Warning ("No output from dnstwist for $target")
continue
}
foreach ($variant in $jsonOutput) {
$domain = $variant.domain
# Check for DNS records
$hasA = ($variant.PSObject.Properties.Name -contains "dns_a") -and `
($variant.dns_a | Where-Object { $_ -ne "" }).Count -gt 0
$hasMX = ($variant.PSObject.Properties.Name -contains "dns_mx") -and `
($variant.dns_mx | Where-Object { $_ -ne "" }).Count -gt 0
$hasNS = ($variant.PSObject.Properties.Name -contains "dns_ns") -and `
($variant.dns_ns | Where-Object { $_ -ne "" }).Count -gt 0
if ($hasA -or $hasMX -or $hasNS) {
Write-Host "[+] Registered domain found: $domain"
$registeredDomains += $variant
}
}
}
catch {
Write-Warning ("Error running dnstwist on target")
continue
}
}
# Write output to JSON file
if ($registeredDomains.Count -gt 0) {
$registeredDomains | ConvertTo-Json -Depth 5 | Set-Content -Path $outputFile
Write-Host "Results saved to $outputFile"
} else {
Write-Warning "No registered domains found."
}
and the second - DomAnalyze.ps1
Powershell
# DomTwist_Analyze.ps1
$outputFile = "Path to your\DNSTwist.json"
if (-Not (Test-Path $outputFile)) {
Write-Warning "No JSON file found. Run DomTwist.ps1 first."
exit
}
$registeredDomains = Get-Content -Path $outputFile | ConvertFrom-Json
foreach ($variant in $registeredDomains) {
$domain = $variant.domain
# Initialize all fields for consistency
$variant | Add-Member -NotePropertyName usesPHP -NotePropertyValue $false -Force
$variant | Add-Member -NotePropertyName usesWordPress -NotePropertyValue $false -Force
$variant | Add-Member -NotePropertyName usesCpanel -NotePropertyValue $false -Force
$variant | Add-Member -NotePropertyName serverHeader -NotePropertyValue $null -Force
$variant | Add-Member -NotePropertyName xPoweredBy -NotePropertyValue $null -Force
$variant | Add-Member -NotePropertyName suspiciousMX -NotePropertyValue $false -Force
$variant | Add-Member -NotePropertyName isParked -NotePropertyValue $false -Force
$hasA = ($variant.PSObject.Properties.Name -contains "dns_a") -and `
($variant.dns_a | Where-Object { $_ -ne "" }).Count -gt 0
if ($hasA) {
try {
$url = "http://" + $domain
$response = Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 5
$xPoweredBy = $response.Headers["X-Powered-By"]
$serverHeader = $response.Headers["Server"]
if ($xPoweredBy -and $xPoweredBy -match "PHP") { $variant.usesPHP = $true }
if ($response.Content -match "wp-content|wp-login\\.php|/wp-includes/") { $variant.usesWordPress = $true }
$variant.serverHeader = $serverHeader
$variant.xPoweredBy = $xPoweredBy
# Check for cPanel
$usesCpanel = $false
$cpanelUrls = @("https://$domain/cpanel", "https://$domain/webmail")
foreach ($cpanelUrl in $cpanelUrls) {
try {
$cpanelResponse = Invoke-WebRequest -Uri $cpanelUrl -UseBasicParsing -TimeoutSec 5 -MaximumRedirection 5 -ErrorAction Stop
if ($cpanelResponse.StatusCode -in @(200, 301, 302)) {
$usesCpanel = $true
break
}
}
catch {}
}
$variant.usesCpanel = $usesCpanel
}
catch {
Write-Warning ("Failed to fetch HTTP headers/content for " + $domain + ": " + $_)
}
}
$variant.suspiciousMX = ($variant.dns_mx | Where-Object { $_ -match "localhost" -or $_ -eq "" }).Count -gt 0
$variant.isParked = $variant.dns_ns -match "sedoparking|afternic|namebrightdns"
}
$registeredDomains | ConvertTo-Json -Depth 5 | Set-Content -Path $outputFile
Write-Host "Analysis complete. Results saved to $outputFile"