本文大致整理了一下和前端安全相关的常见知识点。
安全问题的场景
web安全,我认为大致分为以下几部分:
- 一部分是用户本身想要对服务器或者web应用进行攻击
- 比如,我拥有这个web应用的身份,我想要通过请求来伪造一些东西,刷数据、改数据
- 通过应用本身的漏洞,对应用进行攻击
- 一个是第三方者针对web应用的用户进行攻击
- 比如盗取用户身份,以此来窃取用户信息、冒充用户做坏事等等
- 第三方直接攻击服务器
常见安全问题
iframe问题
iframe的安全问题很多,因为我们常用来嵌入第三方应用,如果这个第三方应用是自己的还好,如果不是自己的,那就需要防止第三方应用操控主应用的内容。
iframe风险原因
- 同源策略下,iframe 与父页面可双向访问 window 对象和 DOM,若一方存在脚本注入漏洞,会直接威胁另一方安全。
- 点击劫持(下文会细说)
- 跨域信息泄露
- 利用 window.postMessage 漏洞:若父页面未验证 postMessage 的来源(event.origin),恶意 iframe 可发送伪造消息,诱导父页面泄露数据;
- 利用 referrer 泄露:iframe 加载时,请求头会携带父页面的 referrer,可能泄露父页面 URL 中的敏感参数(如用户 ID)。
- iframe第三方内容不可控
iframe安全防护措施
iframe问题的主要原因是其内容不可控且能够访问父页面的内容,那么我们可以从这个角度出发去避免一些安全问题:
- 限制 iframe 权限:sandbox 属性(核心防护),严格限制 iframe 权限,不开放非必要功能:
<iframe src="https://third.com" sandbox="allow-scripts allow-same-origin allow-forms"></iframe>
- sandbox 是 HTML5 为 iframe 提供的安全沙箱机制,通过添加特定关键词限制 iframe 的权限,默认情况下会禁用所有危险操作(如脚本执行、表单提交、同源访问)。
- allow-scripts:允许 iframe 执行脚本(默认禁用,开放需谨慎);
- allow-same-origin:允许 iframe 与父页面同源(若信任内容可开启,否则禁用);
- allow-forms:允许 iframe 提交表单;
- allow-top-navigation:禁止 iframe 导航父页面(_top 目标,防 URL 篡改);
- 未指定的权限默认禁用,遵循 “最小权限原则”。
- 防御点击劫持:X-Frame-Options响应头 与 CSP,限制当前页面是否允许被其他页面通过 iframe 嵌入。
- 安全处理跨窗口通信:postMessage通信验证消息来源(origin),避免和未知的来源通信
- 其他
- 避免嵌入不可信第三方内容
- 隐藏 referrer:
<iframe src="https://third.com" referrerpolicy="no-referrer"></iframe>
window.opener风险
什么是window.opener风险
window.opener 是浏览器提供的一个全局对象,用于在 由 window.open() 打开的新窗口(子窗口) 与 打开它的父窗口 之间建立通信。但该特性存在严重的安全风险,若使用不当可能导致 跨站脚本攻击(XSS)、钓鱼攻击 或 信息泄露,是前端安全中需重点防范的点。
当父窗口通过 window.open(url, name) 打开子窗口时:
- 子窗口可通过 window.opener 访问父窗口的 window 对象(如 window.opener.location、window.opener.document);
- 父窗口可通过 open() 返回的引用(如 const childWin = window.open(…))访问子窗口的 window 对象。
这种双向访问的设计初衷是支持窗口间协作(如子窗口提交表单后通知父窗口刷新),但 未限制访问范围,导致恶意子窗口可篡改父窗口或窃取信息。
window.opener 的访问权限 不受同源策略完全限制:
- 即使父窗口与子窗口 不同源(如父窗口是 a.com,子窗口是 hack.com),子窗口仍可通过 window.opener.location 修改父窗口的 URL(这是最危险的风险点,例如钓鱼);
- 若父窗口存在 XSS 漏洞,同源的恶意子窗口可通过 window.opener.document 读取 / 修改父窗口的 DOM、Cookie 等敏感数据。
如何预防window.opener的安全风险
- 禁止子窗口访问 window.opener(最彻底的方案):通过在 window.open() 的目标 URL 中添加 rel=”noopener noreferrer”(针对
<a>
标签)或设置窗口特性,切断子窗口与父窗口的关联 - 同源场景下的通信加强权限控制(postMessage中验证origin后再处理)
CSRF/XSRF攻击
CSRF / XSRF他们只是缩写不同,中文称之为:跨站请求伪造
什么是CSRF?为什么能造成安全问题?
参考:
其攻击方式的原理为:当用户登录了某个网站A,那么在此时对A网站进行请求就是合法的,而如果用户访问了某个恶意网站,这个恶意网站中也发起了对A网站的请求,此时A网站仍然会认为该请求是合法的,即使,该请求不是用户发起的,且不符合用户的意愿。
其本质的问题在于,网站应用只是通过请求所携带的用户凭证来确定该请求是用户发起的,但是网站其实只能确定该请求是用户所在的浏览器发起的,而不能确定是不是用户自己发起的。
攻击示例:一个用户登录一个银行网站,此时,他可以通过链接https://bank.example.com/xx?account=AccoutName&xxxx=xxxx
对账户进行操作,当用户访问某个带CSRF的危险网站时,网站中可以通过:<img src="https://bank.example.com/xx?account=AccoutName&xxxx=xxxx" />
来执行对该银行网站的当前用户账户的恶意操作,因为此时银行网站只能识别该请求是合法(通过某种授权方式),但是无能保证该请求真的是用户发起的。
如何防御CSRF?
其本质的原因在于,恶意网站能够借用当前用户在浏览器在其他网站认证的身份来发起非用户所期望的恶意请求。那么只要有一个机制,让恶意网站无法借用其他网站的身份来发起恶意请求,就可以防止CSRF攻击了。
我们需要了解,恶意网站为什么可以借用其他网站的身份认证来发起请求呢?
- 即使cookie有同源策略,即A源(域名和路径)的请求只能携带A源的cookie,但是在这个场景下这里是符合的,因为cookie的发送并没有违背同源策略:请求A源,携带A源的cookie,只不过请求的发起不一定是A源的网站。
- 如果使用cookie,那这里唯一的差别是,正常的请求是从A网站发起的,而恶意网站是从其他源发起的,那么是否可以基于这个进行限制?
一些方案:
- cookie中有一个SameSite属性,用来控制 “当浏览器发起跨站请求时,是否携带当前网站的 Cookie”。这完全符合在CSRF场景下对cookie行为的控制。
- 如果不是用cookie这种根据请求自动发送鉴权信息的方式进行的鉴权呢?比如通过请求中携带token或者通过自定义请求头中携带token的方式来鉴权,且防止token信息被其他网站获取到,此时,即使恶意网站能够发送请求,但是获取不到token等鉴权信息,则也无法通过服务器鉴权校验。即csrf Token的方案
- 验证Referer:正常来说,请求的Referer在http中有规定,能够识别请求是从哪里来的,正常请求下,Referer是正常网站的地址,而在恶意网站中进行请求的情况下,其Referer则是恶意网站所在的地址,通过对该Referer的校验,我们可以防止CSRF攻击。但是这个值可能存在被篡改的可能,完全依赖于浏览器。
- csrf通常来自第三方域名,但是也可能来自本域,比如评论这种,那么此时同源策略就不起作用,需要有额外的手段(比如csrf token进行二次校验)
- 为重要操作使用验证码(比如手机验证码),这样也能够较为安全的防止csrf攻击。
XSS攻击
跨站脚本攻击
什么是XSS攻击?为什么能造成安全问题?
这个就是指,通过网站漏洞,攻击者可以在目标网站上注入恶意代码,并是恶意代码在网站中运行。
比如将script插入到html中时,浏览器就会执行该script。
解决方案:由于xss攻击种类挺多且比较复杂,不同场景有不同的优化方式,对于前端来说,我觉得一切可被用户输入或者修改的数据,都尽量将其视为字符串去处理,如果不是这样,那么就要考虑是否可能遭受XSS攻击了。
点击劫持(ClickJacking)
问题:其本质,就是将目标网站嵌入到恶意网站的iframe中,并通过技术将其隐藏起来,然后诱导用户一步一步进行点击,让用户误以为是在其他网站进行操作,其实是在目标网站进行操作。
解决方案:通常可以对iframe的控制来防止目标网站被嵌入到恶意网站。参考:iframe 安全防护措施
钓鱼网站
伪造一个和目标网站一样的网站,然后诱导用户误以为是目标网站,然后进行登录等敏感操作,以此来盗取用户的账户密码等敏感信息。
这个感觉从网站所有者角度,没有太好的预防手段,更多的预防是在于用户侧能否有较好的防范意识和识别手段。
前端安全限制
同源策略
请参考:web同源策略和跨域方案文档