# 网络攻击与防御

## XSS

XSS(Cross-site scripting) 跨网站指令码，是一种网站应用程式的安全漏洞攻击，是代码注入的一种。它允许恶意使用者将程式码注入到网页上，其他使用者在观看网页时就会受到影响。这类攻击通常包含了 HTML 以及使用者端脚本语言。

### 攻击

XSS 通过修改 HTML 节点或者执行 JS 代码来攻击网站。

XSS 分为三种：反射型，存储型和 DOM型

| 类型        | 存储区            | 插入点           |
| --------- | -------------- | ------------- |
| 存储型 XSS   | 后端数据库          | HTML          |
| 反射型 XSS   | URL            | HTML          |
| DOM 型 XSS | 后端数据库/前端存储/URL | 前端 JavaScript |

用户是通过哪种方法“注入”恶意脚本的呢？

不仅仅是业务上的“用户的 UGC 内容”可以进行注入，包括 URL 上的参数等都可以是攻击的来源。在处理输入时，以下内容都不可信：

* 来自用户的 UGC 信息
* 来自第三方的链接
* URL 参数
* POST 参数
* Referer （可能来自不可信的来源）
* Cookie （可能来自其他子域注入）

XSS 通过修改 HTML 节点或者执行 JS 代码来攻击网站。\
例如通过 URL 获取某些参数

```markup
<!-- http://www.domain.com?name=<script>alert(1)</script> -->  
<div>{{name}}</div>
```

上述 URL 输入可能会将 HTML 改为 `<div><script>alert(1)</script></div>` ，这样页面中就凭空多了一段可执行脚本。这种攻击类型是反射型攻击，也可以说是 DOM-based 攻击。

也有另一种场景，比如写了一篇包含攻击代码 `<script>alert(1)</script>`的文章，那么可能浏览文章的用户都会被攻击到。这种攻击类型是存储型攻击，也可以说是DOM-based 攻击，并且这种攻击打击面更广

这里美团前端团队有一篇网络攻击防御的文章，对XSS攻击讲解的很详细，可以详细的看一下

[前端安全系列（一）：如何防止XSS攻击?](https://tech.meituan.com/2018/09/27/fe-security.html)

### 防御

最普遍的方法就是转义输入输出的内容，对于引号，尖括号，斜杠进行转义。

```javascript
str = str.replace(/&/g, "&");  
str = str.replace(/</g, "<");  
str = str.replace(/>/g, ">");  
str = str.replace(/"/g, "&quto;");  
str = str.replace(/'/g, "&##39;");  
str = str.replace(/`/g, "&##96;");  
str = str.replace(/\\//g, "&##x2F;");
```

对于显示富文本来说，不能通过上面的办法来转义所有字符，因为这样会把需要的格式也过滤掉。这种情况通常采用白名单过滤的办法，当然也可以通过黑名单过滤，但是考虑到需要过滤的标签和标签属性实在太多，更加推荐使用白名单的方式。

**使用CSP** 内容安全策略 (CSP) 是一个额外的安全层，用于检测并削弱某些特定类型的攻击，包括跨站脚本 (XSS) 和数据注入攻击等。无论是数据盗取、网站内容污染还是散发恶意软件，这些攻击都是主要的手段。

CSP 本质上也是建立白名单，规定了浏览器只能够执行特定来源的代码。

## CSRF

跨 站 请 求 伪 造（ 英 语：Cross-site request forgery）， 也 被 称 为one-clickattack 或者 session riding，通常缩写为 CSRF 或者 XSRF，

XSS利用的是用户对指定网站的信任，CSRF利用的是网站对用户网页浏览器的信任。\
简单点来说，CSRF就是利用用户的登录状态发起的恶意请求。

### 攻击

假设网站中有一个通过 Get 请求提交用户评论的接口，那么攻击者就可以在钓鱼 网站中加入一个图片，图片的地址就是评论接口

```markup
<img src="http://www.domain.com/xxx?comment='attack'"/>
```

如果接口是 Post 提交的，就相对麻烦点，需要用表单来提交接口

```markup
<form action="http://www.domain.com/xxx" id="CSRF" method="post">  
    <input name="comment" value="attack" type="hidden">  
</form>
```

### 防御

防范 CSRF 可以遵循以下几种规则： 1. Get 请求不对数据进行修改 2. 不让第三方网站访问到用户 Cookie 3. 阻止第三方网站请求接口 4. 请求时附带验证信息，比如验证码或者 token

**SameSite**\
可以对 Cookie 设置 SameSite 属性。该属性设置 Cookie 不随着跨域请求发送，该属性可以很大程度减少 CSRF 的攻击，但是该属性目前并不是所有浏览器都兼容。

**验证 Referer**\
对于需要防范 CSRF 的请求，我们可以通过验证 Referer 来判断该请求是否为第三方网站发起的。

**Token**\
服务器下发一个随机 Token（算法不能复杂），每次发起请求时将 Token携带上，服务器验证 Token 是否有效

## 使用密码加密

### 加盐

加盐就是给原密码添加字符串，增加原密码长度。

但是加盐并不能阻止别人盗取账号，只能确保即使数据库泄露，也不会暴露用户的真实密码。一旦攻击者得到了用户的账号，可以通过暴力破解的方式破解密码。对于这种情况，通常使用验证码增加延时或者限制尝试次数的方式。并且一旦用户输入了错误的密码，也不能直接提示用户输错密码，而应该提示账号或密码错误。

**前端加密**\
虽然前端加密对于安全防护来说意义不大，但是在遇到中间人攻击的情况下，可以避免明文密码被第三方获取

### 实战

之前接触过XSS漏洞修复，网络安全部门指过来一些前端的xss漏洞，发现基本上都是url参数注入的漏洞，属于DOM 型 XSS攻击

```
https://m.beibei.com/n/address_manage/index.html?&redirecturl=javascript:alert(document.cookie)//m.beibei.com.a/n/trade/trade.html?_cart_id=
```

比如有这样的一个地址，url上带了一个参数`redirecturl`，参数被注入了攻击代码，

js代码如下

```javascript
let redirectUrl = url.getParams('redirecturl');
redirectUrl && window.location.href = redirectUrl;
```

这样的一段代码就会遇到一个问题，页面请求后会将用户的cookie alert出来，这样用户的一些敏感内容就被攻击者拿到了。

解决方案：对url中拿到的参数做校验，不能直接执行。

```javascript
let redirectUrl = url.getParams('redirecturl');

// 简单的校验，具体的校验规则视参数场景而定
let redirectUrlValidate = /^(https?:)?\/\/.+/gi.test(redirectUrl);
if (!redirectUrlValidate) {
    note('跳转失败，请重试！');
    return;
}

redirectUrl && window.location.href = redirectUrl;
```

参考

* [前端安全系列（一）：如何防止XSS攻击？](https://tech.meituan.com/2018/09/27/fe-security.html)
