前端网络安全笔记

本文主要涉及6个内容:

  • HTTP与HTTPS
  • 同源策略(Same-origin policy,简称 SOP)/ 跨域资源共享(Cross-Origin Resource Sharing,简称 CORS)
  • 跨站脚本攻击(Cross-Site Scripting,简称 XSS)
  • 跨站请求伪造(Cross-site request forgery,简称 CSRF)
  • Ifame安全
  • 中间人攻击(Man-in-the-MiddleAttack,简称MITM)

HTTP与HTTPS

众所周知,HTTP(Hypertext Transfer Protocol)超文本传输协议有着许多优点,包括但不限于:

  1. 灵活可扩展,可以传输任意数据类型的数据对象;
  2. 无状态,每一次请求都是独立的,请求结束不会记录连接的任何信息,减少了网络开销,这是优点也是缺点
  3. 无连接,每一次请求都要连接一次,请求结束就会断掉,不会保持连接(HTTP1.1后可以保持连接长连

但是HTTP有一个致命的缺陷,它是明文传输的,这些明文数据会经过WiFi、路由器、运营商、机房等多个物理设备节点,如果在这中间任意一个节点被监听,传输的内容就会完全暴露,这一攻击手法叫做MITM(Man-in-the-MiddleAttack)中间人攻击。

为了解决HTTP明文传输数据可能导致的安全问题,1994年网景公司提出了HTTPS(HyperText Transfer Protocol Secure)超文本传输安全协议。

它的原理是在应用层的HTTP和传输层的TCP的传输中建立了一个安全层,这个所谓的“安全层”主要由SSL/TLS协议来承担责任。对于这两个协议,我们只需要知道SSL(Secure Sockets Layer)是一种早期的安全协议,现已被广泛淘汰。TLS(Transport Layer Security)是SSL的后继者,更安全可靠,并且是当前使用最广泛的安全协议,详细的暂且不表。

HTTPS连接的握手过程:

这里我借用掘金大佬的一张图并加以改造~

前端网络安全笔记

大体流程如下:

  • 用户在浏览器发起HTTPS请求,并带上其支持的SSL/TLS版本以及加密算法列表,默认使用服务端的443端口进行连接;

  • HTTPS需要使用一套CA数字证书,证书内会附带一个公钥Pub,而与之对应的私钥Private保留在服务端不公开;

  • 服务端收到请求,返回配置好的包含公钥Pub的证书给客户端;

  • 客户端收到证书,校验合法性,主要包括是否在有效期内、证书的域名与请求的域名是否匹配,上一级证书是否有效(递归判断,直到判断到系统内置或浏览器配置好的根证书),如果不通过,则显示HTTPS警告信息,如果通过则继续;

  • 客户端生成一个用于对称加密的随机Key,并用证书内的公钥Pub进行加密,发送给服务端;

  • 服务端收到随机Key的密文,使用与公钥Pub配对的私钥Private进行解密,得到客户端真正想发送的随机Key

  • 服务端使用客户端发送过来的随机Key对要传输的HTTP数据进行对称加密,将密文返回客户端;

  • 客户端使用随机Key对称解密密文,得到HTTP数据明文;

  • 后续HTTPS请求使用之前交换好的随机Key进行对称加解密。

HTTPS的特点

了解完HTTPS连接的建立过程,我们可以大致介绍下HTTPS相对于HTTP的特点:

  1. HTTP 是明文传输,HTTPS 协议是可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。
  2. HTTPS对搜索引擎更友好,利于 SEO;谷歌、百度优先索引 HTTPS 网页。
  3. HTTPS 标准端口 443,HTTP 标准端口 80。
  4. HTTPS 需要用到SSL证书,而 HTTP 不用。

上面我们提到了SSL证书,这是HTTPS必不可少的一环,服务端在使用HTTPS前,去经过认证的CA机构申请颁发一份数字证书很贵。。。),数字证书里包含有证书持有者、证书有效期、公钥等信息,服务端将证书发送给客户端,客户端校验证书身份和要访问的网站身份确实一致后再进行后续的加密操作。

如何接入HTTPS

参考我的博客接入HTTPS的经历,大致可以分为三个步骤:

  1. 购买SSL证书,通常需要到数字证书授权机构购买
  2. 安装SSL证书,将购买的证书文件上传至CVM
  3. 更改nginx服务器配置,为nginx安装http_ssl_module模块,ningx.conf配置如下(伪代码):
server {
        listen 80;
        server_name  waylon.online;
        return 301 https://$host$request_uri; #把http的域名请求转成https
        }
server {
	listen          443 ssl http2;
        listen          [::]:443 ssl http2;
        server_name  waylon.online;

        ssl_certificate      ../XXXX.crt;
        ssl_certificate_key  ../XXXX.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;
        }

