从线索走到证据

我们继续从首页源码往下翻。在“常用下载”这一组公开链接的下方,出现了一行被注释掉的 HTML 代码:

<!-- <li><a href="/files/exam-plan-draft.html">2024 秋季学期期末考试安排(草稿)</a></li> 考场还没定 等下周教务例会过了再放 -->

这行注释和上一条不太一样。开发者没有只注释说明文字,而是把整个列表项和超链接一起包进了注释里,并且在末尾留下了一句原因说明:考场还没定,等教务例会后再放出来。

从安全排查的角度看,这行代码提供了两个关键信息:一是它明确给出了一个内部文件的路径 /files/exam-plan-draft.html;二是它透露了这份文件原本不准备公开。再结合首页公告里“未定稿安排不在本站发布”的规则,一个值得继续验证的问题就出现了:如果访客知道这个路径,直接请求它,服务器会不会把这份未公开草稿返回过来?

只靠前端代码里的注释,还不能下结论。链接被注释掉,只能说明普通用户无法在页面上点击它;至于这个文件是否真实存在、服务器是否做了权限限制,还需要我们主动发起一次 HTTP 请求来验证。

拼接草稿文件路径

注释中给出的资源路径是:

/files/exam-plan-draft.html

这是一个以 / 开头的资源路径。它表示从网站根目录开始查找:files 是服务器上的一个目录,exam-plan-draft.html 是目录下的文件名。

回到浏览器地址栏,保留当前实验站的协议、域名和端口,只把末尾的 / 替换成刚才提取到的完整路径:

https://你的实验站地址/files/exam-plan-draft.html

注意,这里要使用当前会话分配给你的真实实验地址,也不要在 URL 前面添加 view-source: 这样的前缀。

保留实验站地址、替换成草稿路径,浏览器发出请求并收到返回内容

按下回车,向服务器发起请求。

检验服务端的真实响应

页面成功打开,并直接返回了《2024 秋季学期期末考试安排(草稿)》的正文内容。页面顶部明确标有“内部草稿”和“版本 v0.3”,正文中还有一句话:考场需待后勤保障处最终核定,定稿前严禁对外公布,请勿转发学生。下方排考表格里,多门课程的考场状态都写着“待定”。

实际返回的排考草稿带内部草稿标记,表格中多门课程考场待定

回看整个验证过程,我们没有登录任何内部账号,也没有使用任何特殊权限,只是一个普通浏览器直接向已知路径发起请求。服务器却没有拦截,而是完整返回了这份标明“严禁外传”的内部草稿。

到这里,证据链就闭合了:未授权的外部访客只要知道具体路径,就可以绕过前端页面的隐藏限制,直接读取内部敏感文档。

删除或注释页面上的超链接,只是隐藏了普通用户可点击的入口。如果服务器端的静态资源目录没有做访问控制,文件仍然暴露在公网上,任何知道路径的人都可能访问到。

我们可以把这次验证过程整理成如下记录:

测试目标:阳明大学教务处信息门户(实验站)
访问身份:未登录任何账号的匿名外部访客
线索来源:首页 HTML 源码注释中泄露的相对路径 /files/exam-plan-draft.html
操作步骤:在浏览器地址栏直接请求该资源路径
实际结果:服务端返回 HTTP 200 及期末考试安排草稿正文,含内部密级标识与未定考场
确认结论:匿名访客可直接越权访问并读取标明严禁外传的内部敏感文档

做安全分析时,结论不能只靠一句“我发现了一个草稿”。需要把路径来源、访问身份、操作步骤、响应结果写清楚,别人才能够复现你的验证过程,也才更容易认可这个漏洞。

异常返回状态的判读

如果手动输入 URL 时把路径打错,例如把 draft 误写成 darft,服务器上没有对应的文件,通常就会返回 404 Not Found 错误页。

拼错的草稿路径返回 404,地址里的 darft 与正确的 draft 不同

如果页面打不开,可以先回到首页源码,逐字比对注释里的路径。检查是否把中文说明、引号、空格或 --> 误带进了 URL,也确认实验环境仍处于运行状态。

不同响应状态代表的含义不一样:

  • 返回 401 或 403:说明服务端已经配置了身份认证或权限拦截。
  • 返回 404:说明目标路径不存在,可能拼写错误,也可能文件确实不存在。
  • 返回 200 并显示草稿内容:说明匿名请求成功读取到了受限资源。

只有真正拿到受限数据,而不是只发现注释,才能构成完整的信息泄露证据。

综合练习

把前面的思路串起来练一次:先从首页源码注释中取出草稿路径,直接请求这份内部草稿;再像查看首页源码一样,查看草稿页面自身的源码。

综合练习:草稿页发过来的全部内容

Lab

启动环境并打开 TARGET 入口(启动 Lab 后显示)。

从首页源码的注释中找到那份排考草稿的路径,并直接请求该页面。

除了页面正文,这份草稿发给浏览器的内容里还藏有一处 COIN{...} 标记。请把它提交出来。

加载会话状态…

提交 coin

题解 Hint