什么是 XSS 和 CSRF 攻击
💫

什么是 XSS 和 CSRF 攻击

👉
常见攻击类型,要理解而不是死记硬背

CSRF 跨站请求伪造

cross-site request forgery

什么是跨站请求伪造

是一个挟制用户在当前已登录的web应用程序中进行非本意操作的攻击方法。
notion image

常见的CSRF攻击类型

  1. GET 类型的 CSRF
通常会用 img ,当用户访问到这个图片时,会发送 get 请求
<img src="http://bank.example/withdraw?amount=10000&for=hacker" />
  1. POST 类型
一般是提交表单类
<form action="http://bank.example/withdraw" method=POST>
    <input type="hidden" name="account" value="xiaoming" />
    <input type="hidden" name="amount" value="10000" />
    <input type="hidden" name="for" value="hacker" />
</form>
<script> document.forms[0].submit(); </script>
  1. 链接类型
点击就会中招
<a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank">
  重磅消息!!
<a/>

防御方式

  1. 强验证
一般是涉及钱等重要信息时,需要进行二次验证,如需再输入验证码成功后再发起最后的请求,但是用户体验很差
  1. Referer check
这种方式成本最低,HTTP中有个Referer字段,来表明请求来源的地址。正常的情况下,Referer的值应当和请求的地址来自同一个域名下,因此可以用这个字段来判断请求来源。但是也有问题,1. 低版本的IE浏览器并不支持,并且也可能伪造;2. 如果是从本域发送的伪造请求这个方法就不行了。
  1. SameSite cookie
Chrome 浏览器在51版本后,浏览器的 Cookie 新增了一个 SameSite 属性。SameSite 有三个值:Strict、Lax、None
  • Strict:最严格模式,完全禁止第三方Cookie,跨站点访问时,任何情况下都不会发送Cookie。换言之,只有当前网页的 URL与请求目标一致,才会带上Cookie。
此方式虽然安全,但是存在严重的易用性问题,用户从第三方页面访问一个已登录的系统时,由于未携带Cookie,总是需要重新登录。
  • Lax:Chrome默认模式,对于从第三方站点以 link标签,a标签,GET 形式的 Form 提交这三种方式访问目标系统时,会带上目标系统的Cookie,对于其他方式,如 POST形式的Form提交、AJAX形式的GET、img的src访问目标系统时,不到Cookie。
  • None:原始方式,任何情况都提交目标系统的Cookie。
由于是 Google 提出的,目前兼容性存在问题
  1. 双重 Cookie 验证
双重Cookie验证的原理是在Cookie中保存Token值,同时在Form表单中也提供该值,请求提交时,Cookie和Form表单中的Token同时提交,服务器端只需要对请求中的两个参数进行校验即可,省去了在服务器端维护Token的步骤。
由于Cookie的安全限制,只能在本域名或子域名下访问到Cookie值,兄弟子域名无法访问到,如a.bank.com 域名下的 Cookie,只能被 a.bank.comsub.a.bank.com 访问,无法被 b.bank.com 访问。对于分布式应用,可能需要在多个子域名中提交请求,所以一般需要把Cookie保存在根域名bank.com 中。不过此方式存在安全风险,如果任何一个子域下的页面存在XSS攻击,可导致根域名下的Cookie被篡改,Token可被攻击者任意修改,导致安全措施失效。
 

XSS 跨站脚本攻击

cross-site script

什么是XSS

通常是指攻击者通过 HTML注入 的方式,插入了恶意的脚本,当用户浏览网页时,会进行恶意控制或者获取用户的敏感信息

XSS 可以做的事情

  1. 可以窃取 cookie 信息
恶意的 JavaScript 脚本可以通过 document.cookie 获取到 cookie 信息。拿到用户信息后会进行CSRF 攻击
  1. 可以监听用户行为
添加 addEventListener 事件来监听键盘事件
  1. 添加恶意 DOM 伪造假的登录窗口,用来欺骗用户输入用户名密码等敏感信息
  1. 生成浮动窗口广告,影响用户体验

XSS 的攻击方式

  1. 反射型
恶意脚本作为网络请求的一部分
例:我们通过页面的url的一个参数来控制页面的展示内容,比如我们把上面的一部分代码改成下面这样
app.use(async ctx => {
    // ctx.body 即服务端响应的数据
    ctx.body = ctx.query.userName;
})
通过这个操作,我们会发现用户将一段含有恶意代码的请求提交给服务器,服务器在接收到请求时,又将恶意代码反射给浏览器端,这就是反射型XSS攻击
  1. 存储型
存储型会把用户输入的数据“存储”在服务器
例:攻击者在社区或论坛写下一篇包含恶意 JavaScript代码的博客文章或评论,文章或评论发表后,所有访问该博客文章或评论的用户,都会在他们的浏览器中执行这段恶意的JavaScript代码
  1. 基于DOM
通过恶意脚本修改页面的DOM节点,是发生在前端的攻击
例:
<body>
    <div class="login-wrap">
        <input type="text" placeholder="输入url" class="url">
        <br>
        <br>
        <button class="btn">提交</button>
        <div class="content"></div>
    </div>
</body>
<script>
    var btn = document.querySelector('.btn');
    var content = document.querySelector('.content');
    
    btn.onclick = function () {
        var url = document.querySelector('.url').value;
        content.innerHTML = `<a href=${url}>跳转到输入的url</a>`
    }
</script>

防御 XSS

  1. HttpOnly
设置为 HttpOnly 后,是不能通过 document.cookie 获取到 cookie
  1. 输入和输出的检查
永远不要相信用户的输入
输入检查一般是检查用户输入的数据是都包含一些特殊字符,如 < > ' " 等。如果发现特殊字符,则将这些字符过滤或编码。这种可以称为 XSS Filter
  1. 代码转义
    1. JavaScript 输出到 HTML 页面,相当于一次 XSS 输出的过程,需要根据不同场景进行不同的编码处理
    2. 变量输出到 <script>,执行一次 JavascriptEncode
    3. 通过 JS 输出到 HTML 页面
      1. 输出事件或者脚本,做 JavascriptEncode 处理
      2. 输出 HTML 内容或者属性,做 HtmlEncode 处理
  1. 利用CSP
CSP (Content Security Policy) 即内容安全策略,是一种可信白名单机制,可以在服务端配置浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截是由浏览器自己实现的。我们可以通过这种方式来尽量减少 XSS 攻击。
通常可以通过两种方式来开启 CSP
  • 设置 HTTP Header 的 Content-Security-Policy
Content-Security-Policy: default-src 'self'; // 只允许加载本站资源
Content-Security-Policy: img-src https://*  // 只允许加载 HTTPS 协议图片
Content-Security-Policy: child-src 'none'    // 允许加载任何来源框架
  • 设置 meta 标签的方式
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">