255 lines
8.9 KiB
Python
255 lines
8.9 KiB
Python
"""
|
||
This plugin provides a command to search Exploit-DB for security exploits and vulnerabilities.
|
||
Uses the searchsploit-style approach with the files.csv database.
|
||
"""
|
||
|
||
import logging
|
||
import requests
|
||
import csv
|
||
import io
|
||
import simplematrixbotlib as botlib
|
||
from datetime import datetime
|
||
|
||
# Exploit-DB CSV database URL
|
||
EXPLOITDB_CSV_URL = "https://gitlab.com/exploit-database/exploitdb/-/raw/main/files_exploits.csv"
|
||
|
||
|
||
def format_exploit(exploit, index, total):
|
||
"""
|
||
Format an exploit entry for display.
|
||
|
||
Args:
|
||
exploit (dict): The exploit data.
|
||
index (int): Current result index.
|
||
total (int): Total number of results.
|
||
|
||
Returns:
|
||
str: Formatted HTML string.
|
||
"""
|
||
edb_id = exploit.get('id', 'N/A')
|
||
title = exploit.get('description', 'No title')
|
||
date = exploit.get('date', 'Unknown')
|
||
author = exploit.get('author', 'Unknown')
|
||
exploit_type = exploit.get('type', 'Unknown')
|
||
platform = exploit.get('platform', 'Unknown')
|
||
|
||
# Build the URL
|
||
url = f"https://www.exploit-db.com/exploits/{edb_id}"
|
||
|
||
output = f"""<strong>💣 Exploit {index}/{total}</strong><br>
|
||
<strong>Title:</strong> {title}<br>
|
||
<strong>EDB-ID:</strong> {edb_id}<br>
|
||
<strong>Type:</strong> {exploit_type} | <strong>Platform:</strong> {platform}<br>
|
||
<strong>Author:</strong> {author} | <strong>Date:</strong> {date}<br>
|
||
<strong>URL:</strong> <a href="{url}">{url}</a>"""
|
||
|
||
return output
|
||
|
||
|
||
async def search_exploitdb_csv(query, max_results=5):
|
||
"""
|
||
Search Exploit-DB CSV database for exploits matching the query.
|
||
|
||
Args:
|
||
query (str): Search term.
|
||
max_results (int): Maximum number of results to return.
|
||
|
||
Returns:
|
||
list: List of exploit dictionaries, or None on error.
|
||
"""
|
||
try:
|
||
logging.info(f"Downloading Exploit-DB CSV database...")
|
||
|
||
headers = {
|
||
'User-Agent': 'FunguyBot/1.0',
|
||
}
|
||
|
||
# Download the CSV file
|
||
response = requests.get(EXPLOITDB_CSV_URL, headers=headers, timeout=30)
|
||
response.raise_for_status()
|
||
|
||
# Parse CSV
|
||
csv_data = response.text
|
||
csv_file = io.StringIO(csv_data)
|
||
reader = csv.DictReader(csv_file)
|
||
|
||
# Search through CSV
|
||
results = []
|
||
query_lower = query.lower()
|
||
|
||
logging.info(f"Searching CSV for: {query}")
|
||
|
||
for row in reader:
|
||
# Search in description (title) and other fields
|
||
description = row.get('description', '').lower()
|
||
file_path = row.get('file', '').lower()
|
||
|
||
if query_lower in description or query_lower in file_path:
|
||
exploit = {
|
||
'id': row.get('id', 'N/A'),
|
||
'description': row.get('description', 'No title'),
|
||
'date': row.get('date_published', row.get('date', 'Unknown')),
|
||
'author': row.get('author', 'Unknown'),
|
||
'type': row.get('type', 'Unknown'),
|
||
'platform': row.get('platform', 'Unknown')
|
||
}
|
||
results.append(exploit)
|
||
|
||
if len(results) >= max_results:
|
||
break
|
||
|
||
return results
|
||
|
||
except requests.exceptions.Timeout:
|
||
logging.error("Timeout downloading Exploit-DB database")
|
||
return None
|
||
except requests.exceptions.RequestException as e:
|
||
logging.error(f"Error downloading Exploit-DB database: {e}")
|
||
return None
|
||
except Exception as e:
|
||
logging.error(f"Unexpected error searching Exploit-DB: {e}", exc_info=True)
|
||
return None
|
||
|
||
|
||
async def search_exploitdb_google(query, max_results=5):
|
||
"""
|
||
Alternative: Search Exploit-DB using site-specific search.
|
||
Returns formatted search URLs instead of parsing.
|
||
|
||
Args:
|
||
query (str): Search term.
|
||
max_results (int): Maximum number of results to return.
|
||
|
||
Returns:
|
||
str: Formatted search information.
|
||
"""
|
||
# Create search URLs
|
||
exploitdb_search_url = f"https://www.exploit-db.com/search?q={query}"
|
||
google_search_url = f"https://www.google.com/search?q=site:exploit-db.com+{query}"
|
||
|
||
output = f"""<strong>💣 Exploit-DB Search for: {query}</strong><br><br>
|
||
<strong>Direct Search:</strong><br>
|
||
<a href="{exploitdb_search_url}">{exploitdb_search_url}</a><br><br>
|
||
<strong>Google Site Search:</strong><br>
|
||
<a href="{google_search_url}">{google_search_url}</a><br><br>
|
||
<em>💡 Tip: You can also use <code>searchsploit</code> command-line tool for offline searches.</em><br>
|
||
<em>⚠️ Use responsibly and only on systems you have permission to test.</em>"""
|
||
|
||
return output
|
||
|
||
|
||
async def handle_command(room, message, bot, prefix, config):
|
||
"""
|
||
Function to handle the !exploitdb 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("exploitdb"):
|
||
logging.info("Received !exploitdb command")
|
||
|
||
args = match.args()
|
||
|
||
if len(args) < 1:
|
||
await bot.api.send_text_message(
|
||
room.room_id,
|
||
"Usage: !exploitdb <search term> [max_results]\n"
|
||
"Examples:\n"
|
||
" !exploitdb wordpress\n"
|
||
" !exploitdb apache 3\n"
|
||
" !exploitdb windows privilege escalation\n"
|
||
"Searches Exploit-DB for security vulnerabilities and exploits."
|
||
)
|
||
logging.info("Sent usage message for !exploitdb")
|
||
return
|
||
|
||
# Check if last argument is a number (max results)
|
||
max_results = 5
|
||
search_terms = args
|
||
|
||
if args[-1].isdigit():
|
||
max_results = int(args[-1])
|
||
if max_results < 1:
|
||
max_results = 1
|
||
elif max_results > 10:
|
||
max_results = 10
|
||
search_terms = args[:-1]
|
||
|
||
query = ' '.join(search_terms)
|
||
|
||
try:
|
||
# Send "searching" message
|
||
await bot.api.send_text_message(
|
||
room.room_id,
|
||
f"🔍 Searching Exploit-DB for: {query}... (this may take a moment)"
|
||
)
|
||
|
||
# Try CSV search first
|
||
exploits = await search_exploitdb_csv(query, max_results)
|
||
|
||
if exploits is None:
|
||
# Fallback to providing search links
|
||
logging.warning("CSV search failed, providing search links instead")
|
||
output = await search_exploitdb_google(query, max_results)
|
||
await bot.api.send_markdown_message(room.room_id, output)
|
||
return
|
||
|
||
if not exploits:
|
||
# Also provide search links when no results
|
||
output = f"No exploits found in local search for: <strong>{query}</strong><br><br>"
|
||
output += await search_exploitdb_google(query, max_results)
|
||
await bot.api.send_markdown_message(room.room_id, output)
|
||
logging.info(f"No exploits found for: {query}")
|
||
return
|
||
|
||
total = len(exploits)
|
||
logging.info(f"Found {total} exploit(s) for: {query}")
|
||
|
||
# Format all results
|
||
output = f"<strong>💣 Exploit-DB Search Results for: {query}</strong><br><br>"
|
||
|
||
for idx, exploit in enumerate(exploits, 1):
|
||
output += format_exploit(exploit, idx, total)
|
||
output += "<br><br>"
|
||
|
||
output += f"<em>⚠️ Use responsibly and only on systems you have permission to test.</em>"
|
||
|
||
# Wrap in collapsible details if more than 2 results
|
||
if total > 2:
|
||
summary = f"<strong>💣 Exploit-DB: {query}</strong> ({total} results)"
|
||
output = f"<details><summary>{summary}</summary>{output}</details>"
|
||
|
||
await bot.api.send_markdown_message(room.room_id, output)
|
||
logging.info(f"Sent {total} exploit(s) for: {query}")
|
||
|
||
except Exception as e:
|
||
await bot.api.send_text_message(
|
||
room.room_id,
|
||
f"An error occurred while searching Exploit-DB: {str(e)}"
|
||
)
|
||
logging.error(f"Error in exploitdb plugin: {e}", exc_info=True)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Plugin Metadata
|
||
# ---------------------------------------------------------------------------
|
||
|
||
__version__ = "1.0.0"
|
||
__author__ = "Funguy Bot"
|
||
__description__ = "Exploit-DB search"
|
||
__help__ = """
|
||
<details>
|
||
<summary><strong>!exploitdb</strong> – Search Exploit Database</summary>
|
||
<p><code>!exploitdb <search term> [max_results]</code> – Search for exploits (title, EDB-ID, type, platform, author, link).<br>
|
||
Example: <code>!exploitdb wordpress 5</code></p>
|
||
<p>Fetches from the official Exploit-DB CSV. Falls back to search links if unavailable.</p>
|
||
</details>
|
||
"""
|