""" This plugin provides a command to search Exploit-DB for security exploits. """ import logging import aiohttp import csv import io import simplematrixbotlib as botlib from plugins.common import html_escape, collapsible_summary EXPLOITDB_CSV_URL = "https://gitlab.com/exploit-database/exploitdb/-/raw/main/files_exploits.csv" def format_exploit(exploit, index, total): edb_id = html_escape(str(exploit.get('id', 'N/A'))) title = html_escape(exploit.get('description', 'No title')) date = html_escape(exploit.get('date', 'Unknown')) author = html_escape(exploit.get('author', 'Unknown')) exploit_type = html_escape(exploit.get('type', 'Unknown')) platform = html_escape(exploit.get('platform', 'Unknown')) url = f"https://www.exploit-db.com/exploits/{edb_id}" return f"""💣 Exploit {index}/{total} Title: {title} EDB-ID: {edb_id} Type: {exploit_type} | Platform: {platform} Author: {author} | Date: {date} URL: {url}""" async def search_exploitdb_csv(query, max_results=5): headers = {'User-Agent': 'FunguyBot/1.0'} try: async with aiohttp.ClientSession() as session: async with session.get(EXPLOITDB_CSV_URL, headers=headers, timeout=30) as response: response.raise_for_status() csv_data = await response.text() except Exception as e: logging.error(f"Error downloading CSV: {e}") return None results = [] try: csv_file = io.StringIO(csv_data) reader = csv.DictReader(csv_file) query_lower = query.lower() for row in reader: description = row.get('description', '').lower() file_path = row.get('file', '').lower() if query_lower in description or query_lower in file_path: results.append({ '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') }) if len(results) >= max_results: break return results except Exception as e: logging.error(f"CSV parse error: {e}") return None async def handle_command(room, message, bot, prefix, config): match = botlib.MessageMatch(room, message, bot, prefix) if match.is_not_from_this_bot() and match.prefix() and match.command("exploitdb"): args = match.args() if not args: await bot.api.send_text_message(room.room_id, "Usage: !exploitdb [max_results]") return 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) safe_query = html_escape(query) await bot.api.send_text_message(room.room_id, f"🔍 Searching Exploit-DB for: {safe_query}...") exploits = await search_exploitdb_csv(query, max_results) if exploits is None: await bot.api.send_text_message(room.room_id, "❌ Failed to search Exploit-DB (network error).") return if not exploits: exploitdb_url = f"https://www.exploit-db.com/search?q={query}" google_url = f"https://www.google.com/search?q=site:exploit-db.com+{query}" msg = f"No exploits found for {safe_query}.Direct: Exploit-DB | Google" await bot.api.send_markdown_message(room.room_id, msg) return total = len(exploits) output = f"💣 Exploit-DB Search Results for: {safe_query}" for idx, exp in enumerate(exploits, 1): output += format_exploit(exp, idx, total) + "" output += "⚠️ Use responsibly" if total > 2: output = collapsible_summary(f"💣 Exploit-DB: {safe_query} ({total} results)", output) await bot.api.send_markdown_message(room.room_id, output) __version__ = "1.0.1" __author__ = "Funguy Bot" __description__ = "Exploit-DB search" __help__ = """!exploitdb – Search Exploit Database !exploitdb <search term> [max_results]"""
!exploitdb <search term> [max_results]