我们目前正在开发类似文件服务器的实现,为用户上传的内容提供服务。为了规避 CSRF 攻击,我们为所有内容提供 CSP 标头,这不允许在内容上执行任何脚本。
使用的 CSP 标头看起来像这样:
Content-Security-Policy: default-src 'none'; media-src 'self'; style-src 'unsafe-inline'; font-src data: ; connect-src 'self'; sandbox
这适用于 HTML 或 SVG 等各种媒体。但我们注意到,浏览器不会对在浏览器中打开的嵌入 JavaScript 的 PDF 文件应用 CSP 规则。当您在浏览器中打开包含 JavaScript 的 PDF 时,无论 CSP 标头的值如何,都会执行 JavaScript。
PDF 中 JavaScript 执行的上下文似乎非常有限,似乎没有办法访问像
window
或 document
这样的站点上下文,而且,似乎也没有办法访问在 PDF JavaScript 上下文中执行 HTTP 请求。
在我的研究中,我发现很难找到有关浏览器内 PDF 中的 JavaScript 如何处理或是否存在安全风险的可靠来源。大多数消息来源都暗示通过从文件中剥离 JavaScript 内容来清理 PDF 文件,但如果用户确实想要提供交互式 PDF 文件(如果规范似乎可以实现),那么这将是不方便的。
您在本主题中是否有关于如何通过 Web 服务器安全地提供 PDF 服务的经验?有没有最佳实践?
使用浏览器原生 PDF 查看器的 PDF 中的 JavaScript 确实会在有限范围内以沙盒方式执行。
但是,未来的“理论上”漏洞可能会规避这一点。根据您的安全状况,您可能希望使用 CSP 来降低此风险。您可能也不希望使用这些动态功能显示“烦人”的 PDF(例如,它们可以触发浏览器 alert()
功能)。
正如您所发现的,作为浏览器“插件”的一部分执行的脚本不受 CSP 的约束。它超出了它的控制范围。对于 CSP 来说,它们只是通过
<embed>
、
<object>
、<iframe>
或其他方式实现的不透明“对象”。因此,object-src
和 frame-ancestors
可用于控制是否允许它们完全出现在您的内容中。 但是,它们是“全有或全无”开关,无法控制 PDF 内的脚本执行。您只能控制它们是否可以嵌入。我猜想您会为能够将 PDF 嵌入到您的用例中赋予一定的产品价值。
如果您想继续采取某种解决方案,有一些具有不同权衡的潜在选项:
使用基于 JS 的 PDF 查看器,例如
enableScripting
设置为 false。
理论上,你可以从PDF服务器端剥离JS。
object-src
frame-ancestors
来实现,以便仅允许来自您自己的服务器(“缓存”/“剥离”位置)的 PDF。感觉它有相当大的开销和一点负担。