Web开发安全的XSS和CSRF问题以及解决方案 | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的的第2天
一、XSS
1. 什么是XSS?
跨站脚本攻击(Cross-Site-Scripting)但是缩写是css,重名,所以改为XSS。XSS是跨站脚本攻击,恶意攻击者在web页面中插入恶意的script代码,当用户访问该页面时,恶意的script会执行,达到恶意攻击的目的。
不需要用户做任何的登录认证,它会通过合法的操作(比如在url中输入,在评论框中输入),向用户的页面注入脚本(可能是html,js代码),原理与SQL注入攻击类似。
2. 攻击方式
反射型
发出请求时,XSS代码出现在url中,作为输入提交到服务器端,当用户打开带有恶意代码的url链接的时候,网站的服务器将恶意代码从url中取出,然后拼接到html中返回给浏览器端,用户浏览器接受到后相应并解析代码,其中的恶意代码也会被执行到,攻击是一次性的。
例如:
host/path/?param=<script>alert('123456')</script>
存储型
存储型XSS和反射型的XSS的区别在于,提交的代码会存储到服务器端(数据库,内存,文件系统等),对全部用户可见,攻击是持久的。
- 攻击者将恶意代码存放到目标网站的数据库中
- 用户浏览目标网站的时候,网站服务器从数据库中把恶意代码取出,然后拼接到html后返回给浏览器
- 浏览器接受到响应后解析并执行,其中恶意代码也会被执行
DOM-based型
基于文档对象模型,不需要服务器的参与,恶意攻击的发起+执行,全在浏览器完成。
- 攻击者构造出特殊的url,其中url中含有恶意代码
- 用户打开含有恶意代码的url
- 用户浏览器响应解析并执行,前端使用js取出url中恶意代码并执行
host/path/?param=<script>alert('123456')</script> //相同的URL
const content=new URL(location.href).searchParams.get("param");
const div=document.createElement("div");
//恶意脚本注入
div.innerHTML=content;
document.body.append(div);
3.特点
- 通常难以从UI上感知(暗地里执行脚本)
- 窃取用户信息(cookie/token)
- 绘制UI(例如弹窗等,诱骗用户点击或者填写表单)
4. 危害
- 窃取网页浏览中的cookie值,document.cookie 获取 Cookie 信息后,在其他电脑上模拟用户登录,然后进行转账等行为;
- 劫持流量实现恶意跳转
- 配合CSRF攻击完成恶意请求
- 监听用户行为:使用 addEventListener 监听用户键盘行为,获取用户账号密码信息;
- 修改 DOM 伪造登录窗口,欺骗用户输入用户名和密码;
5.如何阻止?
- cookie安全策略。Cookie 设置 HttpOnly 属性: 禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也无法窃取此 Cookie。
- XSS防御HTML编码。即转义转义 HTML。
- XSS防御之javascript编码
- XSS 防御之 URL 编码
- 开启CSP网页安全政策防止XSS攻击(CSP(Content Security Policy)是一种内容安全策略,通过配置可以告诉浏览器那些内容可以被加载执行,而那些又不可以)
- 服务器对输入内容进行过滤或转码
二、CSRF
1. 什么是CSRF ?
CSRF(Cross-Site Request Forgery):“跨站请求伪造”。攻击者盗用了用户的身份,以用户的名义发送恶意请求。
2. 攻击方式
登录受信任的网站A,并且在本地生成cookie 在不登出网站A的情况下,访问恶意网站B。
与 XSS 攻击不同的是:XSS 是攻击者直接对我们的网站 A 进行注入攻击,CSRF 是通过网站 B 对我们的网站 A 进行伪造请求。
例如:登录购物网站 A 之后点击一个恶意链接 B,B 请求了网站 A 的下单接口,结果是在网站 A 的帐号生成一个订单。其背后的原理是:网站 B 通过表单、get 请求来伪造网站 A 的请求,这时候请求会带上网站 A 的 cookies,若登录态是保存在 cookies 中,则实现了伪造攻击。
跨站请求可以用各种方式:图片 URL、超链接、CORS、Form 提交等等。
GET 类型的 CSRF
浏览器自动发起获取图片资源时,如果浏览器未做判断会认为这是一个转账请求。
<!DOCTYPE html>
<html>
<body>
<h1>黑客的站点:CSRF攻击演示</h1>
<img src="https://time.geekbang.org/sendcoin?user=hacker&number=100">
</body>
</html>
复制代码
POST 类型的 CSRF
构建一个自动提交转账请求的隐藏表单,当用户打开该站点时自动执行表单提交转账请求。
<!DOCTYPE html>
<html>
<body>
<h1>CSRF攻击</h1>
<form id='hacker-form' action="https://123.com" method=POST>
<input type="hidden" name="user" value="hacker" />
<input type="hidden" name="number" value="100" />
</form>
<script> document.getElementById('hacker-form').submit(); </script>
</body>
</html>
复制代码
链接类型的 CSRF
引诱用户点击图片下方的链接,发起请求。
<div>
<img width=150 src=http://123.com/123456.jpg> </img> </div> <div>
<a href="https://123.com/getInfo?user=hacker&number=100" taget="_blank">
点击下载
</a>
</div>
3. 特点
- 在用户不知情的前提下
- 利用用户权限(cookie)
- 构造HTTP请求,窃取或修改用户的敏感信息
4. 危害
- 用户的登录状态态被盗用
- 冒充用户完成操作或修改数据
5. 如何阻止
- 尽量使用POST请求,限制GET
- cookie设置SameSite,设置 cookie 的 SameSite 值为 strict,这样只有同源网站的请求才会带上 cookie。这样 cookies 就不能被其他域名网站使用,达到了防御的目的。
- 增加token,用于向服务端确认身份
- 通过referer进行识别,在 HTTP 协议中,头部有个 Referer 字段,他记录了该 HTTP 请求的来源地址,在服务端设置该字段的检验,通过检查该字段,就可以知道该请求是否合法,不过请求头也容易伪造。
三、XSS和CSRF的区别
1.CSRF需要用户进行登录,XSS不需要
2.CSRF是利用网站本身的漏洞,去请求网站,XSS是向网站中注入JS代码,然后执行代码,篡改网站的内容
在平时基本的页面开发中,我们很注意一些基本的注入攻击,包括html代码,以及SQL注入攻击。其次,在我们的请求中,不仅仅增加了token,也会有签名sign来保证参数的一致,防止请求中有恶意的参数。