美文网首页
吃透浏览器安全(同源限制/XSS/CSRF/中间人攻击)

吃透浏览器安全(同源限制/XSS/CSRF/中间人攻击)

作者: IT沐华 | 来源:发表于2021-10-02 07:40 被阅读0次

    前言

    随着互联网的高速发展,信息安全问题已经成为企业最为关注的焦点之一,而前端又是引发企业安全问题的高危据点。在移动互联网时代,特别是前端人员除了传统的 XSS、CSRF 等安全问题之外,又时常遭遇网络劫持、非法调用 Hybrid API 等新型安全问题。当然,浏览器自身也在不断在进化和发展,不断引入 CSP、SameSite、HttpOnly、Cookies 等新技术来增强安全性,但是仍存在很多潜在的威胁,这需要我们不断进行“查漏补缺”

    浏览器安全可以分为三大块:Web页面安全、浏览器网络安全、浏览器系统安全

    Web页面安全主要就是同源策略限制

    什么是同源策略

    同源指的是我们访问站点的:协议域名端口号必须一至,才叫同源

    浏览器默认同源之间的站点是可以相互访问资源和操作DOM的,而不同源之间想要互相访问资源或者操作DOM,那就需要加一些安全策略的限制,俗称同源策略

    同源策略主要限制了三个方面:

    1. DOM层面:不同源站点之间不能相互访问和操作DOM
    2. 数据层面:不能获取不同源站点的Cookie、LocalStorage、indexDB等数据
    3. 网络层面:不能通过XMLHttpRequest向不同源站点发送请求

    当然同源策略限制也不是绝对隔离不同源的站点,比如link、img、script标签都没有跨域限制,这让我们开发更灵活了,但是也同样带来了一些安全问题,也就是浏览器网络安全问题,最典型的就是XSS攻击和CSRF攻击

    说一下XSS攻击

    XSS攻击是一种代码注入攻击,通过恶意注入脚本在浏览器运行,然后盗取用户信息

    造成XSS攻击其实本质上还是因为网站没有过滤恶意代码,与正常代码混在一起之后,浏览器没有办法分辨哪些是可信的,然后导致恶意代码也被执行。然后可能导致以下情况:

    • 页面数据或用户信息被窃取,如DOM、Cookie、LocalStorage
    • 修改DOM,比如伪造登录窗口或在页面生成浮窗广告
    • 监听用户行为,比如在登录或银行等站点用 addEventListener 监听键盘事件,窃取账号密码等信息
    • 流量被劫持向其他网站

    XSS攻击有三种类型:存储型反射型DOM型

    1. 存储型:是在有发贴评论等带有数据保存功能的网站的input、textarea将恶意代码提交到网站数据库中,如<script src="http://恶意网站"></script> ,然后比如在显示评论的页面就会从数据获取,并直接执行这个script标签里的恶意代码

    2. 反射型:是攻击者将恶意JS脚本作为用户发送给网站请求中的一部分,然后网站又把恶意脚本返回给用户,这时候就会在页面中被执行。比如打开包含带恶意脚本的链接,当打开后会向服务器请求后,服务器会获取URL中的数据然后拼接在HTML上返回,然后执行。它和存储型不同的是不会储存在服务器里

    3. 基于DOM型:就是攻击者通过一些劫持手段,在页面资源传输过程中劫持并修改页面的数据,插入恶意代码

    怎么防范XSS攻击,有什么解决办法?

    • 就是对输入框的内容进行过滤或使用转义符进行转码

      字符 转义后的字符
      < &lt;
      > &gt;
      " &quot;
      ' &#x27;
      / &#x2F
      & &amp;
    • 使用CSP,就是白名单,告诉浏览器哪些外部资源可以加载执行,让即使插入进来恶意代码的也不会执行,或者可以向哪些第三方站点提交数据。开启白名单的方式有两种:

      • 使用 meta 标签 <meta http-equiv="Content-Security-Policy">
      • 设置http头部的 Content-Security-Policy
    • 对一些敏感信息进行保护,在Cookie信息中添加httpOnly,告诉浏览器在保存Cookie,且不要对客户端脚本开放访问权限,然后就不能通过document.cookie获取cookie了

    Set-Cookie: widget_session=123456; httpOnly
    
    • 使用验证码,避免脚本伪装成用户执行一些操作

    说一下CSRF攻击

    就是跨站请求伪造攻击主要就是利用用户的登录状态发起跨站请求,比如邮箱里的乱七八糟的链接,打开链接的时候邮箱肯定是处于登录状态,然后黑客就可以用这个登录状态,伪造带有正确 Cookie 的 http 请求,直接绕过后台的登录验证,然后冒充用户执行一些操作

    发起CSRF攻击有三个必要条件:

    1. 目标网站一定要有CSRF漏洞
    2. 用户登录过目标网站,并且浏览器保存了登录状态
    3. 需要用户主动打开第三方站点

    本质是利用cookie在同源请求中携带发送给服务器的特点,来实现冒充用户

    CSRF攻击也有三种类型:GET类型POST类型链接型

    • 自动发GET类型:比如imgiframe标签等,当用户打开这个网站时会自动发起带Cookie的资源请求
    <img src="http://恶意网址" >
    
    • 自动发POST类型:比如整一个隐藏的表单,在用户进入页面的时候自动提交表单
    <form id="hack" action="https://恶意网址" method="post">
        ...
    </form>
    <script>document.getElementById('hack').submit()</script>
    
    • 诱导链接型:就是诱导用户主动点击链接,比如a标签
    <a href="https://恶意网址">点击领取大礼包</a>
    <a href="https://恶意网址">点击下载美女视频</a>
    

    怎么防范CSRF攻击,有什么解决办法?

    1. 在Cookie信息中添加SameSite属性,这个属性有三个值:

      • strict严格模式,完全禁止使用Cookie
      • lax宽松模式,允许部分情况使用Cookie,跨域的都行,a标签跳转,link标签,GET提交表单
      • none:任何情况下都会发送Cookie,但必须同时设置Secure属性,意思是需要安全上下文,Cookie 只能通过https发送,否则无效

      Chrome 80之前默认值是none,之后是lax

    Set-Cookie: widget_session=123456; SameSite=None; Secure
    
    1. 验证请求来源:服务器根据http请求头中的OriginReferer属性判断是否为允许访问的站点,从而对请求进行过滤。优先判断Origin,如果两个都不存在的话就直接阻止。
    • Referer:记录了请求是从哪个链接跳过来的并且包含了路径信息,也就是来源地址。不过这家伙不太可靠,所以后来又新增了Origin属性
    Referer: https://juejin.cn/editor/drafts/xxxx
    
    • origin:记录了域名信息,没有具体的URL路径
    Origin: https://juejin.cn
    
    1. Token验证:服务器向用户返回一个随机数Token,再次请求时在请求头中以参数的形式添加入这个Token,然后服务器验证这个Token,如果没有或者内容不正确,就拒绝请求。缺点是

      • 每个请求都得添加比较繁琐
      • 单方面验证Cookie可能会被冒用,
      • 如果网站不止一台服务器,通过负载均衡转到了其他服务器的话,其他所有服务器中的Session中都得保留Token,不然就验证不了了
    2. 双重验证Cookie:利用攻击者只能利用Cookie,不能获取Cookie的特点,用户访问页面时,服务器向请求域名添加一个Cookie随机字符串,然后,用户再次请求时从Cookie中取出这个字符串,添加到URL参数中,然后服务器通过对Cookie中的数据和参数中的数据对比验证,不一样就拒绝请求。

      缺点是如果网站存在XSS漏洞,这法子就会失效,而且不能做到子域名的隔离

    浏览器系统安全 - 安全沙箱

    首先,我们设想一下,如果我们下载了一个恶意程序,但是没有执行它,对我们有没有影响?

    那肯定没有,而浏览器也是一样的

    浏览器可以安全地下载各种网络资源,但是执行的时候就需要谨慎了。比如解析HTML、CSS、执行JS等操作,一不小心黑客就会利用这些操作对有漏洞的浏览器发起攻击

    所以需要在渲染进程和操作系统之间建一堵墙,有这堵墙在挡着,黑客能黑进来,也只能获取渲染进的操作权限(如下图),不会影响到外面,而这隔离操作系统和渲染进程的一堵墙就是安全沙箱

    安全沙箱最小的保护单位是进程,并且能限制进程对操作系统资源的访问和修改,这就意味着,安全沙箱所在的进程不能有读写操作系统的功能,比如读写本地文件、发起网络请求,调用GPU接口等

    安全沙箱怎么影响各个模块功能

    • 持久存储
      • 存储Cookie的读写,浏览器内核会维护一个存放所有Cookie的Cookie数据库,在渲染进程通过JS读取Cookie时,渲染进程会通过IPC将读取Cookie的信息发送给内核,浏览器内核读取Cookie之后再将内容通过IPC返回给渲染进程
      • 缓存文件的读写也是由浏览器内核实现
    • 网络访问:渲染进程不能直接访问网络,也需要通过浏览器内核,而浏览器内核在处理URL请求之前,会检查渲染进程有没有权限请求该URL,比如有没有跨域
    • 用户交互
      • 输入时:操作系统会将输入事件传给浏览器内核,内核判断如果是地址栏输入事件就直接在内核处理,如果是页面里的就转发给渲染进程
      • 渲染时:渲染进程渲染出位图后,需要将生成好的位图发送给浏览器内核,再由内核将位图复制到屏幕上显示

    站点隔离你知道吗

    我们知道一个标签页会有一个渲染进程,假如这个标签页里面有多个不同站点的 iframe 呢? 这就会导致多个不同站点的内容运行在同一个渲染进程中,这肯定不行

    所有操作系统中都存在两个A级漏洞:幽灵(Spectre)和熔毁(Meltdown),这是处理器架构导致的,很难修补

    如果银行页面中有一个恶意 iframe ,这个恶意站点利用两个A级漏洞入侵渲染进程,那恶意程序就可以读取银行站点渲染进程内所有内容了,这对用户来说风险就很大了,如果没有沙箱保护,甚至还可以对操作系统发起攻击

    所以后来Chrome对渲染进程进行重构,将标签级的渲染进程改成 iframe 级渲染进程,就是说一个标签页内可能运行多个渲染进程,并且相互隔离,这样恶意 iframe 就无法访问页面中其他的内容了,也就无法攻击其他站点了,这就是站点隔离

    中间人攻击

    在 http 数据提交给 TCP 层之后,会经过用户电脑、路由器、运营商、服务器,这中间每一个环节,都不是安全的

    一句话就是:在 http 传输过程中容易被中间人窃取、伪造、篡改,这种攻击方式称为中间人攻击

    那怎么让数据可以更安全的传输呢?

    就是使用 https ,利用 https 安全层对数据进行加解密操作,以保证数据安全。

    关于 https性能优化、版本、优缺点、SSL/TLS、握手(RSA、TLS1.2、TLS1.3)三个版本及优化等等,文章太长这里就不展开了,可以看我另一篇文章有详细介绍

    那么 https 是如何对数据加解密的呢?这要先说一下它的算法

    对称加密算法

    就是加密和解密使用同一个密钥。如AES、DES。加解密过程:

    1. 浏览器给服务器并发送一个随机数client-random加密套件(一个支持的加密方法列表)
    2. 服务器生成给浏览器返回另一个随机数server-random加密套件
    3. 两边分别返回确认消息。然后两者用加密方法将两个随机数混合生成密钥,这就是通信双上加解密的密钥

    有了密钥之后就可以对数据进行加密传输了

    问题是client-randomserver-random都是明文的,双方如何安全的传递两个随机数和加密方法呢?直接传给客户端,那过程中就很可能被窃取,中间人还是能解密拿到数据,往下看

    不对称加密算法

    就是一对密钥,有公钥(public key)和私钥(private key),其中一个密钥加密后的数据,只能用另一个密钥进行解密。如RSAECDHE。加解密过程:

    1. 浏览器给服务器发送加密套件
    2. 服务器选好支持的加密方法公钥(明文) 传给浏览器
    3. 两边分别返回确认消息。然后浏览器用公钥对数据进行加密,这个密钥只能用私钥解密

    这是不是看上去很完美了

    其实还存在很严重的问题

    1. 使用公钥反推出私钥是非常困难,但不是做不到,随着计算机运算能力提高,非对称密钥至少要2048位才能保证安全性,这就导致加解密速度慢,效率太低
    2. 无法保证服务器发送给浏览器的数据安全。因为浏览器可以用公钥来加密,而浏览器就只能用私钥加密,公钥是明文传输的,中间人可以获取到,这样服务器端的数据安全就得不到保证了

    所以!

    混合加密

    TLS实际用的是两种算法的混合加密通过 非对称加密算法 交换 对称加密算法 的密钥,交换完成后,再使用对称加密进行加解密传输数据。这样就保证了会话的机密性。过程如下

    1. 浏览器给服务器发送一个随机数client-random对称和非对称加密套件
    2. 服务器把另一个随机数server-random加密套件公钥传给浏览器
    3. 浏览器又生成另一个随机数pre-random,并用公钥对 pre-random 加密后传给服务器
    4. 服务器再用私钥解密,得到pre-random,并返回确认消息
    5. 这样浏览器和服务器都有三个随机数了,然后各自将三个随机数用加密方法混合生成最终的对称密钥

    然后开始数据加密传输

    这样即便被截持,中间人没有私钥就拿不到pre-random,就无法生成最终密钥

    这样就安全了吗?

    emmmm......还没

    因为问题又来了,如果一开始DNS就被中间人劫持,那么请求被中间人截获,中间人把他自己的服务器公钥给了浏览器,浏览器收到公钥就把信息发给中间人了,中间人解密拿到数据,并干了一些见不得人的勾当之后,再请求实际服务器,拿到服务器公钥,再把加密处理过后的数据发给服务器

    这样不知不觉间信息就被人窃取了,所以在结合对称和非对称加密的基础上,还需要服务器向浏览器证明身份,那怎么证明呢?

    所以数字证书来了,往下看

    如何保证数据是否被篡改?

    数字证书(数字签名)

    它可以帮我们验证服务器身份,而且数字证书里包含了公钥,而数字证书需要向有权威的认证机构(CA)获取授权给服务器。

    相比之前就变成了

    • 服务器不直接返回公钥给浏览器,而是返回数字证书,而公钥就在数字证书中
    • 浏览器这边多了一步证书验证,验证成功才能继续后续流程

    那么如何申请数字证书呢?

    • 首先,服务器准备一套公钥私钥,私钥留着自己用
    • 服务器将公钥和站点等信息提交给CA认证,这个是要钱
    • CA验证服务器提供的信息
    • 审核通过后签发认证的数字证书,包含了公钥CA信息有效时间证书序列等这些都是明文的,还有一个CA生成的签名

    CA的签名过程

    • CA也有一套公钥私钥
    • CA使用摘要算法计算服务器提交的明文信息并得出信息摘要
    • 然后CA再用它的私钥和特定的算法对信息摘要加密,生成签名
    • 签名服务器公钥等信息打包放入数字证书,并返回给服务器
    • 服务器配置好证书,以后浏览器连接服务器,都先把证书发给客户端验证

    摘要算法:主要用于保证信息的完整性。常见的MD5算法散列函数hash函数都属于这类算法,其特点就是单向性无法反推原文

    浏览器如何验证数字证书

    • 浏览器连接服务器,都先把证书发给客户端验证
    • 使用CA公钥和声明的签名算法对CA中的签名进行解密,得到服务器的摘要内容和服务器公钥
    • 再用摘要算法对证书里的服务器公钥生成摘要,再把这个摘要和上一步得到的摘要对比
    • 然后将两个信息摘要对比,如果是一致的,就说明证书是合法的,即证明了服务器自己,否则就是非法的

    证书认证又分为单向认证双向认证

    单向认证:服务器发送证书,客户端验证证书
    双向认证:服务器和客户端分别提供证书给对方,并互相验证对方的证书

    不过大多数https服务器都是单向认证,如果服务器需要验证客户端的身份,一般通过用户名、密码、手机验证码等之类的凭证来验证。只有更高级别的要求的系统,比如大额网银转账等,就会提供双向认证的场景,来确保对客户身份提供认证性

    另外在申请和使用证书的过程中,需要注意

    • 申请数字证书是不需要提供私钥的,要确保私钥永远只能由服务器掌握
    • 数字证书最核心的是CA使用它的私钥生成的数字签名
    • 内置CA对应的证书称为根证书,根证书是最权威的机构,它们自己为自己签名,这称为自签名证书

    有了这些之后就安全了吗?

    emmmmm.....没有

    虽然不是绝对安全,但是现行架构下最安全的解决文案了,大大增加了中间人的攻击成本

    结语

    点赞支持、手留余香、与有荣焉

    参考

    浏览器工作原理与实践

    HTTPS:网络安全攻坚战

    相关文章

      网友评论

          本文标题:吃透浏览器安全(同源限制/XSS/CSRF/中间人攻击)

          本文链接:https://www.haomeiwen.com/subject/inppnltx.html