跳转到内容
HexaTransfer
返回博客
加密与安全

Web应用安全头:完整配置指南

为文件传输Web应用配置基本安全头。CSP、HSTS、X-Frame-Options等防护常见Web攻击。

安全头是 HTTP 响应字段,告知浏览器如何约束页面行为。对于执行客户端 AES-256-GCM 加密的文件传输应用,六个响应头最为关键:Strict-Transport-Security 强制使用 HTTPS、Content-Security-Policy 阻止脚本注入、X-Frame-Options 防止点击劫持、Referrer-Policy 阻止 URL 片段泄露、Permissions-Policy 禁用未使用的浏览器 API,以及 Cross-Origin-Opener-Policy 隔离浏览上下文。正确配置这六个响应头,无需更改一行 JavaScript,即可阻断 80% 的实际客户端攻击。

HSTS 与预加载列表

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload 告知浏览器在两年内永远不再通过明文 HTTP 连接。preload 指令使你有资格进入 Chrome 的 HSTS 预加载列表(hstspreload.org),该列表随浏览器一同发布——即使对你域名的第一次请求也会走 HTTPS,消除了初始 MITM 攻击窗口。提交是单向操作,移除需要数月时间。建议先用 max-age=300 测试几天。一个没有 HSTS 预加载的文件传输服务,只需一次 DNS 劫持就可能被伪造上传表单所替代。

真正有效的 Content Security Policy

CSP 是部署难度最大、价值也最高的响应头。文件传输应用的严格策略如下:default-src 'none'; script-src 'self' 'wasm-unsafe-eval'; connect-src 'self' https://upload.hexatransfer.com; style-src 'self'; img-src 'self' data:; font-src 'self'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'。禁止内联脚本,禁止 eval(WebAssembly 除外),禁止第三方连接。将任何内联事件处理程序移入外部文件中的 addEventListener'wasm-unsafe-eval' 是 libsodium.js 所必需的;没有它,Argon2id 将无法实例化。

每个 Bundle 都要配置子资源完整性

如果你的 JavaScript 从 jsDelivr 或 unpkg 等 CDN 加载,在每个 script 标签上添加 integrity="sha384-..." 属性。浏览器拒绝执行哈希值不匹配的脚本——被攻破的 CDN 无法悄悄推送带后门的 bundle。对于自托管的脚本,SRI 没那么关键,但仍然值得部署。将 SRI 与 CSP 的 require-sri-for script style(已弃用但 Chrome 仍支持)配对,或通过构建流水线强制执行。HexaTransfer 为每个版本发布哈希值,方便有需要的用户手动验证。

X-Frame-Options 与框架祖先限制

点击劫持攻击将你的上传页面加载到透明 iframe 中叠加在另一个页面上,诱骗用户点击"发送"并分享他们本不想共享的文件。X-Frame-Options: DENY 阻止所有框架嵌入;现代替代方案是 Content-Security-Policy: frame-ancestors 'none'。两者都应部署——旧版浏览器只识别传统响应头,新版浏览器优先使用 CSP。文件传输应用永远不要使用 SAMEORIGIN,因为没有任何正当理由需要从其他页面框架嵌入上传界面。

Referrer-Policy 防止片段泄露

浏览器默认会从 Referer 请求头中去除 URL 片段(存放解密密钥的 #key=... 部分),但路径部分仍会泄露。Referrer-Policy: no-referrer 阻止所有引用来源信息——出站链接不携带 Referer 头,无跨域泄露,无外部追踪器对 URL 的指纹识别。对于位于 /d/7Kj9xQmN2vP8rBwLsE4fT#k=abc 的下载页面,此策略可防止 slug 泄露到用户点击进入的任何外部域名。通过响应头在全站范围内设置,不要依赖每个链接上的 rel="noreferrer"

Permissions-Policy 纵深防御

如果你的应用不使用摄像头、麦克风、地理位置或 USB API,应明确禁用它们:Permissions-Policy: camera=(), microphone=(), geolocation=(), usb=(), bluetooth=(), accelerometer=(), magnetometer=(), gyroscope=(), payment=()。即使绕过了 CSP 的 XSS 攻击,也无法打开网络摄像头录制用户面部。这个响应头部署成本低,对文件传输工作流没有任何用户体验影响,并向安全审查人员表明你已认真考虑了沙箱隔离。

跨源隔离响应头

要访问高精度计时器和 SharedArrayBuffer(某些 WebAssembly 加密实现所需),浏览器要求通过 Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp 实现跨源隔离。这些响应头还可防止可能从相邻源泄露 AES 密钥的 Spectre 侧信道攻击。代价是:嵌入的第三方资源(YouTube 视频、Stripe 结账页面)将会失效,除非它们提供 Cross-Origin-Resource-Policy: cross-origin。对于没有第三方嵌入内容的单一用途文件传输应用,隔离是零成本的。

敏感页面的 Cache-Control

下载确认页面可能会显示短期解密密钥或会话令牌。防止缓存:Cache-Control: no-store, must-revalidatePragma: no-cache。不要仅依赖 no-cache——它允许对源服务器进行重新验证,意味着缓存仍然会发生。对于上传页面的 JavaScript bundle,情况相反:使用带内容哈希文件名(/js/main-a7b3c9.js)的长 max-age,使 CDN 缓存无需手动失效。按路径精确应用响应头。

X-Content-Type-Options 与 MIME 嗅探

X-Content-Type-Options: nosniff 阻止浏览器根据内容猜测 MIME 类型。若没有此响应头,攻击者上传的包含 <script> 的 .txt 文件在被回传时可能被渲染为 HTML。对于向用户提供受控下载的传输服务,将 nosniffContent-Disposition: attachment; filename="..." 结合使用,使浏览器下载而非渲染内容。在服务端对文件名进行路径穿越验证(../../../etc/passwd),不要信任上传元数据中的任何内容用于安全决策。

CSP 报告与监控

先以 report-only 模式部署 CSP,在 report-uri 端点收集一周的违规记录,修复合法问题后再强制执行。使用 Content-Security-Policy-Report-Only 进行观察,切换到 Content-Security-Policy 进行执行。报告端点接收描述每条违规的 JSON POST:被阻止的 URI、被违反的指令、源文件、行号。Report URI 等服务或自托管的 Sentry 可以收集这些数据。每周审查一次——真实攻击会以你从未见过的异常被阻止 URI 形式出现。

评估配置结果

将生产环境 URL 通过 securityheaders.com 和 Mozilla Observatory 进行检测。获得 A 或 A+ 评级并非完美,但这是基本标准。大多数文件传输竞争对手只能得 B 或更低,因为他们忘记了 Permissions-Policy,或者在 CSP 中允许了 'unsafe-inline'。小服务轻松可以超越 WeTransfer 的安全响应头评分;这些响应头无需任何成本就能添加,而且在与 SOC 2 审计员讨论"为什么你的 CSP 不够严格"时,从一开始就保持严格会让审计路径短得多。

在 hexatransfer.com 上试试 — 免费、无需注册、最多 10 GB。

通过端到端加密安全发送大文件

通过端到端加密免费传输最大10GB的文件。无需注册账户。文件在上传前在浏览器中加密,其他人无法读取。

发送文件