浏览器 - XSS 和 CSRF 的原理和对策
前端常见的攻击方式及应对策略
XSS
跨站脚本攻击(Cross Site Scripting)主要有反射型和存储型两种。
反射型
XSS 代码在 url 中,读取含有恶意脚本的 url 参数并渲染至模板,脚本会在浏览器解析过程中运行。
举个例子:
URL:localhost:8080?id=<script>alert('xss')</script>100
<div>
My Account: {query.id}
</div>
当访问上述网址时,参数能够正常显示,但同时也会弹出 xss 的提示框,表示已经注入成功。
还有一类便是通过溢出 Html 元素属性来实现,举个例子:
URL:localhost:8080?imgpath=ABCD" onclick="alert('xss')"
<img src="{query.imgpath}"/>
这时候实际渲染出的是:
<img src="ABCD" onclick="alert('xss')" />
通过增加双引号关闭了 src 属性,然后添加自定义的属性,当点击该图片时就会触发脚本。
最省事的解决方式:将 url 参数转义为 JSON 字符串
存储型
XSS 代码存储在后端,从后端取数据时,会将带有恶意脚本的数据渲染至模板,导致脚本的运行。
解决方案:对用户输入进行白名单过滤,可使用现有 js-xss 库,在存储用户输入时进行过滤而非渲染时过滤能够减少不必要的性能损耗。
CSRF
跨站请求伪造(Cross Site Request Forgy),在 B 站发起对 A 站的请求,如果用户已经在 A 站登录,那么请求会带上 A 站的 Cookie,那么这个请求就会被判定是 A 站用户的正常操作。
举个例子:
A 站的转账请求格式如下
https://a.com?userid=*&amount=*
B 站的页面如下
<img src='https://a.com?userid=100&amount=200' />
访问 B 页面时会直接提交 A 站的转账请求,用户的存款就被转走了。
解决 CSRF 的方案主要有以下几种方式:
sameSite属性
cookie 增加了 samesite 属性,将其设置为 Lax 或者 Strict 都能够防止跨站读取 Cookie。
同源检测
Http 头中含有 referer 和 Origin 字段用来记录发出请求的地址,如果判断 referer 或 origin 的值合法,那么大概率没有被伪造,但也不可以确信,因为浏览器可能被修改或不支持。
验证码校验
CSRF 特点便是不在主站页面上运行,通过在页面设置验证码并要求用户输入,可以避免跨站的请求伪造。
设置 token
token 是简化版的验证码,先由后端生成由时间戳和随机数组成的 token 并保存在 session 中,然后传递给页面,页面将 token 添加至请求数据中,后端收到数据时,取出 token 并与 session 中的 token 进行比对,如果一致且没有超过有效期限,则说明没有被伪造。
浏览器 - XSS 和 CSRF 的原理和对策