📋 目录背景介绍核心挑战解决方案完整实现测试策略最容易踩的5个坑面试高频考点总结与扩展背景介绍在Web安全扫描中,**爬虫(Crawler)和被动代理(Passive Proxy)**是两种互补的技术:爬虫的优势:✅ 主动发现隐藏页面和接口✅ 可控制扫描深度和范围✅ 自动化程度高被动代理的优势:✅ 零侵入,不影响业务✅ 只扫描真实流量✅ 能捕获JavaScript动态生成的请求xray的创新:将两者结合,形成混合扫描模式混合扫描 = 爬虫(发现URL) + 被动代理(捕获交互) + 智能调度(去重+限速)核心挑战挑战1:如何避免重复扫描?场景:1. 爬虫发现 /api/users 2. 用户访问 /api/users(被代理捕获) 3. AJAX请求 /api/users 4. ❌ 同一个URL被扫描3次 需要:多层去重机制挑战2:如何处理HTTPS流量?问题:HTTPS流量是加密的,被动代理无法直接查看内容 解决方案:MITM(中间人攻击) ├── 安装CA证书 ├── 拦截TLS握手 ├── 动态生成证书 └── 解密流量进行检测挑战3:如何智能限速?平衡点:太快 → 可能打爆目标服务器,影响业务 太慢 → 扫描时间过长,效率低下 需要:自适应速率控制 ├── 根据响应时间调整 ├── 根据错误率降级 └── 支持手动QPS设置解决方案架构设计┌─────────────────┐ ┌─────────────────┐ │ Crawler │ │ HTTP Proxy │ │ (主动爬取) │ │ (被动拦截) │ └────────┬────────┘ └────────┬────────┘ │ │ └────────┬───────────────┘ │ ▼ ┌─────────────────────────────────┐ │ URL Deduplication │ │ (Bloom Filter + HashSet) │ └────────────────┬────────────────┘ │ ▼ ┌─────────────────────────────────┐ │ Rate Limiter │ │ (Token Bucket / Sliding Window) │ └────────────────┬────────────────┘ │ ▼ ┌─────────────────────────────────┐ │ Detection Engine │ │ (执行漏洞检测) │ └─────────────────────────────────┘完整实现步骤1:基础爬虫实现pkg/crawler/crawler.gopackagecrawlerimport("net/http""golang.org/x/net/html")// Crawler Web爬虫typeCrawlerstruct{visited*BloomFilter urlQueuechanstringmaxDepthint}// Start 开始爬取func(c*Crawler)Start(startURLstring,maxDepthint){c.maxDepth=maxDepth c.urlQueue-startURLforurl:=rangec.urlQueue{// 检查深度depth:=getDepth(url)ifdepthmaxDepth{continue}// 去重ifc.visited.Contains(url){continue}c.visited.Add(url)// 爬取页面c.crawlPage(url)}}// crawlPage 爬取单个页面func(c*Crawler)crawlPage(urlstring){resp,err:=http.Get(url)iferr!=nil{return}deferresp.Body.Close()// 解析HTML,提取链接links:=extractLinks(resp.Body)// 添加到队列for_,link:=rangelinks{c.urlQueue-link}}// extractLinks 提取页面中的链接funcextractLinks(body io.Reader)[]string{varlinks[]stringtokenizer:=html.NewTokenizer(body)for{tokenType:=tokenizer.Next()iftokenType==html.ErrorToken{break}token:=tokenizer.Token()iftokenType==html.StartTagTokentoken.Data=="a"{for_,attr:=rangetoken.Attr{ifattr.Key=="href"{links=append(links,attr.Val)}}}}returnlinks}步骤2:被动代理实现pkg/proxy/mitm_proxy.gopackageproxyimport("crypto/tls""crypto/x509""net/http")// MITMProxy 中间人代理typeMITMProxystruct{caCert*x509.Certificate caKeyinterface{}server*http.Server}// NewMITMProxy 创建MITM代理funcNewMITMProxy()