网络安全 | 关于XSS攻击、CSRF攻击、中间人攻击...

359 阅读12分钟

网络安全

什么是CSRF

CSRF(Cross-site request forgey)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中向被攻击者网站发送跨站请求。利用受害者在攻击网站已经获取的注册凭证,绕过后台用户验证,达到冒充用户对被攻击的网站执行某种操作的目的。

一个典型的CSRF攻击过程

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

CSRF的特点

  • 攻击发生在第三方网站,被攻击网站无法阻止攻击发生
  • 攻击利用受害者在被攻击网站的登录凭证(整个过程没有获取到受害者的登录凭证,,只是冒用)
  • 跨站请求各种方式:图片URL、超链接、CORS、Form提交等等

防护策略

  • 阻止不明外域的访问

    • 同源检测,CSRF大多来自第三方网站,我们直接禁止外域对我们发起请求 如何判断请求是否来自外域? 在HTTP协议中,每一个异步请求都会携带两个Header,用于标记来源域名:

      • Origin Header 对应请求头Origin字段,标识请求来源地址 。请求来源不包含path和query

        • 不存在Origin 字段的情况:1. IE11同源策略:不会在跨站CORS上添加Origin字段,Referer头是唯一标识 2. 302重定向,因为Origin重定向可能被认为是其他来源的敏感信息,因此浏览器不想Origin泄露到新服务器上
      • Referer Header 对应请求头Referer字段 HTTP请求的来源地址。对于Ajax请求,图片和script等资源请求,Referer为发起请求的页面地址;对于页面跳转,Referer为打开页面历史记录的前一个页面地址。Referer是由浏览器提供的,可能不安全,攻击者可以隐藏、甚至修改自己请求的Referer Referer Policy草案:tech.meituan.com/2018/10/11/… 设置Referer Policy: 比如设置成same-origin ,对于同源的链接和引用,会发送Referer,referer 值为Host不带Path。如果是跨域访问,则不设置Referer 设置Referer

    • SameSite Cookie : 有两个属性StrictLax

    Samesite=Strict, 严格模式,表明这个Cookie在任何情况下都不可以作为第三方Cookie,绝无例外。 比如b.com设置了

      ```
        Set-Cookie:foo=1;Samesite=Strict
        Set-Cookie:bar=2;Samesite=Lax
        Set-Cookie:baz=3
        ```
    

    我们在a.com下发送对b.com的任意请求,foo这个cookie都不会被包含在cookie请求头中,但bar会 。

    Samesite=Lax, 宽松模式,比Strict放宽一点限制:加入这个请求(会改变了当前页面或打 开了新页面),且同时是GET请求,则这个Cookie可以作为第三方请求。 同样:

    Set-Cookie:foo=1;Samesite=Strict
    Set-Cookie:bar=2;Samesite=Lax
    Set-Cookie:baz=3
    

如果a.com网站是点击链接(GET请求)foo不会包含在Cookie请求头中,但是barbaz会 如果a.com网站发起对b.com的异步请求,或者页面跳转是通过表单POST提交的,bar不会发送.

提交时要求附加本域才能获取的信息

  • CSRF Token:CSRF产生的原因之一是服务器误把攻击者的请求当成了用户的请求,那我们可以要求所有的用户请求都携带一个CSRF攻击者无法获取到的Token。服务器通过校验请求是否携带正确的Token,来把正常的请求和攻击的请求分开

    • 原理:三个步骤

      • 将CSRF Token输出到页面中。服务器需要给这个用户生成一个Token,该Token通过加密算法对数据进行加密,一般Token都包括随机字符串和时间戳的组合,Token就不能放Cookie中,最好存在服务器的Session中,之后每次页面加载时,用JS遍历整个DOM树,对所有的aform标签加入Token(对于页面加载后动态生成的HTML代码),需要我们手动加入
      • 页面提交的请求携带这个Token。GET请求可以拼接到URL后面,POST请求可以设置一个<input type="hidden" name="csrftoken" value="token">标签 3.服务器验证Token是否正确。服务器对Token进行解密,对比加密字符串以及时间戳,如果加密字符串一致且时间未过期,token有效。

