网络攻击与防御

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 获取某些参数

<!-- 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攻击?

防御

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

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 请求提交用户评论的接口,那么攻击者就可以在钓鱼 网站中加入一个图片,图片的地址就是评论接口

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

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

<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代码如下

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

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

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

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

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

redirectUrl && window.location.href = redirectUrl;

参考

Last updated