
开源安全软件工程实践分析——OWASP ZAP一、项目简介与选型理由1.1 背景与目的1.2 选型理由二、软件工程视角的核心发现2.1 架构特点2.2 设计亮点2.3 可改进之处三、系统功能建模3.1用例图3.1.1识别核心用例3.1.2识别参与者3.1.3识别用例关系3.1.4绘制用例图3.2体系结构图3.2.1核心模块职责说明3.2.2模块间依赖关系说明3.2.3体系结构图四、核心设计复原4.1 核心类调用关系图4.1.1业务场景选择4.1.2核心类清单4.1.3核心类调用关系图4.2 核心类作用分析4.2.1 **ActiveScan**4.2.2 **HostProcess**4.2.3 **AbstractPlugin**五、结对编程的真实体验与反思5.1 协作模式5.2 “ 112 ”的真实体验5.3 遇到的困难解决方案5.4 与单独完成相比结对的优势和劣势一、项目简介与选型理由1.1 背景与目的在本次课程的理论学习中我们已经建立了“安全漏洞的本质往往是软件工程实践的系统性失败”这一核心认知。优秀的网络安全工程师不仅需要能够发现漏洞更需要从工程视角理解、评估和改进安全软件的设计与实现。核心训练培养快速理解中大型软件系统的工程化阅读能力掌握从代码到架构的逆向建模方法用例图、包图、类图实践Git协作开发流程体验真实团队的分支管理与代码集成从软件工程视角审视安全工具理解其设计权衡与质量属性1.2 选型理由考量维度ZAP的优势架构清晰ZAP采用模块化设计核心代理、扫描引擎、GUI、扩展加载器职责分明文档完整官方提供了详尽的架构文档和开发者指南技术栈匹配基于Java开发功能可验证功能完整可以运行并验证主动扫描、被动扫描等核心功能社区活跃拥有活跃的开源社区遇到问题容易找到解决方案二、软件工程视角的核心发现2.1 架构特点1插件化架构ZAP的几乎所有功能都是以扩展形式存在的。可扩展性新功能可以以插件形式独立开发可维护性模块间松耦合修改不影响核心可测试性每个扩展可以独立测试2分层架构ZAP采用了清晰的分层设计层次职责代表组件展示层用户交互ActiveScanPanel、CustomScanDialog控制层业务调度ActiveScanController、ExtensionActiveScan执行层核心逻辑ActiveScan、AbstractPlugin基础设施层底层支持Paros代理核心、网络通信3设计模式应用ZAP中大量运用了经典设计模式设计模式应用场景代码示例单例模式扫描调度器ActiveScanController.getInstance()模板方法模式扫描流程定义ActiveScan.run()定义扫描标准流程策略模式漏洞检测规则AbstractPlugin.scan()各子类实现不同检测逻辑观察者模式扫描结果通知ScanListener监听漏洞发现事件工厂模式插件实例化PluginFactory.getPlugins()2.2 设计亮点1扩展点设计ZAP的扩展机制使得添加任何新功能只需要继承ExtensionAdaptor类实现hook()方法注册组件将JAR包放入插件目录2策略与配置分离ScanPolicy类将扫描策略与执行逻辑分离publicclassScanPolicy{privateMapInteger,RuleConfigruleConfigs;privateStrengthdefaultStrength;privateThresholddefaultThreshold;publicListIntegergetEnabledRuleIds(){returnruleConfigs.entrySet().stream().filter(e-e.getValue().isEnabled()).map(Map.Entry::getKey).collect(Collectors.toList());}}这种设计使得用户可以灵活配置扫描策略而不需要修改代码。2.3 可改进之处1文档与代码的同步问题部分模块的官方文档更新滞后于代码实现增加了逆向分析的难度。建议可以考虑在代码注释中生成架构文档或者使用Swagger等工具自动生成API文档。2模块边界清晰度问题ascan模块和paros核心的职责边界有时不够清晰部分类在两个包中都有依赖。建议可以进一步明确模块划分原则将通用功能抽取到独立的基础模块。3配置复杂度问题扫描策略配置选项过多强度、阈值、规则开关等对新手不够友好。建议可以增加配置模板快速扫描、深度扫描、合规扫描等降低配置门槛。三、系统功能建模3.1用例图3.1.1识别核心用例用例名称功能描述证据来源主动扫描主动向目标发送攻击载荷检测SQL注入、XSS等漏洞右键站点“攻击→主动扫描”被动扫描监听通过代理的流量自动分析漏洞自动开启底部有“passive scan”图标站点爬虫遍历网站所有链接构建站点树右键站点“攻击→spider”生成报告导出HTML/PDF/XML/JSON格式的扫描报告菜单“报告→生成报告”拦截请求/响应手动修改HTTP请求后再发送界面右侧有“请求”和“响应”标签页插件管理安装/更新/卸载扩展插件顶部图标栏拼图形状的图标附加组件管理器3.1.2识别参与者参与者说明证据来源安全测试人员使用ZAP执行扫描、分析结果的人。ZAP的主要目标用户群体。目标Web服务器被测试的系统ZAP向其发送请求。ZAP作为代理与目标服务器交互。3.1.3识别用例关系包含关系包含用例被包含用例关系说明证据来源主动扫描配置扫描策略启动主动扫描前必须选择扫描规则集ActiveScanController.startScan()方法参数包含 ScanPolicy 对象若未传入则使用默认策略。主动扫描设置作用域需要明确扫描范围避免扫描无关域名HostProcess.start()检查目标是否在作用域内不在则跳过。拦截请求/响应修改请求内容拦截请求后必须提供修改请求内容的功能如修改参数、Headers、Cookie等请求/响应标签页中可直接编辑请求的Header、Body内容生成报告选择报告模板生成报告前必须选择报告模板菜单“报告”→“生成报告”→下拉选择“模板”扩展关系扩展用例基础用例关系说明证据来源断点调试拦截请求/响应在拦截请求/响应时可选地开启断点调试模式工具栏红色/绿色圆形按钮全局断点开关。安装/更新插件插件管理可选安装、更新、卸载插件的操作顶部“管理附加组件”图标 → “安装、更新、卸载所选”按钮设置作用域被动扫描可选是否仅扫描作用域内工具→选项→被动扫描器→“仅扫描作用域内站点”选项3.1.4绘制用例图图1 用例图3.2体系结构图3.2.1核心模块职责说明模块名称对应包名核心职责推断依据用户界面org.zaproxy.zap.view负责用户交互、菜单显示、扫描结果展示、配置管理包名直观表明为视图层代码中包含 View 类、对话框、面板等 Swing 组件扩展插件org.zaproxy.zap.extension定义插件生命周期和加载机制所有功能模块均继承此抽象类ZAP 采用插件化架构是系统的扩展基石主动扫描org.zaproxy.zap.extension.ascan实现主动攻击型漏洞检测主动向目标发送攻击请求包含 ActiveScan 类对应 ZAP 的主动扫描功能菜单被动扫描org.zaproxy.zap.extension.pscan实现流量监听型漏洞检测分析代理流量而不主动发送请求包含PassiveScan 类对应 ZAP 的被动扫描功能代理核心org.parosproxy.paros.core.proxy作为中间人代理负责拦截、解析、转发 HTTP/HTTPS 流量ZAP 前身是 Paros Proxy该包是代理功能的核心实现扫描引擎org.parosproxy.paros.core.scanner提供漏洞检测的底层框架和算法定义扫描插件的执行逻辑包含 Scanner、Plugin 等抽象类是扫描功能的底层支撑3.2.2模块间依赖关系说明依赖关系关系说明用户界面 → 扩展插件GUI 需要通过扩展插件框架获取插件列表、调用插件功能图形用户 → 代理核心GUI 需要启动/停止代理显示代理拦截的流量扩展插件 → 主动扫描扩展插件框架作为基类主动扫描模块是它的具体实现扩展插件 → 被动扫描扩展插件框架作为基类被动扫描模块是它的具体实现主动扫描 → 扫描引擎主动扫描调用扫描引擎核心中的扫描插件执行攻击检测被动扫描 → 扫描引擎被动扫描也使用相同的扫描引擎框架进行分析代理核心 → 扫描引擎代理拦截流量后将流量数据传递给扫描引擎进行检测3.2.3体系结构图图2 体系结构图四、核心设计复原4.1 核心类调用关系图4.1.1业务场景选择选择“ZAP 启动主动扫描”作为典型业务场景主要基于以下三点功能核心性主动扫描是 ZAP 作为漏洞扫描工具最核心、最常用的功能代表了工具的主要使用场景用户从点击按钮到发现漏洞的完整流程具有高度代表性。调用链路清晰该场景涉及的七个核心类层次分明界面层→控制层→任务层→引擎层→插件层→数据层方法调用顺序明确从ActiveScanPanel接收用户输入到Alert生成漏洞报告形成完整的请求-响应-分析-告警链路。设计模式典型该场景体现了控制器模式ActiveScanController管理多任务、工厂模式PluginFactory加载插件、观察者模式alertFound回调通知等多种经典设计模式。4.1.2核心类清单类名全限定名文件路径ActiveScanPanelorg.zaproxy.zap.extension.ascan.ActiveScanPanelzap/src/main/java/org/zaproxy/zap/extension/ascan/ActiveScanPanel.javaActiveScanControllerorg.zaproxy.zap.extension.ascan.ActiveScanControllerzap/src/main/java/org/zaproxy/zap/extension/ascan/ActiveScanController.javaActiveScanorg.zaproxy.zap.extension.ascan.ActiveScanzap/src/main/java/org/zaproxy/zap/extension/ascan/ActiveScan.javaHostProcessorg.parosproxy.paros.core.scanner.HostProcesszap/src/main/java/org/parosproxy/paros/core/scanner/HostProcess.javaPluginFactoryorg.parosproxy.paros.core.scanner.PluginFactoryzap/src/main/java/org/parosproxy/paros/core/scanner/PluginFactory.javaAbstractPluginorg.parosproxy.paros.core.scanner.AbstractPluginzap/src/main/java/org/parosproxy/paros/core/scanner/AbstractPlugin.javaAlertorg.parosproxy.paros.core.scanner.Alertzap/src/main/java/org/parosproxy/paros/core/scanner/Alert.java4.1.3核心类调用关系图图3 核心类调用关系图4.2 核心类作用分析4.2.1ActiveScan(1) 类名org.zaproxy.zap.extension.ascan.ActiveScan(2) 所属模块扫描引擎层 - 扫描控制器(3) 核心职责单次主动扫描任务的执行控制器负责协调扫描流程、状态管理、进度统计和结果收集(4) 关键方法start(Targettarget)启动扫描任务初始化计时器和统计线程stopScan()停止当前扫描关闭调度器hostProgress(intid, String hostAndPort, String msg, int percentage)接收进度回调计算平均进度并发布事件notifyNewMessage(finalHttpMessage msg)记录发送的HTTP消息更新UI表格alertFound(Alertalert)收集发现的漏洞ID(5) 设计模式观察者模式实现ScannerListener接口监听扫描事件同时通过ActiveScanEventPublisher发布事件publicclassActiveScanextendsorg.parosproxy.paros.core.scanner.ScannerimplementsGenericScanner2,ScannerListener{…}(6)与你选择的场景的关系ActiveScan是主动扫描场景的核心执行器。它负责启动扫描线程、调度扫描插件、收集扫描结果并通过观察者模式将进度和结果实时反馈给UI。所有扫描任务的生命周期都由它管理。4.2.2HostProcess(1) 类名org.parosproxy.paros.core.scanner.HostProcess(2) 所属模块扫描引擎层 – 站点扫描引擎(3) 核心职责负责单个站点host:port的主动扫描调度管理插件执行顺序、请求发送、进度统计和结果收集(4) 关键方法run()扫描主线程入口遍历节点、调度插件执行processPlugin(Pluginplugin)处理单个插件的执行根据插件类型Host/App决定扫描策略scanMessage(Pluginplugin, int messageId)对单个消息执行插件扫描创建插件实例并提交到线程池alertFound(Alertalert)收集发现的漏洞更新统计信息(5) 设计模式策略模式不同类型的插件AbstractHostPlugin/ AbstractAppPlugin采用不同的扫描策略if(plugininstanceofAbstractHostPlugin){scanMessage(plugin,messageIdToHostScan);}elseif(plugininstanceofAbstractAppPlugin){for(intmessageId:messagesIdsToAppScan){scanMessage(plugin,messageId);}}(6) 与你选择的场景的关系HostProcess是主动扫描场景的核心执行引擎。当用户启动扫描后ActiveScan会为每个目标站点创建一个HostProcess实例它负责遍历站点节点、调度所有启用的扫描插件、发送攻击请求并收集结果。没有HostProcess整个扫描流程无法执行。4.2.3AbstractPlugin(1) 类名org.parosproxy.paros.core.scanner.AbstractPlugin(2) 所属模块扫描引擎层 – 插件基类(3) 核心职责所有主动扫描插件的抽象基类定义攻击执行的通用流程、请求发送方法、漏洞上报接口(4) 关键方法run()插件执行入口调用子类的scan()方法scan()抽象方法子类实现具体的攻击检测逻辑sendAndReceive(HttpMessagemsg)发送HTTP请求并接收响应处理重定向、Anti-CSRF等newAlert()创建AlertBuilder用于构建和上报漏洞(5) 设计模式a. 策略模式不同的阈值和强度影响扫描行为AlertThreshold和AttackStrength枚举privateAlertThresholddefaultAttackThresholdAlertThreshold.MEDIUM;privateAttackStrengthdefaultAttackStrengthAttackStrength.MEDIUM;b. 工厂方法模式newAlert()创建AlertBuilderprotectedAlertBuildernewAlert()c. 观察者模式通过parent.notifyNewMessage()回调通知parent.notifyNewMessage(this,message)(6) 与你选择的场景的关系AbstractPlugin是主动扫描场景中所有攻击规则的基础。每个具体的漏洞检测规则如SQL注入、XSS、命令注入等都是AbstractPlugin的子类。在扫描过程中HostProcess创建插件实例调用run()方法run()内部调用子类实现的scan()方法执行具体攻击并通过sendAndReceive()发送请求最后通过newAlert().raise()上报发现的漏洞。五、结对编程的真实体验与反思5.1 协作模式本次作业我们采用角色交替的模式轮流作为Driver和Navigator角色切换依据/时机每个任务开始前确定Driver在自己擅长的领域作为Driver例如在我们两人之间我更擅长Java的代码分析那么我可以作为核心类识别这一任务的Driver在遇到困难时及时沟通理解更好/透彻的可以作为执行者5.2 “ 112 ”的真实体验效率提升两人负责自己擅长的领域使得合作更加顺利、高效、理解更加透彻精准在任务3和任务4中两人并行推进不同模块显著缩短了整体完成时间。遇到理解卡点时双人讨论也比单人查阅资料更快定位问题。互相审查减少错误在各自完成分工后我们会交叉审核对方的产出两人互相验证确保理解准确避免错误5.3 遇到的困难解决方案代码理解不一致困难在确定哪些是主动扫描的核心类时我们两人的意见不完全一致我认为ActiveScanController和ActiveScan是最核心的类因为它们在调用链中处于枢纽位置体现了单例模式和模板方法模式而吴惠敏持不同观点。解决方案为了接解决这一问题我们共同追踪了主动扫描的调用链逐环节商讨最终达成共识认为ActiveScan、HostProcess、AbstractPlugin作为核心类体现了执行控制、规则调度、规则实现的职责分离原则。沟通成本困难在确认好分工之后在完成任务时我们两人的沟通不够频繁、及时导致在完成任务4确定核心类时出现两人有不同的理解且都在各自理解的基础上进一步完成任务。解决方案在发现这一问题后我们立刻沟通统一对核心类的判断并在之后保持及时沟通、告知对方当前的任务完成进度遇到不确定的问题立刻讨论想法和观点。沟通成本困难在确认好分工之后在完成任务时我们两人的沟通不够频繁、及时导致在完成任务4确定核心类时出现两人有不同的理解且都在各自理解的基础上进一步完成任务。解决方案在发现这一问题后我们立刻沟通统一对核心类的判断并在之后保持及时沟通、告知对方当前的任务完成进度遇到不确定的问题立刻讨论想法和观点。5.4 与单独完成相比结对的优势和劣势优势分析任务完成的质量更高双向审查有效减少了个人盲区带来的遗漏和错误效率更高两人并行推进不同模块整体完成时间明显缩短理解更加深入两人相互督避免拖延促提高效率共同分担任务整体压力比独自完成时更小发挥各自所长使分析过程更加顺畅、顺利劣势对代码的理解存在差异分工无法做到完全均等、可能会职责划分不清淅远程协作时无法做到面对面即时沟通沟通效率受影响需要花费额外的时间进行同步和沟通