同源策略(SOP)

这里我们需要解答3个问题,什么是同源?为什么要存在同源策略?如何跨过同源策略?

什么是同源?

这个很简单,协议、域名、端口都一样,就是同源。

为什么要有存在同源策略?

同源策略是一种安全机制,它的存在是为了保护用户的隐私和安全。同源策略限制了浏览器内网页间的交互,使得来自不同源的脚本不能访问彼此的数据。这样可以避免恶意脚本通过操纵页面中的数据、Cookie等信息进行攻击,从而保护用户的隐私和安全。

如果没有同源策略的限制,那么就会出现跨站点脚本攻击(XSS)、跨站点请求伪造(CSRF)等安全问题,给用户带来风险和损失,浏览器需要背大锅。因此,同源策略是保护用户隐私和安全的重要手段之一。

如何跨过同源策略?(如何跨域)

在解答如何跨域之前,我们需要明白一个事实,跨域的请求是可以正常发送出去的,并且服务器也会接收到这个请求并且做出正确的回应,唯一与同源请求不同的点是浏览器会把跨域请求的返回隐藏,并且无法通过javascript获取请求的返回。具体可以参考这篇博客《跨域的请求在服务端会不会真正执行?》,里面还将请求分为简单请求与复杂请求,服务端对于这两种请求的还会做出不一样的处理;

  • 简单请求:不管是否跨域,只要发出去了,一定会到达服务端并被执行,浏览器只会隐藏返回值;
  • 复杂请求:先发预检,预检不会真正执行业务逻辑,预检通过后才会发送真正请求并在服务端被执行;

言归正传,如何跨域?

  1. JSONP:利用 <script> 标签没有跨域限制的特性,通过动态创建 script 标签并指定 src 属性为跨域的 URL,服务端将数据以 JavaScript 函数调用的形式返回给客户端。
  2. CORS(Cross-Origin Resource Sharing):服务端设置响应头部信息,允许指定来源(Origin)的请求访问自己的资源,并且这个机制是浏览器自动实现的,不需要手动处理跨域请求。服务端设置 Access-Control-Allow-Origin。
  3. 正向代理,对客户端进行代理,通常前端本地开发常用的一种手段。
  4. 反向代理,对服务端进行代理,通过nginx将后端接口代理到代理到网站地址;
  5. postMessage:H5提供的API,主要是框架间的通信,可以实现跨域通信安全和稳健。
  6. WebSocket:基于 TCP 协议,适合实时性较高的场景,如在线聊天、直播弹幕等。
  7. img script link都是支持跨域的。

跨站脚本攻击(XSS)

是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全,任何可以输入的地方都有可能引起,包括表单、URL…

XSS分为3种类型:分别是存储型XSS攻击、反射型XSS攻击、基于DOM的XSS攻击

存储型 XSS攻击(Server)

存储型 XSS 攻击大致需要经过如下步骤:

  1. 首先黑客利用站点漏洞将一段恶意 JavaScript 代码提交到被攻击的网站的数据库中
  2. 然后用户向网站请求包含了恶意 JavaScript 脚本的页面;
  3. 当用户浏览该页面的时候,恶意脚本就会将用户的 Cookie 信息等数据上传到服务器。

场景:见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。

反射型 XSS 攻击(Server)

反射型 XSS攻击与存储型 XSS攻击的区别在于:与存储型的区别在于,存储型的恶意代码存储在数据库中,反射型的恶意代码在URL上,其步骤如下:

  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

场景:通过 URL 传递参数的功能,如网站搜索、电子邮件、社交网络等途径跳转等。

基于 DOM的 XSS攻击(Client)

基于DOM 的XSS 攻击是指攻击者利用客户端脚本对DOM进行修改,从而导致恶意脚本的执行。这种攻击方式的特点是不需要向服务器发送请求,因此可以避开某些安全措施和过滤机制,其步骤如下:
基于DOM的XSS攻击的流程如下:

  1. 攻击者通过某种方式,将恶意脚本代码插入到网页中的某个元素中,比如一个输入框或者链接等。
  2. 受害者浏览器通过解析HTML代码生成文档对象模型(DOM)树,恶意脚本代码被加入到DOM树中。
  3. 当受害者与网页进行交互时,例如点击一个链接、提交表单等操作,浏览器就会执行恶意脚本代码。
  4. 恶意脚本代码可以执行一些攻击者预设好的操作,如窃取cookie信息、更改页面内容、将受害者重定向到恶意网站等。

场景:需要具体情况具体分析,一般来说与前端交互比较频繁的网站更容易受到此类攻击。

