同源策略(Same-origin policy)
URL 的协议、域名和端口都相同
- DOM 层面:同源策略限制来自不同源的 JS 脚本对于 DOM 对象的读写操作
- 数据层面:对于 Cookie、IndexDB、LocalStorage 等数据的访问限制
- 网络层面:限制通过 XMLHttpRequest 等方式将站点的数据发送给不同源的站点
跨域问题
CORS(Cross-origin resource sharing,跨域资源共享)
Access-Control-Allow-Origin: http://api.bob.com
服务器代理
服务器不存在跨域问题,由服务器请求所有域的资源再返回给客户端
跨站脚本攻击(Cross Site Scripting,XSS)
页面被注入恶意代码
- 在 HTML 中内嵌的文本中,恶意内容以 script 标签形成注入。
- 在内联的 JavaScript 中,拼接的数据突破了原本的限制(字符串,变量,方法名等)。
- 在标签属性中,恶意内容包含引号,从而突破属性值的限制,注入其他属性或者标签。
- 在标签的 href、src 等属性中,包含
javascript:
等可执行代码。 - 在 onload、onerror、onclick 等事件中,注入不受控制代码。
存储型 XSS
这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。放射型 XSS
反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。
反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。DOM 型 XSS
DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。预防
- 服务器对输入脚本进行过滤或转码
- 充分利用 CSP(Content Security Policy)
- 禁止加载外域代码,防止复杂的攻击逻辑。
- 禁止外域提交,网站被攻击后,用户的数据不会泄露到外域。
- 禁止内联脚本执行(规则较严格,目前发现 GitHub 使用)。
- 禁止未授权的脚本执行(新特性,Google Map 移动版在使用)。
- 合理使用上报可以及时发现 XSS,利于尽快修复问题。
- 使用 HttpOnly 属性
set-cookie: NID=189=M8q2FtWbsR8RlcldPVt7qkrqR38LmFY9jUxkKo3-4Bi6Qu_ocNOat7nkYZUTzolHjFnwBw0izgsATSI7TZyiiiaV94qGh-BzEYsNVa7TZmjAYTxYTOM9L_-0CN9ipL6cXi8l6-z41asXtm2uEwcOC5oh9djkffOMhWqQrlnCtOI; expires=Sat, 18-Apr-2020 06:52:22 GMT; path=/; domain=.google.com; HttpOnly
JS 脚本无法读取设置了 HttpOnly 的 Cookie 数据
跨站请求伪造(Cross-site request forgery,CSRF)
攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
CSRF 的特点
- 攻击一般发起在第三方网站,而不是被攻击的网站。被攻击的网站无法防止攻击发生。
- 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;而不是直接窃取数据。
- 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”。
跨站请求可以用各种方式:图片URL、超链接、CORS、Form提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。
防护策略
利用 Cookie 的 SameSite 属性
set-cookie: 1P_JAR=2019-10-20-06; expires=Tue, 19-Nov-2019 06:36:21 GMT; path=/; domain=.google.com; SameSite=none
Strict:浏览器会完全禁止第三方 Cookie
- Lax:在跨站点的情况下,从第三方站点的链接打开和从第三方站点提交 Get 方式的表单这两种方式都会携带 Cookie
-
验证请求的来源站点
Referer:HTTP 请求头中的一个字段,记录了该 HTTP 请求的来源地址
- Origin:通过 XMLHttpRequest、Fecth 发起跨站请求或者通过 Post 方法发送请求时,都会带上 Origin 属性,只包含了域名信息,并没有包含具体的 URL 路径
CSRF Token
- 在浏览器向服务器发起请求时,服务器生成一个 CSRF Token,将 CSRF Token 输出到页面中
- 页面提交的请求携带这个
-
参考资料
- 33 | 跨站脚本攻击(XSS):为什么Cookie中有HttpOnly属性?
- 前端安全系列(二):如何防止CSRF攻击?
- 34 | CSRF攻击:陌生链接不要随便点