Nmap + Masscan + ffuf 实战:扫描流水线 + 自动化脚本

前言

Masscan 找"活的",Nmap 回答"是什么",ffuf 发现"藏了什么"。本文给出完整扫描流水线和可直接用的脚本。


一、Masscan(全端口秒扫)

1.1 基础用法

# 全端口扫描(1-65535)
masscan example.com -p1-65535 --rate=10000 -oL masscan.txt

# 网段扫描
masscan 10.0.0.0/24 -p1-65535 --rate=50000 -oL masscan.txt

# 高危端口快速扫
masscan example.com -p21,22,23,25,53,80,110,135,139,143,443,445,1433,1521,3306,3389,5432,6379,7001,8080,8443,9090 --rate=50000

# 从文件读 IP
masscan -iL targets.txt -p1-65535 --rate=50000 -oL masscan.txt

# 多种输出
masscan example.com -p1-65535 -oL a.txt -oJ b.json -oG c.gnmap

1.2 高级参数

# 设置源端口(某些防火墙会过滤)
masscan example.com -p80 --source-port 53 --rate=1000

# 设置源 IP(多网卡环境)
masscan example.com -p80 -e eth0 --adapter-ip 192.168.1.100

# 随机化扫描顺序
masscan example.com -p1-65535 --randomize-hosts

# 排除某些 IP
masscan example.com -p1-65535 --excludefile exclude.txt

# 等待所有响应后退出
masscan example.com -p1-65535 --wait=10

二、Nmap(服务识别 + 漏洞扫描)

2.1 基础用法

# 快速扫描常见端口 + 服务识别
nmap -sV -sC example.com -oN nmap.txt

# 全端口扫描(慢但全)
nmap -sV -sC -p- --min-rate 1000 example.com -oN nmap_full.txt

# 操作系统检测
nmap -O example.com

# 漏洞扫描脚本
nmap --script vuln example.com -oN nmap_vuln.txt

# Masscan -> Nmap 管道
masscan example.com -p1-65535 --rate=10000 -oL masscan.txt
PORTS=$(grep open masscan.txt | awk '{print $4}' | cut -d: -f2 | sort -un | tr '\n' ',')
nmap -sV -sC -p "$PORTS" example.com -oN nmap_targeted.txt

# 批量扫描多主机
nmap -iL alive.txt -sV -sC -oN nmap_batch.txt

2.2 NSE 脚本速查

# 暴力破解
nmap --script ftp-brute,http-brute,mysql-brute,smb-brute example.com

# 漏洞检测
nmap --script vuln example.com
nmap --script http-vuln-cve2021-44228 example.com   # Log4Shell
nmap --script http-vuln-cve2021-40444 example.com   # MSHTML

# 信息收集
nmap --script http-headers,http-title,http-methods example.com
nmap --script dns-brute example.com
nmap --script smb-os-discovery,smb-enum-shares example.com

# SSL 检查
nmap --script ssl-enum-ciphers,ssl-cert example.com

# 完整高危漏洞扫描
nmap --script "vuln and safe" example.com

2.3 Nmap XML 解析脚本

#!/usr/bin/env python3
"""Parse Nmap XML output into structured report."""
import xml.etree.ElementTree as ET
import sys

def parse_nmap_xml(xml_path):
    tree = ET.parse(xml_path)
    root = tree.getroot()
    results = []
    for host in root.findall("host"):
        ip = host.find("address").get("addr")
        ports = []
        for port in host.findall(".//port"):
            portid = port.get("portid")
            proto = port.get("protocol")
            state = port.find("state").get("state")
            svc = port.find("service")
            service = svc.get("name", "") if svc is not None else ""
            product = svc.get("product", "") if svc is not None else ""
            version = svc.get("version", "") if svc is not None else ""
            ports.append({
                "port": int(portid), "proto": proto, "state": state,
                "service": service, "product": product, "version": version
            })
        results.append({"ip": ip, "ports": ports})
    return results

if __name__ == "__main__":
    data = parse_nmap_xml(sys.argv[1])
    for host in data:
        print()
        print("=" * 60)
        print("Host:", host["ip"])
        print("=" * 60)
        for p in host["ports"]:
            banner = (p["product"] + " " + p["version"]).strip()
            print(f"  {p['port']:>5}/{p['proto']}  {p['state']:>7}  {p['service']:<15}  {banner}")

三、ffuf(目录 + 参数 Fuzz)

3.1 目录爆破

# 基础
ffuf -u "http://example.com/FUZZ" -w ~/wordlists/directory-list-2.3-medium.txt      -mc 200,301,302,403,500 -t 50 -o ffuf_dir.txt

# 带扩展名 + 大小写变体
ffuf -u "http://example.com/FUZZ" -w dirs.txt -e php,asp,aspx,jsp,html,txt,bak,zip,swp