XSS攻击 常见攻击手段

  • 在 HTML 中内嵌的文本中,恶意内容以 script 标签形成注入。
  • 在内联的 JavaScript 中,拼接的数据突破了原本的限制(字符串,变量,方法名等)。
  • 在标签属性中,恶意内容包含引号,从而突破属性值的限制,注入其他属性或者标签。
  • 在标签的 href、src 等属性中,包含 javascript: (伪协议)等可执行代码。
  • 在 onload、onerror、onclick 等事件中,注入不受控制代码。
  • 在 style 属性和标签中,包含类似 background-image:url(“javascript:…”); 的代码(新版本浏览器已经可以防范)。
  • 在 style 属性和标签中,包含类似 expression(…) 的 CSS 表达式代码(新版本浏览器已经可以防范)。

XSS 攻击防御措施

  1. 现代浏览器是支持防御部分XSS 攻击功能的,只需要在http设置X-XSS-Protection响应标头,告诉浏览器开始XSS防护,即可防御部分XSS攻击,值1指示浏览器启用其XSS过滤器,而值0则禁用它。另一个值mode=block告诉浏览器如果检测到XSS攻击,则阻止整个页面。
  2. 在Cookie和HTTP头中设置HTTP-Onlysecure属性,以避免被XSS攻击者获取。
  3. 合理使用CSP(Content Security Policy)来限制第三方内容的注入,它分别可以使用HTTP请求、HTML mate表情的形式来开启,如下;

http响应头设置白名单

Content-Security-Policy: default-src 'self'; script-src 'self' waylon.com

HTML mate设置白名单

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' waylon.com">
  1. 输入验证:比如一些常见的数字、URL、电话号码、邮箱地址等等做校验判断;
  2. 对于从数据库获取的一些敏感数据,需要进行适当的编码和过滤,以避免被攻击者利用,防存储型。
  3. 对于HTML注入进行过滤(Vue/React 技术栈,避免使用 v-html / dangerouslySetInnerHTML),例如(伪代码):
let regex = /^url\("&quot;.*&quot;"\)$/;
    if(node.style && node.style['backgroundImage'] && regex.test(node.style['backgroundImage'])){
        node.style['backgroundImage'] = ''; // 防范background-image: url('javascript:alert("XSS")');
    }

跨站请求伪造(CSRF)

CSRF 攻击是攻击者利用浏览器在发起请求时自动带上 cookie 的特性,借助受害者的 Cookie 骗取服务器的信任,可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击服务器,从而在并未授权的情况下执行在权限保护之下的操作。

CSRF 攻击流程:

  1. 受害者登录 a.com,并保留了登录凭证(Cookie);
  2. 攻击者引诱受害者访问了b.com
  3. b.coma.com 发送了一个请求:a.com/act=xx浏览器会默认携带a.com的Cookie;
  4. a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求;
  5. a.com以受害者的名义执行了act=xx
  6. 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作;

前端网络安全笔记

CSRF 攻击类型:

  • ET型:如在页面的某个 img 中发起一个 get 请求
  • POST型:通过自动提交表单到恶意网站
  • 链接型:需要诱导用户点击链接

CSRF 攻击的防御措施:

  1. Cookie 的 SameSite 属性,对于现代浏览器,在 HTTP 响应头中,通过 set-cookie 字段设置 Cookie 时,可以带上 SameSite 选项。其兼容性可参考caniuse
    • Strict 仅允许一方请求携带 Cookie,即浏览器将只发送相同站点请求的 Cookie,即当前网页 URL 与请求目标 URL 完全一致。
    • Lax 允许部分第三方请求携带 Cookie
    • None 无论是否跨站都会发送 Cookie
      前端网络安全笔记
  2. 同源检查,由服务器端验证当前请求的来源站点,HTTP 请求头中的 Referer 和 Origin 属性;
  3. 页面级别的token,将Token输出到页面中,页面提交的请求携带这个Token,服务器验证Token是否正确;
  4. 验证码,后端接口加验证码校验,让攻击方无法在用户无感知的情况下正常调用接口

iframe安全

iframe的安全问题其实分别属于不同的区域,只不过我们在富文本、微前端等领域都有对iframe的广泛应用,所以单独拎出来讲。

ifame带来的安全问题

iframe在应用过程中可能会出现的问题主要有以下三种:

  1. 嵌入第三方 iframe 会有很多不可控的问题,同时当第三方 iframe 出现问题或是被劫持之后,也会诱发安全性问题;
  2. 通过iframe通信机制操作外部网站js;
  3. 点击劫持,攻击者将需要攻击的网站通过iframe嵌套的⽅式嵌⼊自己的网页中,并将 iframe 设置为透明,在页面中透出⼀个按钮诱导⽤户点击,案例如下:
