一、写在前面

在软件工程课程中,老师反复强调一个观点:安全漏洞的本质往往是软件工程实践的系统性失败。也就是说,很多漏洞的产生,根源不在于某个具体的代码错误,而在于整个软件的设计、架构、开发流程中存在系统性问题。

本次作业要求我们选择一款开源安全软件,通过逆向工程的方式复原其软件架构、设计决策和工程实践。我选择了 OWASP ZAP(Zed Attack Proxy)——全球最流行的Web应用安全扫描器之一。

本文记录了我从零开始分析ZAP源码、绘制UML图、理解其设计模式的全过程,希望能给同样在学习软件工程的同学一些参考。

二、为什么选择ZAP

在四个候选项目中(ZAP、Snort、YARA、Zeek),我最终选择了ZAP,原因很简单:

考量因素 ZAP的特点
文档完善度 OWASP旗舰项目,官方文档非常详细
技术栈熟悉度 使用Java + Swing,对我来说更容易上手
架构清晰度 扩展加载器 + 插件机制,分层明确
实际操作性 图形界面,运行后能直观看到扫描过程

事实证明,这个选择是对的。ZAP的代码结构比我想象中要规范,尤其是extension包下的扩展机制,很好地体现了插件化设计的思路。

三、环境搭建与功能验证

3.1 安装过程

按照官方文档,ZAP提供两种安装方式:

  • 安装包方式:下载.exe直接安装(我选了这个)

  • 源码编译方式:用Gradle构建

安装完成后,双击启动,底部状态栏显示Proxy: localhost:8080,说明代理服务启动成功。

3.2 测试靶场选择

测试靶场是最难找的环节——很多在线靶场已经关停了。最后我找到了一个依然可用的:http://demo.testfire.net(Security Innovation公司提供的演示应用)。

3.3 执行主动扫描

操作步骤很简单:

  1. 启动ZAP,点击"手动浏览"

  2. 输入靶场地址,ZAP自动打开配置好代理的浏览器

  3. 浏览几个页面,让ZAP记录URL

  4. 右键点击目标 → 攻击 → 主动扫描

  5. 等待扫描完成,查看"警报"选项卡

扫描结果让人惊喜——确实扫出了SQL注入、XSS、缺少安全头等多种漏洞。

3.4 遇到的坑
  • Java版本问题:第一次启动提示Java版本过低,检查发现是1.8,需要升级到JDK 11+

  • 测试靶场失效:原本推荐的testphp.vulnweb.com已无法访问,花了些时间才找到替代的demo.testfire.net

四、系统功能建模(UML图)

4.1 用例图

通过分析ZAP的实际功能,我绘制了以下用例图:

用例 功能说明 证据来源
主动扫描 主动发送攻击请求检测漏洞 任务1实际操作
被动扫描 分析代理流量发现安全问题 ZAP官方文档
生成报告 导出扫描结果为HTML 任务1实际操作
管理会话 保存/加载扫描会话 ZAP菜单功能
插件管理 安装/更新扩展插件 插件市场功能

用例关系:

  • 主动扫描 <<include>> 被动扫描

  • 生成报告 <<extend>> 主动扫描

4.2 体系结构图

ZAP采用分层模块化架构,核心模块包括:

模块 职责 推断依据
GUI 用户图形界面 技术栈明确使用Swing
扩展加载器 动态加载插件 官方架构文档描述
扫描引擎 漏洞检测核心 任务1主动扫描功能
代理核心 HTTP/HTTPS代理 ZAP前身为Paros Proxy

模块依赖关系:GUI → 扩展加载器 → 扫描引擎 → 代理核心

五、核心设计复原

5.1 典型场景:主动扫描

选择这个场景是因为它最典型、调用链最完整。我从源码中找到了6个核心类:

类名 文件路径 职责
ExtensionActiveScan ascan/ExtensionActiveScan.java 主动扫描扩展入口
ActiveScan ascan/ActiveScan.java 扫描任务管理
ActiveScanController ascan/ActiveScanController.java 扫描控制器
ActiveScanAPI ascan/ActiveScanAPI.java API接口层
HostProcess scanner/HostProcess.java 单主机扫描处理器
Plugin scanner/Plugin.java 扫描插件接口
5.2 序列图