分布式校验token 在大型网站中,使用session存储CSRF Token会带来很大的压力(session默认存储在单及服务器内存中),在分布式环境下同一个用户发送的多次HTTP请求可能会先后落在不同的服务器上,导致后面发起的HTTP请求无法拿到之前HTTP请求存储在服务器中的Session数据,使得session机制在分布式环境下失效,因此分布式集群中CSRF Token需要存储在Redis之类的公共存储空间 使用Session存储,读取和验证CSRF Token会引起比较大的复杂度和性能问题,目前很多网站采用Encryptyed Token Pattern方式。这种方法的Token是一个计算出来的结果,而非随机生成的字符串.这样在校验时无需再去读取存储的Token,只用再计算一次即可。 Token值通常使用UserID、时间戳和随机数,通过加密的方法生成

  • 双重Cookie验证 就是在提交前先用js读取用于验证的cookie值加入到提交字段,这样验证字段有两份,一份在cookie中,一份在POST或者URL中。那CSRF只能让请求中带有Cookie但是不能读取cookie加入到POST或URL中

优点:

-   无需使用session,适用卖弄更广,易于实施
-   Tokens存储于客户端中,不会给服务器带来压力
-   相对于Token,实施成本低,可以在前后端设置统一拦截校验,无需一个个接口或一个个页面添加 缺点:
-   Cookie中添加了额外的字段
-   如果有XSS攻击,供给者可以注入Cookie
-   难以做到子域名的隔离
-   Cookie传输安全,采用这种防御方式最好确保用到整个HTTPS的方式

XXS攻击

Cross-Site Scripting(跨站脚本攻击,简称XSS),是一种恶意代码注入攻击。供给者通过在目标网站注入恶意脚本,使之在用户浏览器上运行。利用这些恶意脚本,供给者可获取用户的敏感信息,如Cookie、SessionId等,进而危害数据安全。

XSS本质上就是 恶意代码未经过滤,与网站正常代码混在一起;浏览器无法辨别哪些脚本是可信的,导致恶意脚本运行,其来源:

  • 来自用户的UGC信息
  • 来自第三方的链接
  • URL参数
  • POST参数
  • Referer (可能来自不可信来源)
  • Cookie(可能来自其他子域注入)

XSS的分类

三种:存储型、反射型和DON型

存储型XSS攻击步骤:

  1. 攻击者将恶意代码提交到目标网站的数据库
  1. 用户打开目标网站时,网站服务端 将 恶意代码从数据库取出,拼接在HTML中返回给浏览器
  1. 用户浏览器接受到响应后解析执行,混在 其中 的恶意代码 也被执行
  1. 恶意代码窃取用户数据发送到 攻击者的网站 ,或者冒充用户行为,调用目标网站接口执行 攻击者执行操作 这种攻击常见于 带有用户保存数据的网站功能,如 论坛 、商品评论 、 用户私信等

反射型XSS攻击步骤

  1. 攻击者构造出 特殊的URL,其中包括恶意代码
  1. 用户访问恶意代码URL时 ,网站服务将 恶意代码从URL中取出,拼接在HTML中返回浏览器
  1. 用户浏览器接收到响应后执行, 混在其中的恶意代码也被执行
  1. 恶意代码窃取用户数据发送到 攻击者的网站 ,或者冒充用户行为,调用目标网站接口执行 攻击者执行操作常见于通过URL传递参数的功能,如网站搜索、跳转等 与存储型XSS的区别:存储型XSS的恶意代码存在数据库里,反射型XSS的恶意代码存在URL里

DOM型XSS的攻击步骤:

  1. 攻击者构造出 特殊的URL , 其中包含恶意代码
  1. 用户打开带有恶意代码的URL
  1. 用户浏览器 接收到响应后解析执行 , 前端js取出URL中的恶意代码并执行
  1. 恶意代码窃取用户数据发送到 攻击者的网站 ,或者冒充用户行为,调用目标网站接口执行 攻击者执行操作

DOM型与前两种的区别:DOM型XSS攻击中,取出和执行恶意代码由浏览器完成,属于前端JS自身的安全漏洞,其他两种XSS都属于服务端的安全漏洞