<!DOCTYPE html>
<html>
<head>
	<title>攻击者的网页</title>
	<style type="text/css">
	iframe {
		position: absolute;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		border: none;
		opacity: 0.5; /* 将iframe设置为透明 */
		z-index: -1; /* 将iframe放到最底层 */
	}
	button {
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		font-size: 24px;
		padding: 12px 24px;
		background-color: #f00;
		color: #fff;
		border: none;
		border-radius: 4px;
		cursor: pointer;
	}
	</style>
</head>
<body>
	<iframe src="https://www.example.com"></iframe> <!-- 将需要攻击的网站通过iframe嵌套的方式嵌入攻击者的网页中 -->
	<button onclick="alert('你被骗了!')">点击这里领取礼品</button> <!-- 在页面中透出一个按钮诱导用户点击 -->
</body>
</html>

如何防御iframe安全问题

  1. 设置 CSP,这个上文XSS中有介绍过,不再赘述
  2. 设置 X-Frame-Options 响应头,拒绝页面被嵌套,X-Frame-Options 是HTTP 响应头中用来告诉浏览器一个页面是否可以嵌入iframe中;
    X-Frame-Options: SAMEORIGIN; iframe 页面的地址只能为同源域名下的页面
    X-Frame-Options: ALLOW-FROM; 可以嵌套在指定来源的 iframe 里
    X-Frame-Options: DENY; 当前页面不能被嵌套在 iframe 里
    
  3. 为 iframe 设置 sandbox 属性,通过它可以对iframe的行为进行各种限制,充分实现“最小权限”原则;

sanbox主要属性有:

  • allow-forms:允许在iframe中提交表单数据。
  • allow-modals:允许在iframe中打开模态对话框(modal dialogs)。
  • allow-orientation-lock:允许在iframe中锁定屏幕方向。
  • allow-pointer-lock:允许在iframe中使用Pointer Lock API,这个API可以隐藏鼠标指针并且从鼠标事件中获取移动值,通常适用于一些游戏和3D场景。
  • allow-popups:允许在iframe中打开弹出窗口,但不会自动打开它们。
  • allow-presentation:允许在iframe中打开全屏幕的演示文稿。
  • allow-same-origin:只允许加载与父文档同源的文档,这是sandbox属性默认的限制。
  • allow-scripts:允许在iframe中运行脚本代码。
  • allow-storage-access-by-user-activation:允许通过用户操作来授予iframe访问同源localStorage和sessionStorage的权限。
  • allow-top-navigation:允许在iframe中导航到顶层窗口中的不同URL。如果不想允许该行为,可以将此属性设置为不存在或空字符串。

中间人攻击(MITM)

中间人攻击是攻击方同时与服务端和客户端建立起了连接,并让对方认为连接是安全的,但是实际上整个通信过程都被攻击者控制了。攻击者不仅能获得双方的通信信息,还能修改通信信息。我们大名鼎鼎的抓包工具Charles便是运用了中间人攻击的原理来实现的。

如何防范中间人攻击

  1. 使用可靠的证书:在为网站或应用程序配置SSL/TLS时,确保使用来自受信任的证书颁发机构(CA)的证书。这将有助于防止攻击者创建伪造的证书并欺骗用户。
  2. 避免在公共网络上进行敏感操作:在使用公共Wi-Fi等公共网络时,请避免执行敏感操作,例如银行业务或网上购物等。攻击者可能会通过中间人攻击窃取您的敏感信息。
  3. 对用户强制HTTPS:在编写Web应用程序时,可以使用HTTP Strict Transport Security(HSTS)来强制用户始终使用HTTPS连接访问您的网站。这可以提高安全性并保护用户不受中间人攻击

如何开启HSTS

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

HTTPS可以防范所有中间人攻击吗

答案是不能,试想我们平常在抓包的时候,不少https请求依然可以有效抓到他们的返回并且实现代理,这意味着仅仅升级HTTPS并不能有效防范所有的中间人攻击。

如果攻击者能够劫持证书颁发机构(CA),或自己创建一个假的CA颁发伪造的数字证书,就有可能欺骗浏览器并进行中间人攻击。此外,如果用户在连接到不安全的公共WiFi热点时使用HTTPS协议,攻击者仍然可以通过其他手段实现中间人攻击。因此,用户需要多加注意网络安全,以免遭受中间人攻击。

这种情况浏览器会提示用户存在风险,如果点击【继续】就很有可能受到中间人攻击,如果用户在浏览器【证书】中新任了这个证书,那么后续浏览器更是不会再弹出这个警告。

以上就是前端领域常见的网络安全问题,除此之外还有SQL注入式攻击、OS攻击等这里就不做介绍了~

参考文献:

原文链接:https://juejin.cn/post/7216915438298333242 作者:waylon11113

(0)
上一篇 2023年4月2日 上午10:47
下一篇 2023年4月2日 上午10:57

相关推荐

发表回复

登录后才能评论