前端安全

XSS(Cross Site Scripting)跨站脚本攻击

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

XSS 分为三种:反射型,存储型和 DOM-based

攻击方式

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

例如:某个搜索功能,通过 URL 获取某些参数

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

当执行搜素操作时,URL 中的 JS 代码会被执行,这样,页面中就会凭空多出了一弹框。

那如果是获取 cookie 然后发给黑客服务器呢?是不是就有很大的安全隐患了。

根据攻击来源,XSS 攻击可以分为:

  • 存储型
  • 反射型
  • DOM 型

储存型

储存型 XSS 的攻击步骤:

  1. 攻击者将恶意代码提交到目标网站的数据库中
  2. 当用户打开目标网站时,网站服务端将恶意代码取出后,然后返回给浏览器。
  3. 浏览器执行恶意代码

这种攻击常见于保存用户数据的网站,如论坛发帖,商品评论等。

反射型

反射型 XSS 的攻击步骤:

  1. 攻击者构造出特殊的 URL 请求,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL,浏览器执行恶意代码。

反射型和储存型的区别:

  1. 储存型 XSS 的恶意代码放在数据里,反射型 XSS 的恶意代码放在 URL 里。
  2. 反射型 XSS 漏洞常见于 URL 传递参数的功能,如搜索,跳转
  3. 储存型 XSS 常见于通过用户提交的内容,如论坛留言,评论等

DOM 型 XSS

DOM 型 XSS 的攻击步骤:

  1. 攻击者构造出特殊的 URL,其中包含恶意代码
  2. 用户打开带有恶意代码的 URL
  3. 用户浏览器接受到响应后解析执行,前端 JavaScript 去除 URL 中的恶意代码并执行
  4. 恶意代码窃取用户数据并且发送到攻击者的网站,或者冒充用户行为完成恶意操作。

DOM 型 XSS 与前两种 XSS 的区别:

DOM 型 XSS 攻击中,取出和执行恶意代码都由浏览器端完成,是 JavaScript 自身的安全漏铜,而其他两种 XSS 都是服务端的漏铜。

防御方式

通过前面的介绍,看到 XSS 攻击的两大因素:

  1. 攻击者提交恶意代码
  2. 浏览器执行恶意代码

针对第一个要素,在用户输入的内容时进行过滤掉恶意代码。

针对第二个,则应该是在后端写入数据库时,对数据进行过滤。

前端处理的方式可以使用字符串替换的方法,例如:

function escape(str) {
  str = str.replace(/&/g, "&amp;");
  str = str.replace(/</g, "&lt;");
  str = str.replace(/>/g, "&gt;");
  str = str.replace(/"/g, "&quto;");
  str = str.replace(/'/g, "&#39;");
  str = str.replace(/`/g, "&#96;");
  str = str.replace(/\//g, "&#x2F;");
  return str;
}
1
2
3
4
5
6
7
8
9
10

上面的函数就可以将恶意代码进行转译。

也可以借助js-xssopen in new window来实现。

通过以上我们可以得出,用户输入不可信,所以使用一些 API 时需要各位的注意,比如.innerHTML、outerHTML、document.write,还有一些框架的 API,比如 Vue 的 v-html 等,使用时都需要谨慎一些。

CSRF(Cross-site request forgery)跨站请求伪造

CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求

简单来说,CSRF 就是利用用户的登录态发起恶意请求。

攻击方式

CSRF 攻击流程:

  1. 受害者登录 a.com,并保留了登录凭证(cookie)’
  2. 攻击者引诱受害者访问 b.com
  3. b.com 向 a.com 发送一个请求:a.com?act=xx,会默认携带 a.com 的 cookie
  4. a.com 收到请求后,会执行相应的操作。
  5. 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让 a.com 执行了自己定义的操作。

POST 攻击

<form action="http://bank.example/withdraw" method=POST>
    <input type="hidden" name="account" value="xiaoming" />
    <input type="hidden" name="amount" value="10000" />
    <input type="hidden" name="for" value="hacker" />
</form>
<script> document.forms[0].submit(); </script>
1
2
3
4
5
6

这是一个自动提交表单的 POST 请求,当用户访问该页面时,表单会自动提交,然后模拟用户完成一个 POST 操作。

GET 攻击

<a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank">
    重磅消息!!
<a/>
// 也可以使用img的url
1
2
3
4

这种需要用户点击某个链接,然后自动请求某个网站模拟用户的操作。

CSRF 的特点

  • 攻击一般发生在第三方网站,而不是被攻击的网站,被共计的网站无法防止攻击发生。
  • 攻击利用受害者在被攻击网站的登录凭证(cookie),冒充受害者进行各种操作,而不是窃取数据。
  • 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”
  • 跨站请求可以用各种方式:如图片 URL、超链接、CORS、Form 表单提交等。

CSRF 的防御

CSRF 通常从第三方网站发起,被攻击的网站无法防止攻击发生,只能通过增强自己网站针对 CSRF 的防护能力来提升安全性。

防止 CSRF 的常用方式如下:

  • 阻止不明外域的访问

    • 同源检测:通过 Http header Referer 判断是否是第三方网站发起的请求
  • SameSite:可以对 Cookie 设置 SameSite 属性,该设置 Cookie 不随着跨域请求发送,该属性可以很大程度减少 CSRF 的攻击,但是该属性目前并不是所有浏览器都兼容。

  • token

    • CSRF 攻击的基础是受害者在被攻击网站的登录态(coolie),而是用 token 可以防止这个问题,因为 token 不会自动携带,而是需要手动设置 header。

SQL 注入攻击

Sql 注入攻击,是通过将恶意的 SQL 语句插入到应用的输入参数中,在后台的服务器将 SQL 服务器上解析并执行的攻击。

攻击流程

  • 找出 SQL 漏洞的注入点
  • 判断数据库的类型和版本
  • 猜解用户名和密码以及 web 后台管理入口
  • 入侵和破坏

预防方式如下

  • 严格检查输入变量的类型和格式
  • 将 SQL 语句进行转译和过滤处理
  • 对访问数据库的应用采用防火墙

密码安全

对于需要储存密码的地方,需要对密码进行加密。

加盐

对于密码储存来说,必然是不能使用明文密码储存在数据库中的。否则一旦泄露,会对用户造成极大的损失。

并且不建议只对密码单纯的通过加密算法加密,因为存在彩虹表的关系。

// 加盐也就是给原密码添加字符串,增加原密码长度
sha256(sha1(md5(salt + password + salt)));
1
2

但是加盐也不能阻止被人盗号,只能确保不会暴露用户的真实密码,一旦攻击者得到用户的账号,就可以通过暴露方式破解密码。

对于暴力破解(穷举)这种情况,通常使用验证码、增加延迟验证时间、限制验证次数来制止。

并且一旦用户输入了错误的密码,也不能直接提示输错密码,而是提示账号或密码错误。