# 过滤已知 404 页面大小
ffuf -u "http://example.com/FUZZ" -w dirs.txt -fs 1234 -t 50

# HTTPS + 忽略证书
ffuf -u "https://example.com/FUZZ" -w dirs.txt -k

# 自定义 Header
ffuf -u "http://example.com/FUZZ" -w dirs.txt -H "Authorization: Bearer xxx"

# POST Body Fuzz
ffuf -u "http://example.com/api/FUZZ" -w api.txt -X POST -d "data=FUZZ"

# 递归(爬一层再爬一层)
ffuf -u "http://example.com/FUZZ" -w dirs.txt -mc 200 -t 50 -of json -o l1.json
jq -r ".results[].input.FUZZ" l1.json | while read d; do
  ffuf -u "http://example.com/$d/FUZZ" -w subdirs.txt -mc 200 -t 50 -o "l2_$d.txt"
done

3.2 参数枚举

# GET 参数
ffuf -u "http://example.com/page?FUZZ=test" -w params.txt -mc 200 -fs 0

# POST 参数
ffuf -u "http://example.com/api/user" -w params.txt -X POST -d "FUZZ=test"      -H "Content-Type: application/x-www-form-urlencoded"

# JSON 参数
ffuf -u "http://example.com/api/user" -w params.txt -X POST -d '{"FUZZ":"test"}'      -H "Content-Type: application/json"

# Arjun(专门的参数发现工具)
python3 arjun.py -u http://example.com --rate-limit 10
python3 arjun.py -i urls.txt --output json -o params.json

3.3 字典推荐

综合目录字典:
- directory-list-2.3-medium.txt(22 万条,够用)
- raft-medium-directories.txt
- wordlist/raft-large-directories.txt

子域名 / API / 敏感文件:
- subdomains-top10000.txt
- PayloadsAllTheThings 里的 API 字典
- Seclists: https://github.com/danielmiessler/SecLists

四、完整扫描流水线脚本

#!/bin/bash
# full_scan.sh - Masscan + Nmap + ffuf 流水线
DOMAIN=$1
OUT="./scan_$DOMAIN"
mkdir -p "$OUT" && cd "$OUT"

echo "[1/5] 子域名枚举..."
subfinder -d "$DOMAIN" -silent > subs.txt
echo "  -> $(wc -l < subs.txt) 个子域名"

echo "[2/5] 存活探测..."
cat subs.txt | httpx -silent -title -o alive_web.txt
echo "  -> $(wc -l < alive_web.txt) 个活跃 Web"

echo "[3/5] 端口扫描..."
cat subs.txt | httpx -silent -ip | awk '{print $NF}' | sort -u > ips.txt
masscan -iL ips.txt -p1-65535 --rate=50000 -oL masscan.txt
echo "  -> Masscan 完成"

echo "[4/5] Nmap 服务识别..."
grep open masscan.txt | awk '{print $4}' | cut -d: -f1 | sort -u | while read ip; do
  ports=$(grep "Open.*${ip}" masscan.txt | awk '{print $NF}' | cut -d/ -f1 | sort -un | tr '\n' ',')
  nmap -sV -sC -p "${ports%,}" "$ip" -oN "nmap_${ip}.txt" &
done
wait
echo "  -> Nmap 完成"

echo "[5/5] 目录爆破..."
while read url; do
  ffuf -u "${url}/FUZZ" -w ~/wordlists/directory-list-2.3-medium.txt        -mc 200,301,302,403 -t 30 -o "ffuf_$(echo $url | sed 's|https\?://||;s|/$||').txt" &
done < alive_web.txt
wait
echo "  -> ffuf 完成"

echo ""
echo "===== 扫描完成 ====="
echo "活跃 Web: $(wc -l < alive_web.txt)"
echo "开放端口: $(grep -c open masscan.txt)"
echo "Nmap 文件: $(ls nmap_*.txt 2>/dev/null | wc -l)"
echo "ffuf 结果: $(ls ffuf_*.txt 2>/dev/null | wc -l)"

五、各工具职责 + 常见坑

Masscan 常见坑:
- masscan -p1-65535 example.com 扫的是 C 段,不是该域名的所有 IP
  应该先解析域名到 IP 再扫
- --rate 太高会丢包,生产环境建议 1000-5000
- masscan 不会做 DNS 反查

Nmap 常见坑:
- -p- 全端口扫很慢,先用 masscan 筛出开放端口再用 nmap
- --min-rate 不要太大,会丢包
- -sV 服务识别是探测包,生产环境慎用

ffuf 常见坑:
- -fs 响应大小过滤很重要
- -fw 过滤特定字数也好用
- FUZZ 和 fuzz 的位置要对(大小写敏感)
- 先跑小字典验证,再跑大字典

三者配合:
Masscan 快速找出开放端口
  -> Nmap 识别是什么服务
    -> ffuf 找隐藏路径

六、推荐资源