# 8.网络攻防,如 XSS、CSRF、SQL 注入攻击
前端常见安全问题的十个方面:
- iframe
- opener
- CSRF(跨站请求伪造)
- XSS(跨站脚本攻击)
- ClickJacking(点击劫持)
- HSTS(HTTP 严格传输安全)
- CND 劫持
- HTTPS 中间人攻击
- SQL 注入
- Dos 服务拒绝攻击
# 一、iframe
# 1. 如何让自己的网站不被其他网站的 iframe 引用?
// 检测当前网站是否被第三方iframe引用
// 若相等证明没有被第三方引用,若不等证明被第三方引用。当发现被引用时强制跳转百度。
if (top.location != self.location) {
top.location.href = "http://www.baidu.com";
}
2
3
4
5
- i)嵌入第三方 iframe 会有很多不可控的问题,同时当第三方 iframe 出现问题或是被劫持之后,也会诱发安全性问题
- ii)点击劫持
- 攻击者将目标网站通过 iframe 嵌套的方式嵌入自己的网页中,并将 iframe 设置为透明,诱导用户点击。
- iii)禁止自己的 iframe 中的链接外部网站的 JS
# 2. 如何禁用被使用的 iframe 对当前网站某些操作?
sandbox 是 html5 的新属性,主要是提高 iframe 安全系数。iframe 因安全问题而臭名昭著,这主要是因为 iframe 常被用于嵌入到第三方中,然后执行某些恶意操作。 现在有一场景:我的网站需要 iframe 引用某网站,但是不想被该网站操作 DOM、不想加载某些 js(广告、弹框等)、当前窗口被强行跳转链接等,我们可以设置 sandbox 属性。如使用多项用空格分隔。
- allow-same-origin:允许被视为同源,即可操作父级 DOM 或 cookie 等
- allow-top-navigation:允许当前 iframe 的引用网页通过 url 跳转链接或加载
- allow-forms:允许表单提交
- allow-scripts:允许执行脚本文件
- allow-popups:允许浏览器打开新窗口进行跳转
- “”:设置为空时上面所有允许全部禁止
# 二、opener
如果在项目中需要 打开新标签 进行跳转一般会有两种方式
// 1) HTML -> <a target='_blank' href='http://www.baidu.com'>
// 2) JS -> window.open('http://www.baidu.com')
/*
* 这两种方式看起来没有问题,但是存在漏洞。
* 通过这两种方式打开的页面可以使用 ==window.opener 来访问源页面的 window 对象==。
* 场景:A 页面通过 <a> 或 window.open 方式,打开 B 页面。但是 B 页面存在恶意代码如下:
* window.opener.location.replace('https://www.baidu.com') 【此代码仅针对打开新标签有效】
* 此时,用户正在浏览新标签页,但是原来网站的标签页已经被导航到了百度页面。
* 恶意网站可以伪造一个足以欺骗用户的页面,使得进行恶意破坏。
* 即使在跨域状态下 opener 仍可以调用 location.replace 方法。
*/
2
3
4
5
6
7
8
9
10
11
12
解决方案:
# 1. 通过 rel 属性进行控制
<a target="_blank" href="" rel="noopener noreferrer nofollow">a标签跳转url</a>
<!--
通过 rel 属性进行控制:
noopener:会将 window.opener 置空,从而源标签页不会进行跳转(存在浏览器兼容问题)
noreferrer:兼容老浏览器/火狐。禁用HTTP头部Referer属性(后端方式)。
nofollow:SEO权重优化,详情见 https://blog.csdn.net/qq_33981438/article/details/80909881
-->
2
3
4
5
6
7
# 2.window.open()
<button onclick='openurl("http://www.baidu.com")'>click跳转</button>
function openurl(url) { var newTab = window.open(); newTab.opener =
null;//将oper设置为null就好了 newTab.location = url; }
2
3
4
# 三、CSRF/XSRF(跨站请求伪造)
你可以这么理解 CSRF 攻击:攻击者盗用了你的身份,以你的名义进行恶意请求。它能做的事情有很多包括:以你的名义发送邮件、发信息、盗取账号、购买商品、虚拟货币转账等。总结起来就是:个人隐私暴露及财产安全问题。
/*
* 阐述 CSRF 攻击思想:(核心2和3)
* 1、浏览并登录信任网站(举例:淘宝)
* 2、登录成功后在浏览器产生信息存储(举例:cookie)
* 3、用户在没有登出淘宝的情况下,访问危险网站
* 4、危险网站中存在恶意代码,代码为发送一个恶意请求(举例:购买商品/余额转账)
* 5、携带刚刚在浏览器产生的信息进行恶意请求
* 6、淘宝验证请求为合法请求(区分不出是否是该用户发送)
* 7、达到了恶意目标
*/
2
3
4
5
6
7
8
9
10
攻击类型
- i)GET 型:如在页面的某个 img 中发起一个 get 请求
- 因为自动携带 cookie
- ii)POST 型:通过自动提交表单到恶意网站
- 模拟提交操作
- iii)链接型:需要诱导用户点击链接
- 点击即攻击成功
与 XSS 不同的是,XSS 是攻击者直接对我们的网站 A 进行注入攻击,CSRF 是通过网站 B 对我们的网站 A 进行伪造请求。
与 XSS 最为不同一点是 CSRF 可以不用 JS 就能达到目的(GET 和 POST 的区别)
举个例子,你登录购物网站 A 之后点击一个恶意链接 B,B 请求了网站 A 的下单接口,结果是你在网站 A 的帐号真的会生成一个订单。其背后的原理是:网站 B 通过表单、get 请求来伪造网站 A 的请求,这时候请求会带上网站 A 的 cookies,若登录态是保存在 cookies 中,则实现了伪造攻击。
# 防御措施(推荐添加 token / HTTP 头自定义属性)
- 防御思路:
- 阻止不明外域的访问
- 同源检测
- Samesite Cookie
- 提交时要求附加本域才能获取的信息
- CSRF Token
- 双重 Cookie 验证
# 阻止不明外域的访问
- 涉及到数据修改操作严格使用 post 请求而不是 get 请求(因为普通 get 请求不会有跨域问题,自动携带 cookie)
- HTTP 协议检测 HTTP referer(Origin Header 、Referer Header) 字段同域 (检测是否跨域)(在 IE6、7 存在漏洞,302 请求、HTTPS 跳转 HTTP、flash 不适用)
# 提交时要求附加本域才能获取的信息
# token
- 请求地址添加 token ,使黑客无法伪造用户请求(token 即防伪码,不在 cookie 中。随机产生,一般放在 session 中)
- 给所有 a 和 form 标签添加 token
- GET、POST 请求添加 token 参数,form 请求在 value 里面添加 token 参数
- HTTP 头自定义属性验证(类似上一条,如:把 token 放在 HTTP 头自定义属性中,通过 XMLHttpRequest 给所有该类请求加上 csrftoken 这个 HTTP 头属性。并把 token 值放入其中。(这样更方便,也不会被记录在地址栏,或者 token 通过 referer 泄露))
- 显示验证方式:添加验证码、密码等
- 服务端验证
- 使用 session 存储 Token
- 但是在分布式的时候,不同后端机器 session 的 token 不能同步,所以可以使用 redis 进行统一存储。
- Encrypted Token Pattern: 使用计算的形式验证 token 是否合法
- 使用 session 存储 Token
# 不使用 token,使用双重 Cookie 验证
- 在用户访问网站页面时,向请求域名注入一个 Cookie,内容为随机字符串(例如 csrfcookie=v8g9e4ksfhw)。
- 在前端向后端发起请求时,取出 Cookie,并添加到 URL 的参数中(接上例 POST https://www.a.com/comment?csrfcookie=v8g9e4ksfhw)。
- 后端接口验证 Cookie 中的字段与 URL 参数中的字段是否一致,不一致则拒绝。
但是,在大型网站上的安全性还是没有 CSRF Token 高:
- 由于任何跨域都会导致前端无法获取 Cookie 中的字段(包括子域名之间),于是发生了如下情况:
- 如果用户访问的网站为www.a.com,而后端的api域名为api.a.com。那么在www.a.com下,前端拿不到api.a.com的Cookie,也就无法完成双重Cookie认证。
- 于是这个认证 Cookie 必须被种在 a.com 下,这样每个子域都可以访问。
- 任何一个子域都可以修改 a.com 下的 Cookie。
- 某个子域名存在漏洞被 XSS 攻击(例如 upload.a.com)。虽然这个子域下并没有什么值得窃取的信息。但攻击者修改了 a.com 下的 Cookie。
- 攻击者可以直接使用自己配置的 Cookie,对 XSS 中招的用户再向www.a.com下,发起CSRF攻击。
用双重 Cookie 防御 CSRF 的优点:
- 无需使用 Session,适用面更广,易于实施。
- Token 储存于客户端中,不会给服务器带来压力。
- 相对于 Token,实施成本更低,可以在前后端统一拦截校验,而不需要一个个接口和页面添加。
缺点:
- Cookie 中增加了额外的字段。
- 如果有其他漏洞(例如 XSS),攻击者可以注入 Cookie,那么该防御方式失效。
- 难以做到子域名的隔离。
- 为了确保 Cookie 传输安全,采用这种防御方式的最好确保用整站 HTTPS 的方式,如果还没切 HTTPS 的使用这种方式也会有风险。
# Samesite Cookie 属性
它用来标明这个 Cookie 是个“同站 Cookie”,同站 Cookie 只能作为第一方 Cookie,不能作为第三方 Cookie,Samesite 有两个属性值,分别是 Strict 和 Lax
我们应该如何使用 SamesiteCookie 如果 SamesiteCookie 被设置为 Strict,浏览器在任何跨域请求中都不会携带 Cookie,新标签重新打开也不携带,所以说 CSRF 攻击基本没有机会。
但是跳转子域名或者是新标签重新打开刚登陆的网站,之前的 Cookie 都不会存在。尤其是有登录的网站,那么我们新打开一个标签进入,或者跳转到子域名的网站,都需要重新登录。对于用户来讲,可能体验不会很好。
如果 SamesiteCookie 被设置为 Lax,那么其他网站通过页面跳转过来的时候可以使用 Cookie,可以保障外域连接打开页面时用户的登录状态。但相应的,其安全性也比较低。
另外一个问题是 Samesite 的兼容性不是很好,现阶段除了从新版 Chrome 和 Firefox 支持以外,Safari 以及 iOS Safari 都还不支持,现阶段看来暂时还不能普及。
而且,SamesiteCookie 目前有一个致命的缺陷:不支持子域。例如,种在 topic.a.com 下的 Cookie,并不能使用 a.com 下种植的 SamesiteCookie。这就导致了当我们网站有多个子域名时,不能使用 SamesiteCookie 在主域名存储用户登录信息。每个子域名都需要用户重新登录一次。
总之,SamesiteCookie 是一个可能替代同源验证的方案,但目前还并不成熟,其应用场景有待观望。
# 四、XSS(跨站脚本攻击)
- 反射型攻击:
http://example.com/search.php?query=<script>alert('恶意脚本执行!')</script>
- 存储型XSS攻击: 将脚本代码提交到评论区,其他人读到的时候就会执行脚本
- DOM型XSS攻击:
function changeTitle() {
var userInput = window.location.hash.substring(1); // 从URL中获取用户输入
document.title = userInput; // 将用户输入设置为页面标题
}
document.getElementById('link').addEventListener('click', changeTitle);
`http://example.com/#<script>alert('恶意脚本执行!')</script>`
2
3
4
5
6
7
类型 存储区 插入点 反射型 URL HTML 存储型 后端数据库 HTML DOM 型 后端数据库/前端存储/URL 前端 JavaScript
XSS 又叫 CSS(Cross Site Script),跨站脚本攻击:攻击者在目标网站植入恶意脚本(js / html),用户在浏览器上运行时可以获取用户敏感信息(cookie / session)、修改 web 页面以欺骗用户、与其他漏洞相结合形成蠕虫等。
原理:浏览器遇到 html 中的 script 标签时,会解析并执行其中的 js 代码
针对这种情况,我们对特殊字符进行转译就好了(vue/react 等主流框架已经避免类似问题,vue 举例:不能在 template 中写 script 标签,无法在 js 中通过 ref 或 append 等方式动态改变或添加 script 标签)
XSS 类型:
持久型 XSS:将脚本植入到服务器上,从而导致每个访问的用户都会执行
场景:见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。
攻击步骤:
i)攻击者将恶意代码提交到目标网站的数据库中
ii)用户打开目标网站时,服务端将恶意代码从数据库中取出来,拼接在 HTML 中返回给浏览器
iii)用户浏览器在收到响应后解析执行,混在其中的恶意代码也同时被执行
iv)恶意代码窃取用户数据,并发送到指定攻击者的网站,或者冒充用户行为,调用目标网站的接口,执行恶意操作
非持久型 XSS:对个体用户某 url 的参数进行攻击
与持久型的区别在于,持久型的恶意代码存储在数据库中,反射型的恶意代码在 URL 上
场景:通过 URL 传递参数的功能,如网站搜索、跳转等。
攻击步骤:
i)攻击者构造出特殊的 URL,其中包含恶意代码。
ii)用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
iii)用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
iv)恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
一般 XSS 可以做到以下的事情:
- 获取页面的数据,包括 dom、cookies、localStorage 等
- 劫持前端逻辑
- 发送请求
存在风险的代码:
<template>
<p>{{username}}</p>
</template>
<script>
username = "<script>alert('xss')</script>"
</script>
2
3
4
5
6
7
# 防御措施(对用户输入内容和服务端返回内容进行过滤和转译)
- 现代大部分浏览器都自带 XSS 筛选器,vue / react 等成熟框架也对 XSS 进行一些防护
- 对用户输入内容和服务端返回内容进行过滤和转译
- 通过转义
<
为<
以及>
为>
来实现防御 HTML 节点内容,除此之外,JS 代码,富文本都有可能被攻击。 - 重要内容加密传输
- 合理使用 get/post 等请求方式
- 对于 URL 携带参数谨慎使用
- 我们无法做到彻底阻止,但是能增加黑客攻击成本,当成本与利益不符时自然会降低风险
# 五、ClickJacking(点击劫持)
ClickJacking 翻译过来被称为点击劫持。一般会利用透明 iframe 覆盖原网页诱导用户进行某些操作达成目的。
防御措施
- 在 HTTP 投中加入 X-FRAME-OPTIONS 属性,此属性控制页面是否可被嵌入 iframe 中【DENY:不能被所有网站嵌套或加载;SAMEORIGIN:只能被同域网站嵌套或加载;ALLOW-FROM URL:可以被指定网站嵌套或加载。】
- 判断当前网页是否被 iframe 嵌套(详情在第一条 firame 中)
# 六、HSTS(HTTP Strict Transport Security:HTTP 严格传输安全)
网站接受从 HTTP 请求跳转到 HTTPS 请求的做法,例如我们输入“http://www.baidu.com (opens new window)”或“[www.baidu.com”最终都会被302重定向。这就存在安全风险,当我们第一次通过 HTTP 或域名进行访问时,302 重定向有可能会被劫持,篡改成一个恶意或钓鱼网站。
HSTS:通知浏览器此网站禁止使用 HTTP 方式加载,浏览器应该自动把所有尝试使用 HTTP 的请求自动替换为 HTTPS 进行请求。用户首次访问时并不受 HSTS 保护,因为第一次还未形成链接。我们可以通过 浏览器预置 HSTS 域名列表 或 将 HSTS 信息加入到域名系统记录中,来解决第一次访问的问题。
# 七、CDN 劫持
出于性能考虑,前端应用通常会把一些静态资源存放到 CDN(Content Delivery Networks)上面,例如 js 脚本和 style 文件。这么做可以显著提高前端应用的访问速度,但与此同时却也隐含了一个新的安全风险。如果攻击者劫持了 CDN,或者对 CDN 中的资源进行了污染,攻击者可以肆意篡改我们的前端页面,对用户实施攻击。 现在的 CDN 以支持 SRI 为荣,script 和 link 标签有了新的属性 integrity,这个属性是为了防止校验资源完整性来判断是否被篡改。它通过 验证获取文件的哈希值是否和你提供的哈希值一样来判断资源是否被篡改。 使用 SRI 需要两个条件:一是要保证 资源同域 或开启跨域,二是在
<script>
中 提供签名 以供校验。
# 八、HTTPS 中间人攻击
中间人攻击(Man-in-the-middle attack, MITM),指攻击者与通讯的两端分别创建独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者窃听、篡改甚至完全控制。**没有进行严格的证书校验是中间人攻击着手点。**目前大多数加密协议都提供了一些特殊认证方法以阻止中间人攻击。如 SSL (安全套接字层)协议可以验证参与通讯的用户的证书是否有权威、受信任的数字证书认证机构颁发,并且能执行双向身份认证。攻击场景如用户在一个未加密的 WiFi 下访问网站。在中间人攻击中,攻击者可以拦截通讯双方的通话并插入新的内容。
场景
- i)在一个未加密的 Wi-Fi 无线接入点的接受范围内的中间人攻击者,可以将自己作为一个中间人插入这个网络
- ii)Fiddler / Charles (花瓶)代理工具
- iii)12306 之前的自己证书
过程
- i)客户端发送请求到服务端,请求被中间人截获
- ii)服务器向客户端发送公钥
- iii)中间人截获公钥,保留在自己手上。然后自己生成一个【伪造的】公钥,发给客户端
- iv)客户端收到伪造的公钥后,生成加密 hash 值发给服务器
- v)中间人获得加密 hash 值,用自己的私钥解密获得真秘钥,同时生成假的加密 hash 值,发给服务器
- vi)服务器用私钥解密获得假密钥,然后加密数据传输给客户端
使用抓包工具 fiddle 来进行举例说明
- 首先通过一些途径在客户端安装证书
- 然后客户端发送连接请求,fiddle 在中间截取请求,并返回自己伪造的证书
- 客户端已经安装了攻击者的根证书,所以验证通过
- 客户端就会正常和 fiddle 进行通信,把 fiddle 当作正确的服务器
- 同时 fiddle 会跟原有的服务器进行通信,获取数据以及加密的密钥,去解密密钥
常见攻击方式
- 嗅探:嗅探是一种用来捕获流进和流出的网络数据包的技术,就好像是监听电话一样。比如:抓包工具
- 数据包注入:在这种,攻击者会将恶意数据包注入到常规数据中的,因为这些恶意数据包是在正常的数据包里面的,用户和系统都很难发现这个内容。
- 会话劫持:当我们进行一个网站的登录的时候到退出登录这个时候,会产生一个会话,这个会话是攻击者用来攻击的首要目标,因为这个会话,包含了用户大量的数据和私密信息。
- SSL 剥离:HTTPS 是通过 SSL/TLS 进行加密过的,在 SSL 剥离攻击中,会使 SSL/TLS 连接断开,让受保护的 HTTPS,变成不受保护的 HTTP(这对于网站非常致命)
- DNS 欺骗,攻击者往往通过入侵到 DNS 服务器,或者篡改用户本地 hosts 文件,然后去劫持用户发送的请求,然后转发到攻击者想要转发到的服务器
- ARP 欺骗,ARP(address resolution protocol)地址解析协议,攻击者利用 APR 的漏洞,用当前局域网之间的一台服务器,来冒充客户端想要请求的服务端,向客户端发送自己的 MAC 地址,客户端无从得到真正的主机的 MAC 地址,所以,他会把这个地址当作真正的主机来进行通信,将 MAC 存入 ARP 缓存表。
- 代理服务器
# 预防方案:
- i)用可信的第三方 CA 厂商
- ii)不下载未知来源的证书,不要去下载一些不安全的文件
- iii)确认你访问的 URL 是 HTTPS 的,确保网站使用了 SSL,确保禁用一些不安全的 SSL,只开启:TLS1.1,TLS1.2
- iv)不要使用公用网络发送一些敏感的信息
- v)不要去点击一些不安全的连接或者恶意链接或邮件信息
https://segmentfault.com/a/1190000013075736
如何预防中间人攻击
# 九、SQL 注入
就是通过把 SQL 命令插入到 Web 表单递交或输入域名或页面请求的查询字符串,最终达到欺骗数据库服务器执行恶意的 SQL 命令,从而达到和服务器进行直接的交互
预防方案:
- i)后台进行输入验证,对敏感字符过滤。
- ii)使用参数化查询,能避免拼接 SQL,就不要拼接 SQL 语句。
# 十、DoS 服务拒绝攻击(enial of Service)
带宽攻击:以极大的通信量冲击网络,使得所有可用网络资源都被消耗殆尽,最后导致合法的用户请求就无法通过。
连通性攻击:用大量的连接请求冲击计算机,使得所有可用的操作系统资源都被消耗殆尽,最终计算机无法再处理合法用户的请求。
- DDoS(分布式拒绝服务)
- 将多个计算机联合起来作为攻击平台,对一个或多个目标发动 DoS 攻击,从而成倍地提高拒绝服务攻击的威力。
- DDoS(分布式拒绝服务)