预防XSS攻击

  • 预防存储型XSS和反射型XSS攻击 存储型和反射型XSS都是服务端取出恶意代码后,插入到响应端HTML里,攻击者编写的 “ 数据” 被内嵌到“代码”中,被浏览器所执行。 预防:

    • 改成纯前端渲染,把代码和数据分隔开来 纯前端渲染的过程:

      • 浏览器加载一个HTML页面,该页面不包含任何数据
      • 然后浏览器执行HTML中的js
      • js通过Ajax加载业务数据,调用DOM API更新到页面上 纯前端渲染可 识别哪些是文本.innerText 哪些是.setAttribute属性,哪些是.style样式等。但是需要避免DOM型XSS漏洞( onLoad事件href中的javascript:等)
    • HTML 做充分的转义,可以使用合适的转义库ejs

  • 预防DOM型XSS攻击

    • 使用.innerHTMLouterHTMLdocument.write()时需要小心,不要把不可信的数据作为HTML插入到页面,而应尽量使用.textContentsetAttribute()
    • 使用Vue/React技术栈,并且不使用v-html/dangerouslySetInnerHTML,就在前端render阶段避免使用innerHTMLouterHTML的XSS隐患
    • DOM中的内联事件监听器,如locationonclickonerroronloadonmouseover等,<a>标签的href属性,js的eval()setTimeout()setTimeout等,都能把字符串作为代码运行。如果把不可信的数据拼接到字符串中传递给这些API,很容易产生安全隐患。

JSONP可能产生的安全隐患

可能存在CSRF攻击

当某个网站通过JSONP的方式来传递用户敏感信息时,攻击者构造恶意的JSONP调用页面,诱导被攻击者访问来达到截取用户敏感信息的目的。

如下攻击代码:

<script>
function Hack(){
    alert(v.username)
}
</script>
<script src="http://js.login.cn/?o=ss0&m=info&func=Hack"></script>

当被攻击者在登陆js网站的情况下访问了该网页时,那么用户的隐私数据(如用户名,邮箱等)可能被攻击者劫持。

解决方案:Referer过滤

可能存在XSS攻击

使用Content-Type:application/javascript造成HTML根据js解析文件,造成XSS

解决方案:严格使用Content-Type: application/json

详细内容见原文...

HTTPS中间人攻击

中间人攻击:即(Main-in-the-middle attack|MITM) ,就是中间人会在消息发出方和接收方之间拦截双方通讯,并进行信息篡改

常见的HTTPS中间人攻击,首先需要结合ARP(IP地址->Mac地址)、DNS欺骗技术进行拦截。

  1. SSL证书欺骗攻击

通过ARP欺骗、DNS劫持甚至网关劫持等,将客户端的访问重定向到攻击者的机器,让客户端机器与攻击者机器建立HTTPS(使用伪造证书), 而攻击者再跟服务器建立连接。 虽然用户在浏览器看到的链接是相同域名的网站,但浏览器会提示证书不可信, 用户不点击继续浏览就能避免被劫持。

  1. SSL剥离攻击(SSLStrip)

SSL剥离,即将HTTPS连接降级到HTTP连接。该方式主要是利用用户并不会每次都直接输入https://xxx.xxx.com来访问网站,或则有些网站并非全网HTTPS,而是只是在需要进行敏感数据传输时才使用HTTPS,中间人通过劫持了客户端与服务端的HTTP会话后,将HTTP页面所有的https://超链接都换成http://``用户在点击链接时,使用HTTP协议进行访问。所以攻击者可以伪造响应数据发送给客户端。服务端在配置HTTPS服务时,加上HTTP Strict Transport Security`配置项

  1. 针对SSL算法进行攻击 OpenSSL漏洞

防范措施:

  • 不要随意连入公共场所的WIFI,或者使用未知代理服务器

  • 不要安装不可信或突然出现的描述文件,信任伪造的证书

  • 客户端对服务器进行单独对比校验,确认证书不是伪造的。

SYN攻击是什么?

是一种典型的DOS/DDOS攻击

服务端的资源分配是在第二次握手是分配的,而客户端的资源是在完成第三次报文握手时分配的,所以服务器容易收到SYN攻击。SYN攻击就是**Client在短时间内伪造大量不存在的IP地址**,并向服务器不断的发送SYN包,并等客户端回应。但由于源地址不存在,服务器不断的重发超时,这些伪SYN包长时间的占用未连接队列,导致正常的SYN请求因为队列满而被抛弃,从而引起网络拥塞甚至系统瘫痪。

如何检验?当你在服务器上看到大量半连接状态时+IP地址随机,基本上可以断定是SYN攻击。Linux/Uinx上可以使用netstat -n -p TCP | grep SYN_RECV进行检测

常见防御SYN攻击的方法:

  • 缩短超时(SYN Timeout)时间
  • 增加最大半连接数
  • 过滤网防护

内容来源:

  1. CSRF...
  2. XSS...
  3. JSONP...