fierce_scan
Perform DNS reconnaissance and subdomain discovery for target domains using customizable scanning parameters and wordlists.
Instructions
Execute Fierce for DNS reconnaissance and subdomain discovery.
Args: domain: Target domain dns_server: DNS server to use wordlist: Custom wordlist for subdomain brute force threads: Number of threads delay: Delay between requests wide: Wide scan (more comprehensive) additional_args: Additional Fierce arguments
Returns: DNS reconnaissance results
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| additional_args | No | ||
| delay | No | ||
| dns_server | No | ||
| domain | Yes | ||
| threads | No | ||
| wide | No | ||
| wordlist | No |
Implementation Reference
- src/mcp_server/app.py:1151-1192 (registration)MCP tool registration (@mcp.tool()) and handler function for 'fierce_scan'. Proxies parameters to REST API endpoint '/api/fierce' via BugBountyAPIClient.def fierce_scan( domain: str, dns_server: str = "", wordlist: str = "", threads: int = 20, delay: int = 0, wide: bool = False, additional_args: str = "", ) -> dict[str, Any]: """Execute Fierce for DNS reconnaissance and subdomain discovery. Args: domain: Target domain dns_server: DNS server to use wordlist: Custom wordlist for subdomain brute force threads: Number of threads delay: Delay between requests wide: Wide scan (more comprehensive) additional_args: Additional Fierce arguments Returns: DNS reconnaissance results """ data = { "domain": domain, "dns_server": dns_server, "wordlist": wordlist, "threads": threads, "delay": delay, "wide": wide, "additional_args": additional_args, } logger.info(f"🔍 Starting Fierce DNS reconnaissance on {domain}") result = api_client.safe_post("api/fierce", data) if result.get("success"): logger.info(f"✅ Fierce scan completed on {domain}") else: logger.error("❌ Fierce scan failed") return result
- Core execution handler for the 'fierce' tool in REST API. Extracts params, builds and runs 'fierce' command, parses output into structured findings with subdomains.@tool(required_fields=["target"]) def execute_fierce(): """Execute Fierce for DNS reconnaissance and subdomain discovery.""" data = request.get_json() params = extract_fierce_params(data) started_at = datetime.now() command = build_fierce_command(params) execution_result = execute_command( " ".join(command), timeout=params.get("timeout", 600) ) ended_at = datetime.now() return parse_fierce_output(execution_result, params, command, started_at, ended_at)
- Helper function to construct the 'fierce' command-line arguments based on input parameters.def build_fierce_command(params: dict) -> list[str]: """Build the fierce command from parameters.""" args = ["fierce", "--domain", params["domain"]] # Add optional parameters if params["dns_servers"]: if isinstance(params["dns_servers"], list): dns_servers_str = " ".join(params["dns_servers"]) else: dns_servers_str = str(params["dns_servers"]) args.extend(["--dns-servers", dns_servers_str]) if params["wide"]: args.append("--wide") if params["connect"]: args.append("--connect") if params["delay"] > 0: args.extend(["--delay", str(params["delay"])]) if params["traverse"]: args.extend(["--traverse", params["traverse"]]) if params["range"]: args.extend(["--range", params["range"]]) if params["subdomain_file"]: args.extend(["--subdomain-file", params["subdomain_file"]]) if params["subdomains"]: if isinstance(params["subdomains"], list): subdomains_str = " ".join(params["subdomains"]) else: subdomains_str = str(params["subdomains"]) args.extend(["--subdomains", subdomains_str]) if params["tcp"]: args.append("--tcp") # Add any additional arguments if params["additional_args"]: args.extend(params["additional_args"].split()) return args
- Helper function to parse 'fierce' tool output, extract subdomains, and format into structured JSON findings with stats.def parse_fierce_output( execution_result: dict[str, Any], params: dict, command: list[str], started_at: datetime, ended_at: datetime, ) -> dict[str, Any]: """Parse fierce execution results into structured findings.""" duration_ms = int((ended_at - started_at).total_seconds() * 1000) if not execution_result["success"]: return { "success": False, "tool": "fierce", "params": params, "command": command, "started_at": started_at.isoformat(), "ended_at": ended_at.isoformat(), "duration_ms": duration_ms, "error": execution_result.get("error", "Command execution failed"), "findings": [], "stats": {"findings": 0, "dupes": 0, "payload_bytes": 0}, } # Parse successful output stdout = execution_result.get("stdout", "") with open("/tmp/fierce_raw_output.log", "a") as f: f.write(stdout + "\n") findings = [] # Extract subdomains from fierce output for line in stdout.strip().split("\n"): line = line.strip() if not line: continue # Parse subdomain findings subdomain_info = _extract_subdomain_from_line(line, params["domain"]) if subdomain_info: finding = { "type": "subdomain", "target": subdomain_info.get("subdomain", line), "evidence": { "raw_output": line, "domain": params["domain"], "discovered_by": "fierce", }, "severity": "info", "confidence": "medium", "tags": ["fierce", "subdomain-discovery"], "raw_ref": line, } findings.append(finding) payload_bytes = len(stdout.encode("utf-8")) return { "success": True, "tool": "fierce", "params": params, "command": command, "started_at": started_at.isoformat(), "ended_at": ended_at.isoformat(), "duration_ms": duration_ms, "findings": findings, "stats": { "findings": len(findings), "dupes": 0, "payload_bytes": payload_bytes, }, }
- Helper function to extract and normalize input parameters for the 'fierce' tool from the API request JSON.def extract_fierce_params(data: dict) -> dict: """Extract and organize fierce parameters from request data.""" return { "domain": data.get("target", ""), "dns_servers": data.get("dns_servers", []), "wide": data.get("wide", False), "connect": data.get("connect", False), "delay": data.get("delay", 0), "traverse": data.get("traverse"), "range": data.get("range"), "subdomain_file": data.get("subdomain_file"), "subdomains": data.get("subdomains", []), "tcp": data.get("tcp", False), "additional_args": data.get("additional_args", ""), "timeout": data.get("timeout", 600), }