QBin支持用户创建HTML代码,并且支持通过/r/xxx 路径显示渲染后的界面。
那么就可能存在同源恶意攻击问题,那么如何防止这个问题,并且不影响正常用户使用呢?
这就是我们接下来需要讨论的问题。
在浏览器中进行网络请求都会强制携带一些headers信息,我们要关心的就是Referer
和Origin
通过 referer和origin 我们可以知道这个请求来自哪里,那么就可以根据这些信息针对特定路径进行检测。
刚开始我的解决方法是增加一个中间件,在必要的接口中增加检测,关键代码如下
const referer = ctx.request.headers.get("referer");
if (referer && referer.includes("/r/")) {
return new Response(ctx, 403, "不允许从分享链接页面请求token");
}
这个代码看似没有问题,其实还存在缺陷,前端可以修改referrer-policy,就会出现匹配不到的问题,下面是绕过检测成功的攻击案例
虽然前端修改了referrer-policy,但还是会在referrer携带 host,那么就可以改进检测规则
// 获取基本请求信息
const referer = ctx.request.headers.get("referer");
const origin = ctx.request.headers.get("origin");
if (!referer || referer.includes("/r/")) {
return new Response(ctx, 403, "不允许从同源链接页面请求token");
}
if (referer === origin) {
return new Response(ctx, 403, "检测到可疑的Referer策略");
}
const refererUrl = new URL(referer);
if (refererUrl.pathname === "/" || refererUrl.pathname === "") {
return new Response(ctx, 403, "不允许使用仅包含域名的Referer");
}
除了上面的这些防范还不够,因为html不仅可以通过fetch请求,还可以通过表单提交等方式绕过,那么我们就需要为前端增加headers响应防范
{
"X-Content-Type-Options": "nosniff", // 禁止嗅探MIME类型
"X-XSS-Protection": "1; mode=block", // 启用XSS过滤器
"X-Frame-Options": "DENY", // 禁止页面在frame中展示
// "Content-Security-Policy": "default-src 'self'", // 同源加载
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", // HSTS强制使用HTTPS
"Referrer-Policy": "strict-origin-when-cross-origin", // 引用策略
},
更严格的"Content-Security-Policy": "default-src 'self'"
策略是只允许同源域名请求,其他外链都会拒绝,虽然效果很好,但是实际应用中并不方便。
最后是防范成功的截图
如果有其他思路,欢迎在评论区讨论
代码仅供学习参考,请勿用于其他用途