介绍
应用依赖其他项目编写的库。即使你自己的程序看起来运行正常,所使用的库仍可能存在已知弱点。这个 DeskLite 工单客户端使用了存在漏洞的 Python HTTP 库 Requests 版本。
你将解读固定的离线漏洞公告,更新客户端实际导入的软件包,并同时检查功能和版本记录。隔离的 Python 环境、安装缓存和包含两条漏洞公告的课程快照均已准备好。无需软件包管理或 Python 编程经验。
运行客户端并检查软件包
在本步骤中,你将确认客户端当前的业务行为,并定位已安装的依赖。
依赖是应用使用的软件。这个客户端直接使用 requests 发起 HTTP 请求;Requests 自身又使用另一个库 urllib3 来完成部分工作。第二层关系称为传递依赖。
cd /home/labex/project/desklite-dependencies
.venv/bin/python 是为本项目准备的隔离 Python 可执行文件。它的软件包与系统 Python 分离。无需激活命令或全局安装。像在 Git 实验中运行提供的程序一样,运行客户端:
.venv/bin/python app.py
预期显示标题为 Printer offline 的原始工单。程序在安全修复前就能正常工作;已知依赖问题并不意味着每次请求都已失败。
pip 管理 Python 软件包。-m pip 告诉同一个隔离 Python 运行其软件包管理器,而 show 只读取元数据,不作任何更改:
.venv/bin/python -m pip show requests urllib3
找到 Name、Version 和 Location。Requests 应为 2.32.3,urllib3 应为 2.2.2,软件包位置应在本项目的 .venv 内。我们将更新这个环境,而非另一个 Python 安装环境。
解读离线漏洞公告的扫描发现
在本步骤中,你将把扫描器的发现与需要处理的软件包版本联系起来。
预置的 course-deps 启动器运行 OSV-Scanner 2.7.0,使用日期为 2026-10-28 的固定本地快照。这个有意保持小规模的快照包含针对 Requests 和 urllib3 的两条选定漏洞公告;它是教学用数据,并非当前完整的生产环境漏洞数据源。该命令不发起网络请求。
向它提供预置的锁定记录文件:
course-deps requirements.lock
预期出现包含 requests 2.32.3、GHSA-9hjg-9r4m-mvj7、CVE-2024-47081 和 fixed: 2.32.4 的行,随后显示 Security findings: 1。两个 ID 分别在不同漏洞公告体系中标识同一个问题。
这条公告涉及特定构造的 URL 与已存储的客户端凭据交互时,可能发生的凭据泄漏。这里无需复现攻击或配置那些凭据。你的任务是安装提供的兼容修复版本,并保留普通请求功能。
命令发现已知问题时,会按预期以状态 1 退出。CHECK ERROR 表示扫描无法完成,退出状态为 2;这不是安全的证据。严重程度评级有助于确定审查优先级,但并不能说明本应用已遭利用。
报告提供了修复版本。下一步,你将把报告与用于安装和复现环境的文件联系起来。
区分依赖声明和实际安装状态
在本步骤中,你将读取固定版本的安装清单,以及解析后环境的记录。
cat requirements.txt
每行采用 package==version 格式。双等号将软件包固定到某个版本。本课程清单同时包含直接依赖及其已解析的支持软件包,以便离线复现安装。
Requests 被固定为 2.32.3。扫描报告指出,缓存中提供的兼容修复版本是 2.32.4。保留所有无关行。
cat requirements.lock
锁定记录描述解析后软件包的准确版本。这里使用简单的、完全固定版本的 requirements 格式文件。它最初与安装清单一致。更新后,你将从实际环境重新生成它,而不是仅靠编辑文本就声称软件包已更改。
存在三个不同状态:requirements.txt 中的预期版本、.venv 内实际安装的软件包,以及 requirements.lock 中的解析结果记录。交付时三者必须一致。扫描器读取你指定的文件;它不会自动证明运行中的应用导入了这些版本。
/opt/labex-dependency-tools/wheels 下的缓存包含预置初始软件包和修复版本。你将从该缓存安装,因此无需在线查找版本或解决依赖冲突。
安装兼容的修复版本
在本步骤中,你将更新安装清单,并把修复后的软件包安装到项目的实际环境中。
nano requirements.txt
只将 requests==2.32.3 改为 requests==2.32.4。保留其他每个固定版本。使用 Ctrl+O、Enter、Ctrl+X 保存并退出。
现在,使用同一环境的软件包管理器。install 更改已安装的软件包;-r requirements.txt 读取指定的安装清单。--no-index 禁用在线软件包索引,--find-links 将 pip 指向预置 wheel 文件。wheel 是预构建的 Python 安装包:
.venv/bin/python -m pip install --no-index --find-links /opt/labex-dependency-tools/wheels -r requirements.txt
Pip 应将 Requests 2.32.3 替换为 2.32.4,同时其他固定版本的软件包仍满足要求。关注指定的版本变化;进度消息可能不同。不要直接运行系统 pip,因为它可能更新另一个环境。
.venv/bin/python -m pip show requests
预期显示 Version: 2.32.4,且位置位于本项目的 .venv 内。仅保存清单不足以确认这一安装状态。客户端是每次运行时都会导入软件包的一次性程序,因此之后的请求将使用更新后的环境。
重新生成锁定记录
在本步骤中,你将让解析后的版本记录准确描述实际安装的软件包。
pip freeze 打印环境中已安装软件包的固定版本。Shell 运算符 > 将输出写入文件,而非终端,并替换文件原有内容。这里指定的目标就是项目锁定记录:
.venv/bin/python -m pip freeze > requirements.lock
命令通常不打印内容,因为输出已写入文件。读取该文件:
cat requirements.lock
Requests 现在应为 2.32.4;其他依赖版本应保持不变。顺序或大小写可能不同,但不会改变记录的是哪些软件包。
使用 pip check 检查软件包兼容性,它会检查声明的依赖关系:
.venv/bin/python -m pip check
预期显示 No broken requirements found.。它检查的是软件包兼容性,而非应用的业务行为或所有潜在漏洞。
现在,安装意图、已安装软件包和解析结果记录已保持一致。锁定文件是真实的环境复现产物,并非用来证明命令运行过的复制报告。使用其他有效的等价方法生成相同且准确的固定版本记录,也符合结果要求。
运行功能回归检查
在本步骤中,你将确认库更新后,原始请求和响应仍然正常。
回归问题是指某项变更破坏了原先正常工作的行为。课程提供 test.sh,用于对原始客户端进行小型功能检查。这里学习的是运行检查;编写测试将在以后学习。
bash test.sh
预期输出:
PASS: original ticket request and response.
检查会实际运行客户端,请求本地工单服务,并比较返回的数据。它不会把版本字符串变化当作业务成功。
再亲自运行一次客户端:
.venv/bin/python app.py
预期显示 ID 为 1、标题为 Printer offline 的原始工单。删除客户端或移除其依赖都无法保留这一行为。
磁盘上的库已更新,新启动的客户端会导入它。长时间运行的应用在依赖更新后,可能需要单独进行受控重启;本实验客户端每次都会重新运行。最后一步将使用准确的锁定记录重新检查已知问题。
重新扫描交付的依赖状态
在本步骤中,你将综合固定快照扫描、已安装软件包和业务行为的证据。
使用同一个离线扫描器检查更新后的锁定记录:
course-deps requirements.lock
预期显示 No findings in the selected course snapshot.。这明确表示,选定的漏洞公告不再匹配记录的版本。它并不能证明快照涵盖了所有当前或未来问题。
检查预期固定版本和实际安装的软件包:
cat requirements.txt
.venv/bin/python -m pip show requests
文件和环境中的 Requests 都应为 2.32.4;无关的固定版本保持不变。上一步的功能检查证明了另一个要求:更新后的客户端仍然执行原始请求。
完整修复需要这两类证据。只编辑清单可能让存在漏洞的安装继续被使用。更新安装却不记录,会让后续复现变得不可靠。跳过扫描器或删除依赖只会隐藏证据,无法修复所要求的应用。
无需调查文档或复制的扫描报告。交付成果是实际更新的软件包环境、准确的固定版本记录,以及保留的业务行为。
总结
你将离线漏洞公告与实际安装的 Python 依赖联系起来,从预置缓存安装了兼容的修复软件包,并同步了预期版本和解析结果记录。重新扫描和真实功能请求证实,在明确限定的课程快照范围内,目标问题已修复,原有行为得以保留。



