如何识别和预防跨站请求伪造攻击

发表于:2018-1-18 09:48

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:陈峻编译    来源:51CTO

  在您浏览某个网站时,该网站经常会以您的名义向另一个网站请求各种数据。例如,在大多数情况下,某个网站上所显示的视频一般不会存储在网站本地。而该视频之所以可以出现在该网站上,是因为它实际上是从诸如youtube.com之类的视频流媒体网站嵌入过来的。
  这就是所谓的内容分发网络(CDN),它能用于更快速度地交付各种内容与作业。通常许多网站都会将脚本、图像和其他带宽密集型的资源存放在CDN上,因此当您浏览图像和脚本文件时,它们会从最近的CDN资源进行下载,而并非来自网站本身。
  虽然上述方法对于用户良好的浏览体验是必需的,但是它们也可能会成为各种安全问题的源头。因为您正在浏览的网站能够通过请求浏览器,在未经您同意的情况下从另一个网站上获取数据。而如果此类的请求并未正确处理的话,攻击者就可以发动跨站请求伪造攻击。
  跨站请求的危害
  当一个网站以您的名义向另一个网站请求数据时,只要请求无需认证,例如并未发送会话cookie,那么就不存在安全问题。然而当用户的会话cookie连同请求一并被发送时,攻击者就能发动跨站请求伪造攻击,进而滥用受攻击浏览器与Web服务器之间的信任关系。
  在本文中,我们将重点讨论浏览器行为所引发的危险,以及攻击者是如何利用这个“优势”,来发动跨站请求伪造攻击的。为了理解跨站请求伪造的工作原理,让我们首先对HTTP请求和cookies做一个简单的介绍。
  一、HTTP请求和Web Cookies的简要介绍
  1.HTTP的GET和POST请求
  HTTP GET请求
  HTTP GET请求是您对一个Web服务器数据的请求。例如,当您在Web浏览器中输入网址(URL)时,就是指示浏览器发送一个HTTP GET请求到该网站所对应的Web服务器上。相应地,该Web服务器也会发送响应回到浏览器端。
  HTTP POST请求
  HTTP POST请求是指您发送那些要在Web应用中发布的数据。例如:当您提交Web表单时,如果这是一个登录或交互的表单,那么您的浏览器就会产生一个HTTP POST请求。该HTTP POST请求包含着您通过Web表单所提交的数据。
  2.自动生成HTTP GET和POST请求
  有时候GET和POST请求能通过某些HTML标签,或者一段JavaScript代码来自动触发。因此,它们并非总是需要与用户交互的。例如:在src属性中被声明为图像链接的<img>标签,就会自动生成一个GET请求。另一个例子则是XHR POST请求,它在用户输入查询时,被用于自动获取各种下拉式的搜索提示。
  3.网站与会话Cookie
  一般网站使用cookies来识别用户,或是在网站上保留用户的登录会话。会话cookie通常包含着唯一的ID,Web应用程序将用它作为标识号,以判定那些已经完成登录了的特殊用户。因此,当一个cookie被设置用于某个特定网站时,浏览器就会将它连同每一个发往该网站的HTTP请求,都保留在已登录的会话中。然而,这并非只关乎到会话cookie本身的问题。通过使用CSRF,就算Web服务器能够根据IP地址予以识别,攻击者仍然能够以用户的身份,使用NTLM或Basic Auth的认证方式来发送各种请求。
  二、跨站请求伪造的工作原理
  由于跨站点请求不需要您的批准,攻击者就可以滥用它,并且在未经您的同意和知晓的情况下,发送各种请求。下面是一个典型场景,让我们看看这个问题是如果被暴露出来的。
  Web表单的简介
 
  我们来试想一个能够允许您去修改电子邮件地址的网站。您所要做的就是:在您登录之后,将您新的地址写入上述的字段,并点击“更改”。而如果您还没有登录,也就是说,在您并没有会话cookie的时候,该表单是不会工作的。下面让我们来看看底层的HTML代码是如何让这个输入字段工作的:
  <body>  
  <p>Your new email address</p>  
  <form method = "POST" action = "mail.php">  
  <input type = "text" name = "email" placeholder = "Change your email address">  
  <button type = "submit">change</button>  
  </form>  
  </body> 
  在上述Web表单代码中,有三个重要的HTML属性:method、action和name。
  Method属性
  HTML的method属性是用来指定要用到的HTTP动作,并且在默认情况下,就是GET。当使用GET时,所有的参数值会被作为URL请求的一部分发送出去,因此在浏览器地址栏上,它们会在问号字符之后显示出来,如下所示:
  https://www.example.com/mail.php?email=alice@example.com
  这些请求会被记录到Web服务器的日志文件,以及浏览器的历史记录中。因此,GET动作只能用于传输一些非敏感的信息,以及不做任何数据修改的操作(包括:插入、更新、删除等)。比如:表示您正在浏览的当前页面:?page=home。
  HTTP的POST动作经常被用在各种典型的Web表单里,因为它将数据作为请求的主体进行发送。因此,在服务器日志或浏览器历史记录中并无发送数据的记录。这就很适合于传输诸如密码这类的敏感和大量的数据。
  Action属性
  HTML的第二个属性是action,它指定了请求的目标。目标可以是网站内部或外部、甚至是在另一个域中的页面。在上面的代码示例中,该值为mail.php,这是一个PHP脚本,可让您改变电子邮件地址的名称。
  Name属性
  name属性是在Web表单的输入域中。它所包含的参数名称被用来存放您所提交的数据。因此,如果您输入alice@example.com,并点击提交按钮。那么mail的参数值将被设置为alice@example.com,同时Web服务器将收到如下的参数映射值:
  mail=alice@example.com
  HTTP POST请求
  一旦您提交了该表单,浏览器就会发送下面的HTTP请求:
  POST /email.php HTTP/1.1mail=alice@example.com  
  Host: example.com  
  Cookie: SESSION=e29a31e41c9512a4bd  
  Content-Type: application/x-www-form-urlencoded  
  mail=alice@example.com 
  如您所见,Host的HTTP头里包含了从表单提交过来的网站主机名。另外它还包括了会话cookie,Web应用可以籍此来确定您是否已经登录过。
  三、在Web表单中的跨站请求伪造攻击
  创建一个Web表单的副本
  上面所涉及的知识会很容易让人联想到:攻击者将您的邮件地址更改成任何他想要的信息。他可以去复制Web表单,并放置到自己的Web服务器上,例如:http://www.attacker.com/evil.php。下面就是新表单的示例:
  <form id = "csrf_form" method = "POST" action = "http://example.com/email.php">  
  <input type = "text" name = "mail" value = "bob@attacker.com">  
  <form>  
  <script>  
  document.getElementById('csrf_form').submit();  
  </script> 
  从上述代码您也许能注意到:该表单并没有提交按钮,因此攻击者可以在未经您同意或知晓的情况下触发该Web表单。此处应该有的按钮被替换成了一行JavaScript,如下所示:
  document.getElementById('csrf_form').submit();
  这段JavaScript代码先选取表单里的元素,然后以JavaScript的形式进行提交。随着提交的发生,受害者的电子邮件地址随即被更改成了bob@example.com,而在上述代码中属性值正是这个值。
  攻击者的HTTP请求
  以下是由此类攻击所产生的HTTP POST请求。为了便于阅读,我们在此删掉了那些不相关的请求头部信息:
  POST /email.php HTTP/1.1  
  Host: example.com  
  Origin: http://attacker.com  
  Referer: http://attacker.com/csrf.html  
  Cookie: SESSION=e29a31e41c9512a4bd  
  Content-Type: application/x-www-form-urlencoded  
  mail=bob@example.com 
  下面我们列出攻击者所伪造的HTTP POST请求中的明细:
  浏览器发送一个POST请求。
  我们例子中的example.com是用户所登录到的一个脆弱的站点。请注意它的referrer和origin都表明请求是来自attacker.com。
  Cookies的头部信息包含了用户的会话cookie。尽管浏览器请求是被恶意脚本所触发的,但浏览器仍然会将这个Cookie头部连同请求一同发送。由于该请求指向的是example.com,而用户正好具有该网站的会话cookie。这也意味着,Web应用程序会去识别会话里的用户登录状态。
  Cookie头部的下面一行是Content-Type类型的HTTP,它表明该请求是由一个表单所发出的。
  整个post的底部最后一行是参数映射值。此处参数为mail,其值便是攻击者的邮箱地址:bob@attacker.com。
  四、用CSRF攻击来诱骗受害者
  攻击者是如何使用CSRF攻击来诱骗受害者的呢?让我们假设攻击者将该表单发布到了https://attacker.com/csrf.html。为了诱骗用户浏览到的这个URL,他通常会通过电子邮件的形式去诱骗受害者访问该URL。
  因此,一旦受害者访问了https://attacker.com/csrf.html,该表单的提交就会被触发。而那个脆弱的https://example.com网站随即会接受到该请求。由于其Web应用程序根据会话cookie,判定是由受害者亲自提交而来,因此它将邮件地址更改为bob@attacker.com。
  接下来,攻击者所需要做的就是发送一封带有“密码重置”功能的电子邮件了。由于电子邮件已经被改成了bob@attacker.com,因此Bob会收到该邮件,并且能够轻而易举地改变Alice的密码了。至此,Bob完全接管了她的帐号,甚至会把她锁在了“门外”。
  向受害者隐藏CSRF攻击
  为了不使受害者注意到已经遭受了CSRF攻击,攻击者一般会创建另一个称为info.html的网页,来包含一些受害者感兴趣的主题信息。同时,该网页会包含一个指向https://attacker.com/csrf.html的隐藏iframe。一旦受害者访问到了info.html,在csrf.html上的表单就会在受害者不可见的情况下自动触发。
  可见,攻击者通常使用CSRF攻击来更改密码或表单上的电子邮件,从而劫持受害者的??帐户,或是在Web应用上创建一个新的管理员帐号。
  五、预防跨站请求伪造攻击
  攻击者只有在获知到表单里使用了哪些参数和值的组合时,才能发动CSRF攻击。因此,如果增加一个对于攻击者来说是未知的参数值,并且能够通过服务器端进行验证,那么您就可以防止受到CSRF的攻击。下面我们为您罗列了一些可以用来预防跨站请求伪造攻击的方法。
  使用反CSRF的令牌
  这是一个只能被用户端的浏览器和Web应用程序所知悉的一个随机字符串。它通常被存储在一个会话的变量中。而且,它通常被放在在网页的一个隐藏表单的字段内,连同请求一起被发送出去。
  如果会话的变量值和隐藏的表单字段相匹配的话,Web应用程序就会接受该请求。而如果它们不匹配,则该请求会被Web应用所丢弃。由于在这种情况下,攻击者并不知道可用于接受请求的那个被隐藏表单的精确值,也就无法发动CSRF攻击了。
  在cookies中使用相同的站点标志
  相同的站点标志(https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/)是一个比较新的,可用来预防CSRF攻击的方法。在上述场景中,https://attacker.com/将带有会话cookie的POST请求发往https://example.com/。该会话cookie对于每一个用户都是唯一的,而Web应用程序可以用它来区分不同的用户,并确定您是否已经登录过。
  如果给会话cookie标记上“相同站点的cookie”特征,将它与那些仅来自同一个域的请求一起发送出去。那么,当https://example.com/index.php向https://example.com/post_comment.php发送POST请求时,它就会被允许。而由于https://attacker.com/是在另一个不同的域,它无法将会话cookie连同请求一起发送出去,因此也就不能向https://example.com/post_comment.php产生POST请求了。
  最后我们罗列出漏洞分类和严重性的对应表,供您参考。

上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号