Skip to content

Instantly share code, notes, and snippets.

@groundcat
Created July 25, 2024 02:39
Show Gist options
  • Save groundcat/9d9c0b490b3579cc5214336e01569d9e to your computer and use it in GitHub Desktop.
Save groundcat/9d9c0b490b3579cc5214336e01569d9e to your computer and use it in GitHub Desktop.
PSL Single Domain Checker
import datetime
import sys
import os
import subprocess
import re
import webbrowser
from typing import List
def is_valid_domain(domain: str) -> bool:
regex = re.compile(
r'^(?=.{1,253}$)(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)\.)+[A-Za-z]{2,}$'
)
return re.match(regex, domain) is not None
def print_header(title: str):
print(f"\n{'-' * 40}")
print(f"{title}")
print(f"{'-' * 40}")
def run_command(command: List[str]) -> str:
result = subprocess.run(command, capture_output=True, text=True)
return result.stdout
def save_to_file(filename: str, content: str):
with open(filename, 'w') as file:
file.write(content)
def print_welcome():
welcome_text = """
Welcome to the PSL Single Domain Checker CLI Tool!
This script allows you to perform several checks on a given domain name. The checks include:
1. WHOIS lookup: Retrieves registration information for the domain.
2. DNS _psl TXT record check: Fetches TXT records from various DNS servers.
3. Domain usage scan: Checks A, NS, and MX records for the domain.
4. Search engine checks: Opens your browser to search for the domain on multiple search engines.
5. Subdomain finder tools: Opens tools in your browser to find subdomains.
6. crt.sh check: Opens crt.sh in your browser to view Certificate Transparency logs for the domain.
7. VirusTotal check: Opens VirusTotal in your browser to see security reports for the domain.
To use this script, simply run it with a fully qualified domain name (FQDN) as an argument:
python3 singleDomainChecker.py example.com
The script will guide you through each step, displaying results in the console and saving relevant information to files.
A Markdown template report in .md format will also be generated for you to document your findings.
Let's get started!
"""
print(welcome_text)
if input("Continue (y/n)? ").strip().lower() != 'y':
sys.exit(0)
def main():
print_welcome()
if len(sys.argv) != 2 or not is_valid_domain(sys.argv[1]):
print("Usage: python3 singleDomainChecker.py example.com")
sys.exit(1)
domain = sys.argv[1]
print_header(f"Running checks for {domain}")
# WHOIS check
print_header("WHOIS Check")
whois_result = run_command(['whois', domain])
print(whois_result)
save_to_file(f"{domain}_whois.txt", whois_result)
# DNS _psl TXT record check
print_header("DNS _psl TXT Record Check")
dns_servers = ['8.8.8.8', '1.1.1.1', '208.67.222.222'] # Google, Cloudflare, OpenDNS
txt_records = {}
for server in dns_servers:
result = run_command(['dig', '+short', 'TXT', f'_psl.{domain}', f'@{server}'])
txt_records[server] = result.strip()
print(f"Server: {server}\n{result}")
# Scan for domain usage
print_header("Domain Usage Scan")
domain_usage_results = {}
records_to_check = {
"A record (root)": domain,
"A record (www)": f"www.{domain}",
"NS records": domain,
"MX records": domain
}
for record_type, query in records_to_check.items():
result = run_command(['dig', record_type.split()[0], '+short', query])
domain_usage_results[record_type] = result.strip()
print(f"{record_type}:\n{result}")
# Open browser for search engine checks
if input("Open browser for search engine checks (y/n)? ").strip().lower() == 'y':
search_urls = [
f"https://www.google.com/search?q=site:{domain}",
f"https://www.bing.com/search?q=site%3A{domain}",
f"https://duckduckgo.com/?q=site%3A{domain}",
f"https://search.yahoo.com/search?p=site%3A{domain}",
f"https://search.brave.com/search?q=site%3A{domain}"
]
for url in search_urls:
webbrowser.open_new_tab(url)
# Open browser for subdomain finder tools
if input("Open browser for subdomain finder tools (y/n)? ").strip().lower() == 'y':
subdomain_urls = [
f"https://osint.sh/subdomain/",
f"https://subdomainfinder.c99.nl",
f"https://lookup.tools/subdomain/{domain}"
]
for url in subdomain_urls:
webbrowser.open_new_tab(url)
# Open browser for crt.sh check
if input("Open browser for crt.sh check (y/n)? ").strip().lower() == 'y':
crtsh_url = f"https://crt.sh/?q={domain}"
webbrowser.open_new_tab(crtsh_url)
# Open browser for VirusTotal check
if input("Open browser for VirusTotal check (y/n)? ").strip().lower() == 'y':
virustotal_url = f"https://www.virustotal.com/gui/domain/{domain}/detection"
webbrowser.open_new_tab(virustotal_url)
# Generate template report
report_content = f"""
# WHOIS
<!-- TODO: Describe the WHOIS findings -->
Please read the original WHOIS records below:
```
{whois_result}
```
Sources: whois utility generated at {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
# Organization Website and Nature Check
<!-- TODO: Describe the organization website and nature findings -->
Sources:
- Organization website URL from the PSL comments
<!-- TODO: Organization website URL -->
# _psl TXT Record
Responses from multiple DNS servers for the `_psl` TXT record of the domain:
Response from `8.8.8.8`: `{txt_records['8.8.8.8']}`
Response from `1.1.1.1`: `{txt_records['1.1.1.1']}`
Response from `208.67.222.222`: `{txt_records['208.67.222.222']}`
<!-- TODO: Describe the _psl TXT record findings -->
Sources: dig command using DNS servers: Google (8.8.8.8), Cloudflare (1.1.1.1), OpenDNS (208.67.222.222)
# Root-level Domain Usage Scan
As a potential indicator of domain usage, we scan the following records:
`NS records ({domain})` returns `{domain_usage_results['NS records']}`
Additionally, we scan the following records for possible website usage at the root level:
`A record ({domain})` returns `{domain_usage_results['A record (root)']}`
`A record (www.{domain})` returns `{domain_usage_results['A record (www)']}`
`MX records ({domain})` returns `{domain_usage_results['MX records']}`
<!-- TODO: Describe the domain usage scan findings -->
Sources: `dig` command for A, NS, and MX records
# Search Engine Checks
For possible website usage, we queried multiple different search engines:
<!-- TODO: Perform search engine checks and describe findings -->
Sources:
- [Google](https://www.google.com/search?q=site:{domain})
- [Bing](https://www.bing.com/search?q=site%3A{domain})
- [DuckDuckGo](https://duckduckgo.com/?q=site%3A{domain})
- [Yahoo](https://search.yahoo.com/search?p=site%3A{domain})
- [Brave](https://search.brave.com/search?q=site%3A{domain})
# Subdomain Discovery
For potential usage of subdomains that are not discovered by the search engines,
we used the following tools and here are the obtained observations:
<!-- TODO: Use subdomain finder tools and describe findings -->
Sources:
- [OSINT.sh](https://osint.sh/subdomain/)
- [Subdomain Finder](https://subdomainfinder.c99.nl)
- [Lookup Tools](https://lookup.tools/subdomain/{domain})
# crt.sh Certificate Transparency Logs
For potential website usage of subdomains that are not discovered by the search engines,
we checked the Certificate Transparency Logs and here are the obtained observations:
<!-- TODO: Check crt.sh and describe findings -->
Sources:
- [crt.sh](https://crt.sh/?q={domain})
# VirusTotal Check
To check for possible security issues, we used VirusTotal and here are the obtained observations:
<!-- TODO: Check VirusTotal and describe findings -->
Sources:
- [VirusTotal](https://www.virustotal.com/gui/domain/{domain}/detection)
"""
save_to_file(f"{domain}_report_template.md", report_content)
print_header(f"Template report in Markdown has been generated at {domain}_report_template.md")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment