追踪并吊销泄露密钥

网络安全Beginner
立即练习

介绍

一个支持摘要任务会读取客户工单,并发布简短摘要。有人从仓库最新的示例中删除了它的 API 密钥,但使用该值的请求仍然成功。你是负责调查这条告警的维护人员。

先了解正常请求流程,再恢复历史证据、识别凭据并吊销它。你将使用本地模拟服务、两个预配置的终端角色和 Key Manager。掌握基本终端操作即可;本实验会介绍 Git、API 请求和密钥吊销。

通过 API 读取工单

本步骤中,你将发送工单读取请求,并学习识别响应内容。支持工单是客户的求助请求。摘要任务是一个预置程序,读取一批工单,再把简短摘要发送给服务。集成就是一个程序与另一个程序协同工作。

在实验界面选择 Workstation 标签页,开始本步骤。

本实验使用本地教学服务,客户和密钥均为合成数据。API 实际执行请求认证与权限检查,但并非某个云服务的复制品,也不涉及真实账号或外部目标。

使用两个终端角色

Workstation 是维护终端,打开后位于保存示例配置的 /home/labex/project/repository。Integration 以 keyworker 账号运行,该账号拥有任务的私有运行配置。请在指定终端执行各条命令;切换目录不会改变账号。Key Manager 标签页通过独立的操作员登录来管理凭据。

在 Workstation 中,pwd 打印当前目录,ls 列出其中的文件名:

运行以下命令前,请切换到 Workstation 标签页。

pwd
/home/labex/project/repository
ls

应当看到 README.md 和 summary-example.ini。它们是仓库示例,并非运行中的任务读取的私有文件。

理解请求接口

API 是服务接收程序请求的接口。端点由操作和路径组成。这里,GET /v1/tickets 读取工单,POST /v1/summaries 发布摘要。http://127.0.0.1:8000 指向此 VM 的本地服务:127.0.0.1 表示本机,8000 是监听端口。

请求携带 API 密钥,即用于程序认证的秘密值。密钥通过 Authorization 请求头发送;请求头是带名称的请求元数据。本服务要求先写 Bearer,再写秘密值。请勿把练习中的合成密钥与真实凭据混用。

切换到 Workstation 标签页,发送一次读取请求。curl 发送 HTTP 请求;-s 隐藏进度,-H 提供请求头。单引号把空格和查询分隔符 ? 保留在同一参数中。batch=demo 选择练习数据集:

curl -s -H 'Authorization: Bearer lab_key_support_exposed' 'http://127.0.0.1:8000/v1/tickets?batch=demo'

响应为 JSON,即包含命名字段和值的数据格式。batch 标识数据集;items 是列表,其中的工单有 id 和 subject。request_id 是会变化的审计标识,不是秘密值。请找到主题 Delivery question。

发布演示摘要

本步骤中,你将用预置 worker 把刚才读取的工单转换为服务接收的摘要。上一步只执行了读取请求,这个程序还会发布结果。

在实验界面选择 Integration 标签页,开始本步骤。

切换到 Integration 标签页,对同一个演示批次运行 worker。python3 执行提供的 Python 程序;路径指向该程序,demo 是批次参数。本课程不要求编写或理解 Python:

运行以下命令前,请切换到 Integration 标签页。

python3 /opt/keylab/worker.py demo
Read batch: demo (1 items)
{"batch":"demo","count":1,"subjects":["Delivery question"]}
Received batch: demo
Receiving key ID: key_support_old

第一个请求读取输入,第二个发布摘要。Received batch 表示接收端 API 已接受结果。key_support_old 这样的密钥 ID 是非秘密标签,与请求头中的秘密值不同。这次运行展示正常行为,并不完成后续恢复实验的指定批次。

找到并吊销历史密钥

本步骤中,你将找到历史凭据,将 ID 对应到服务端记录,并吊销这一密钥。删除可见行可以让它从最新文件消失,却不会使凭据失效。

在实验界面选择 Workstation 标签页,开始本步骤。

先看现在,再看过去

切换到 Workstation 标签页,用 cat 打印当前示例。INI 文件通过 [integration] 这样的方括号节名组织设置;每项设置由名称、等号和值构成:

运行以下命令前,请切换到 Workstation 标签页。

cat summary-example.ini
[integration]
key_id = key_support_old
api_key = SET_AT_RUNTIME

占位符适合用于可共享的示例,但不能说明旧副本是否存在,或服务端密钥处于什么状态。

Git 把项目快照记录为提交(commit)。仓库既包含当前文件,也包含提交历史。git log 按从新到旧的顺序列出提交,--oneline 让每个提交占一条简短记录。全局选项 --no-pager 将结果直接打印到终端,避免进入交互式分页器:

git --no-pager log --oneline

你会看到 Document prepared worker、Remove credential from current example 和 Add integration example。左侧短标识可能不同。

HEAD 表示最新提交,HEAD~2 表示向前两个提交。git show 显示历史对象;冒号分隔版本和文件名:

git --no-pager show HEAD~2:summary-example.ini
[integration]
key_id = key_support_old
api_key = lab_key_support_exposed

原秘密值仍可恢复。删除最新示例或重写本地历史,都不会通知 API 停止信任别人已取得的副本。

与服务端记录对应

Key Manager 使用独立的维护凭据——操作员令牌。应用密钥不能管理其他密钥。切换到 Workstation 标签页,显示预置的本地令牌:

Key Manager 的操作员登录与应用 API 凭据相互独立

cat /home/labex/.config/keylab/operator-token

切换到 Key Manager 标签页,将该值粘贴到 Operator token,选择 Sign in,再选择 Open Key Manager。不要把此令牌放进仓库文件。如果登录被拒绝,在同一标签页选择 Return to Key Manager,切换到 Workstation 重新复制此 VM 的操作员令牌,再切回 Key Manager 重试。找到 key_support_old 行及其 Active 状态。它的权限范围(scope)描述允许执行的操作;下一个实验会介绍如何选择。

在 Recent API requests 中找到该密钥的成功请求。状态 200 表示 API 接受了读取。历史证明秘密值曾暴露,请求证明凭据可用;两者都不能证明以前的请求由谁发起。无需提交报告或复制日志。

吊销已识别的密钥

只吊销受影响的密钥。下一步将测试拒绝结果和独立可用性。吊销改变服务端是否接受凭据的决定,不能擦除秘密值的副本。

切换到 Workstation 标签页,再次请求演示工单,这次显示 HTTP 状态。-w 追加格式化结果;\n 换行,%{http_code} 插入响应状态:

curl -s -w '\nHTTP %{http_code}\n' -H 'Authorization: Bearer lab_key_support_exposed' 'http://127.0.0.1:8000/v1/tickets?batch=demo'

响应以 HTTP 200 结束。切换到 Key Manager 标签页,在 key_support_old 行选择 Revoke。请核对 ID:吊销所有密钥会中断其他工作。该行现在应显示 Revoked。

Key Manager 显示已吊销泄露的支持密钥,监控密钥仍保持有效

测试泄露控制与可用性

本步骤中,你将测试旧凭据已被拒绝,同时 API 和独立监控仍可用。管理界面的状态变化很有用,但实际请求才能确认访问边界。

在实验界面选择 Workstation 标签页,开始本步骤。

在 Workstation 标签页中重复同一请求:

运行以下命令前,请切换到 Workstation 标签页。

curl -s -w '\nHTTP %{http_code}\n' -H 'Authorization: Bearer lab_key_support_exposed' 'http://127.0.0.1:8000/v1/tickets?batch=demo'
{"error":"Invalid or revoked key"}
HTTP 401

对本 API,401 表示提供的凭据无法通过认证。这种预期拒绝意味着泄露控制成功。连接错误则表示服务不可达;停止服务不能算修复。

切换到 Integration 标签页,再次运行 worker:

运行以下命令前,请切换到 Integration 标签页。

python3 /opt/keylab/worker.py demo
HTTP 401: {"error":"Invalid or revoked key"}

此命令应当以失败状态退出。任务仍从私有文件读取已吊销的值,因此无法再读取输入。控制泄露期间允许批处理暂时暂停。下一实验会从该状态开始恢复任务。

切回 Workstation 标签页,检查独立监控。它使用自己的凭据和健康检查端点:

运行以下命令前,请切换到 Workstation 标签页。

curl -s -w '\nHTTP %{http_code}\n' -H 'Authorization: Bearer lab_key_monitor_only' http://127.0.0.1:8000/v1/health
{"status":"ok","integration":"monitor"}
HTTP 200

你已移除泄露凭据的访问,同时保持服务和无关集成可用。你也可以进一步恢复任务;本实验不会因为有效的恢复操作而判定失败。

总结

你了解了正常工作的集成,区分了密钥 ID 和秘密值,从 Git 历史恢复了秘密值,并吊销对应的服务端凭据。你测试了真实拒绝和独立服务的可用性。删除一行内容并不会使密钥失效,吊销才会。下一实验将用专用、权限受限的替代密钥恢复任务。