基于以上类,我绘制了主动扫描的序列图:

核心调用链:

用户 → ActiveScanAPI → ExtensionActiveScan → ActiveScanController → ActiveScan → HostProcess → Plugin

5.3 三个核心类分析

类1:ActiveScanAPI

  • 职责:REST API入口,接收扫描请求

  • 设计模式:外观模式,简化调用接口

类2:HostProcess

  • 职责:处理单个主机的扫描,管理插件执行队列

  • 设计模式:模板方法模式,run()定义扫描框架

类3:Plugin

  • 职责:定义扫描插件接口

  • 设计模式:策略模式,不同插件实现不同检测策略

5.4 设计模式总结
设计模式 应用位置 作用
外观模式 ActiveScanAPI 简化API调用
模板方法模式 HostProcess.run() 定义扫描流程框架
策略模式 Plugin接口 不同插件不同检测策略
观察者模式 ScannerListener 扫描进度通知UI

六、Git协作实践

作业要求模拟两人协作,但我只有一个人,所以采用一人模拟两人协作 + AI结对的方式。

6.1 仓库结构
security-analysis-zap/
├── src/           # 核心类代码片段
├── doc/
│   ├── demo/      # 演示视频
│   ├── diagrams/  # UML图源文件
│   └── report/    # 最终报告
6.2 分支模型
  • master:稳定版本(组长维护)

  • dev:开发分支(组员提交)

6.3 提交历史

通过使用不同的提交信息风格,模拟了两个人的协作。

七、与AI结对:真实的体验与反思

7.1 我是怎么和AI配合的

这次作业全程和DeepSeek结对,AI扮演的是"领航员"角色:

  • 遇到卡点时:直接问"主动扫描的核心调用链是什么""序列图怎么画"

  • AI给出起点后:我去源码里验证,确认正确性

  • 反复迭代:调整UML图、优化代码片段

7.2 1+1 > 2 吗?

答案是:显著大于2

AI帮我省下了大量"找路"的时间——原本可能要花一整天梳理的调用关系,在AI的辅助下半天就理清了。而且AI随时在线,不用等回复,遇到问题能立刻得到参考思路。

7.3 也有坑
  • AI的答案不一定准:推荐的类名在源码里找不到,后来我养成习惯——AI说的都去验证一遍

  • 容易钻牛角尖:一个人容易在细节上纠结太久,后来学会先完成再优化

7.4 量化评估

我用Mermaid生成了两个图表来量化协作效果:

任务完成分布饼图

  • 任务3(系统建模):30%

  • 任务4(核心设计):30%

  • 任务1(环境搭建):20%

  • 任务2(Git协作):15%

  • 任务5(过程反思):5%

协作能力雷达图

  • 代码规范:8/10

  • 设计能力:7/10

  • 沟通主动性:7/10

  • 问题解决:7/10

  • 知识传递:6.5/10

八、从软件工程视角看ZAP

8.1 架构亮点
  1. 插件化设计:通过扩展加载器实现功能动态加载,核心与扩展解耦

  2. 分层清晰:表现层 → 业务逻辑层 → 核心层,职责明确

  3. 设计模式应用得当:外观、模板方法、策略、观察者各司其职

8.2 可改进之处
  1. 类职责过重ActiveScan承担了太多职责,可以进一步拆分

  2. UI与核心耦合:部分UI代码直接依赖核心类,不够解耦

  3. 文档滞后:部分官方文档链接已失效,需要从源码和Wiki补全

九、写在最后

这次作业让我深刻体会到:读懂一个开源项目,不是把每一行代码都看一遍,而是理解它的骨架和设计思路

ZAP的源码规模很大(几十万行),但通过"自顶向下"的方法——先看官方文档,再运行起来跟踪核心流程,最后聚焦2-3个关键包——还是能够快速建立整体认知。

如果你也在学习软件工程,或者对开源安全工具感兴趣,希望这篇文章对你有帮助。

博客互动:欢迎在评论区留言讨论,也欢迎点赞转发~


Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