Add IP geolocation and subdomain enumeration plugins
- Added geo.py plugin for IP geolocation with ip-api.com and ipapi.co support - Added subdomains.py plugin for subdomain enumeration using CertSpotter API - Updated help.py with documentation for new plugins - Updated README.md with documentation for new plugins - Both plugins support domain/IP resolution and provide detailed information
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
"""
|
||||
This plugin provides subdomain enumeration functionality using the CertSpotter API.
|
||||
It queries SSL certificates issued for domains to discover associated subdomains.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import aiohttp
|
||||
import simplematrixbotlib as botlib
|
||||
import json
|
||||
import asyncio
|
||||
|
||||
async def query_certspotter(domain):
|
||||
"""
|
||||
Query CertSpotter API for subdomain enumeration.
|
||||
|
||||
Args:
|
||||
domain (str): The domain to enumerate subdomains for
|
||||
|
||||
Returns:
|
||||
list: List of discovered subdomains
|
||||
"""
|
||||
url = f"https://api.certspotter.com/v1/issuances?domain={domain}&include_subdomains=true&expand=dns_names"
|
||||
subdomains = set()
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(url) as response:
|
||||
if response.status == 200:
|
||||
data = await response.json()
|
||||
for cert in data:
|
||||
if 'dns_names' in cert:
|
||||
for dns_name in cert['dns_names']:
|
||||
if domain in dns_name:
|
||||
subdomains.add(dns_name)
|
||||
else:
|
||||
logging.error(f"CertSpotter API returned status {response.status}")
|
||||
return []
|
||||
except Exception as e:
|
||||
logging.error(f"Error querying CertSpotter API: {e}")
|
||||
return []
|
||||
|
||||
return list(subdomains)
|
||||
|
||||
async def format_subdomain_results(domain, subdomains):
|
||||
"""
|
||||
Format subdomain results into a readable message.
|
||||
|
||||
Args:
|
||||
domain (str): The queried domain
|
||||
subdomains (list): List of discovered subdomains
|
||||
|
||||
Returns:
|
||||
str: Formatted message
|
||||
"""
|
||||
if not subdomains:
|
||||
return f"🔍 No subdomains found for {domain} using CertSpotter API."
|
||||
|
||||
# Sort and remove duplicates
|
||||
subdomains = sorted(list(set(subdomains)))
|
||||
count = len(subdomains)
|
||||
|
||||
# Create the subdomain list with proper HTML list formatting
|
||||
subdomain_list = "<ul>"
|
||||
for sub in subdomains:
|
||||
subdomain_list += f"<li>{sub}</li>"
|
||||
subdomain_list += "</ul>"
|
||||
|
||||
# Create collapsible content
|
||||
content = f"<strong>🔍 Subdomain Enumeration Results for {domain}</strong><br><br>"
|
||||
content += f"<strong>Total subdomains found:</strong> {count}<br><br>"
|
||||
content += f"<strong>Discovered subdomains:</strong><br>{subdomain_list}"
|
||||
|
||||
# Wrap in details tag for Matrix compatibility
|
||||
message = f"<details><summary><strong>🔍 Subdomain Enumeration: {domain} ({count} found)</strong></summary>{content}</details>"
|
||||
|
||||
return message
|
||||
|
||||
async def handle_command(room, message, bot, prefix, config):
|
||||
"""
|
||||
Function to handle the !subdomains command.
|
||||
|
||||
Args:
|
||||
room (Room): The Matrix room where the command was invoked.
|
||||
message (RoomMessage): The message object containing the command.
|
||||
bot (Bot): The bot object.
|
||||
prefix (str): The command prefix.
|
||||
config (dict): Configuration parameters.
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
match = botlib.MessageMatch(room, message, bot, prefix)
|
||||
|
||||
if match.is_not_from_this_bot() and match.prefix() and match.command("subdomains"):
|
||||
args = match.args()
|
||||
|
||||
if len(args) < 1:
|
||||
await bot.api.send_text_message(
|
||||
room.room_id,
|
||||
"Usage: !subdomains <domain>\nExample: !subdomains example.com"
|
||||
)
|
||||
return
|
||||
|
||||
domain = args[0].strip()
|
||||
logging.info(f"Received !subdomains command for: {domain}")
|
||||
|
||||
try:
|
||||
# Notify user that we're starting the lookup
|
||||
await bot.api.send_text_message(
|
||||
room.room_id,
|
||||
f"🔍 Enumerating subdomains for {domain} using CertSpotter API..."
|
||||
)
|
||||
|
||||
# Query CertSpotter API
|
||||
subdomains = await query_certspotter(domain)
|
||||
|
||||
# Format and send results
|
||||
result_message = await format_subdomain_results(domain, subdomains)
|
||||
await bot.api.send_markdown_message(room.room_id, result_message)
|
||||
logging.info(f"Successfully sent subdomain enumeration results for {domain}")
|
||||
|
||||
except Exception as e:
|
||||
await bot.api.send_text_message(
|
||||
room.room_id,
|
||||
f"An error occurred during subdomain enumeration for {domain}. Please try again later."
|
||||
)
|
||||
logging.error(f"Error in subdomains plugin for {domain}: {e}", exc_info=True)
|
||||
Reference in New Issue
Block a user