Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null value in exported file #66

Closed
michaellewis259 opened this issue Feb 7, 2020 · 19 comments
Closed

Null value in exported file #66

michaellewis259 opened this issue Feb 7, 2020 · 19 comments

Comments

@michaellewis259
Copy link

I'm having issues with exporting the trace. It doesn't matter if I mask/exclude values or not, the resulting file shows as null. This is happening in both Firefox and Chrome, which leads me to believe there is something I need to allow with one of my security tools, but nothing is showing up in their various consoles. Do you have any ideas as to what is going on?

@khlr
Copy link
Contributor

khlr commented Feb 10, 2020

Hi Michael!

Unfortunately I cannot reproduce this behaviour.
Could you please launch the dev tools (F12) within the extension window and see if it outputs some stacktrace or something similar at the console-tab?

grafik

@michaellewis259
Copy link
Author

I'm showing a few errors:

image

debug from the first JS error:
`/**

  • Some functionality to support the import/export
  • for SAML-tracer
  • Added to SAML-tracer by M. Dobrinic
  • 2011-dec
    **/

// export SAMLTrace namespace to make ao. Request definitions available
var EXPORTED_SYMBOLS = ["SAMLTraceIO"];

// Put functionality in out own namespace
if ("undefined" == typeof(SAMLTraceIO)) {
var SAMLTraceIO = {};
};

SAMLTraceIO = function() {
};

SAMLTraceIO.prototype = {
/**

  • Main feature: Exports and optionally filters traced requests.
    **/
    'exportRequests': function(reqs, cookieProfile) {
    // Perform request filtering based on user input from dialog:
    var ef = new SAMLTraceIO.ExportFilter(cookieProfile);
    var filteredreqs = ef.perform(reqs);
// Package results
var result = {
  requests: filteredreqs,
  timestamp: new Date().toISOString()
};
return result;

},

'serialize': function(exportResult) {
let indentSpaces = 2;
return JSON.stringify(exportResult, null, indentSpaces);
},

'getOutputFile': function(exportResult) {
let timeStamp = exportResult && exportResult.timestamp ? exportResult.timestamp : "no-timestamp";
return SAML-tracer-export-${timeStamp}.json;
},

/**

  • Imports requests and restores them in the TraceWindow.
    **/
    'importRequests': function(selectedFile, tracer, onSuccess, onError) {
    const parseRequests = rawResult => {
    try {
    let exportedSession = JSON.parse(rawResult);
    let successfullyRestored = this.restoreFromImport(exportedSession.requests, tracer, onError);
    if (successfullyRestored) {
    onSuccess();
    }
    } catch (error) {
    console.log("An error occured while trying to parse and import requests: " + error);
    if (error instanceof SyntaxError) {
    onError("The selected file doesn't seem to contain importable traces!");
    } else if (error instanceof TypeError) {
    onError("The selected file seems to be invalid or corrupted!");
    } else {
    onError("Error while importing: " + error);
    }
    }
    };
let reader = new FileReader();
reader.onload = e => {
  parseRequests(e.target.result);
}
reader.readAsText(selectedFile);

},

'restoreFromImport' : function(importedRequests, tracer, onError) {
if (!importedRequests || importedRequests.length === 0) {
onError("There aren't any requests to import...");
return false;
}

// Since the relase of v1.0.0 every request's got a "requestId". If it ain't present, it's a legacy import.
let isLegacyImport = !importedRequests[0].hasOwnProperty("requestId");
console.log(`The imported requests are in ${isLegacyImport ? "legacy" : "current"}-style.`);

const getHeaders = importedHeaders => {
  if (isLegacyImport) {
    return importedHeaders.map(h => { return { name: h[0], value: h[1] } });
  } else {
    return importedHeaders;
  }
};

const getRequestId = importedRequest => {
  return isLegacyImport ? importedRequest.id : importedRequest.requestId;
};

const createRestoreableModel = importedRequest => {
  let pseudoRequest = {
    req: {
      method: importedRequest.method,
      url: importedRequest.url,
      requestId: getRequestId(importedRequest),
      requestBody: {
        post: importedRequest.post
      }
    },
    requestId: getRequestId(importedRequest),
    url: importedRequest.url,
    headers: getHeaders(importedRequest.requestHeaders),
    saml: importedRequest.saml,
    getResponse: () => {
      let pseudoResponse = {
        requestId: getRequestId(importedRequest),
        url: importedRequest.url,
        statusCode: importedRequest.responseStatus,
        statusLine: importedRequest.responseStatusText,
        responseHeaders: getHeaders(importedRequest.responseHeaders)
      };
      return pseudoResponse;
    }
  };
  return pseudoRequest;
};

let restoreableRequests = importedRequests.map(ir => createRestoreableModel(ir));
restoreableRequests.forEach(rr => {
  tracer.saveNewRequest(rr);
  tracer.addRequestItem(rr, rr.getResponse);
  tracer.attachResponseToRequest(rr.getResponse());
});

return true;

}
};

/**

  • ExportFilter applies filtering of SAMLTrace.Request instances
  • based on provided profile
    **/
    SAMLTraceIO.ExportFilter = function(cookieProfile) {
    this.exportFilters = [];
    this.loadPreferences(cookieProfile);
    };

SAMLTraceIO.ExportFilter.prototype = {
'loadPreferences' : function(cookieProfile) {
this.exportFilters = [];

switch (cookieProfile) {
  case '1' :	// No cookiefiltering or filtering whatsoever
    break;

  case '2' :	// Apply hash filters
    this.exportFilters.push(
      SAMLTraceIO_filters.hashValueFilter('post', '*'),                          // hash *all* the post elements
      SAMLTraceIO_filters.overwriteKeyValue('postData'),                         // overwrite the postData-variable
      SAMLTraceIO_filters.hashCookieValueFilter('requestHeaders', 'Cookie'),     // hash cookie values in request
      SAMLTraceIO_filters.hashCookieValueFilter('responseHeaders', 'Set-Cookie') // ..as well as in response
    );
    break;

  case '3' :	// Apply obfuscate/overwrite filters
    this.exportFilters.push(
      SAMLTraceIO_filters.obfuscateValueFilter('post', '*'),                          // obfuscate *all* the post elements
      SAMLTraceIO_filters.overwriteKeyValue('postData'),                              // overwrite the postData-variable
      SAMLTraceIO_filters.obfuscateCookieValueFilter('requestHeaders', 'Cookie'),     // obfuscate cookie values in request
      SAMLTraceIO_filters.obfuscateCookieValueFilter('responseHeaders', 'Set-Cookie') // ..as well as in response
    );
    break;
}

},

'perform' : function(reqs) {
let the_filters = this.exportFilters; // move from instance to local scope

const createFromJSON = function(obj) {
  let stringified = JSON.stringify(obj);
  return JSON.parse(stringified);
};

const enrichWithResponse = (req, res) => {
  let responseCopy = createFromJSON(res);
  req.responseStatus = responseCopy.statusCode;
  req.responseStatusText = responseCopy.statusLine;
  req.responseHeaders = responseCopy.responseHeaders;
};

let reqscopy = reqs.map(req => {
  let newRequest = createFromJSON(req);
  enrichWithResponse(newRequest, req.getResponse());

  the_filters.forEach(filter => filter(newRequest));
  return newRequest;
});

return reqscopy;

}
};
`

and second:
`/**

  • Some functionality to support the import/export
  • for SAML-tracer
  • Added to SAML-tracer by M. Dobrinic
  • 2011-dec
    **/

// export SAMLTrace namespace to make ao. Request definitions available
var EXPORTED_SYMBOLS = ["SAMLTraceIO"];

// Put functionality in out own namespace
if ("undefined" == typeof(SAMLTraceIO)) {
var SAMLTraceIO = {};
};

SAMLTraceIO = function() {
};

SAMLTraceIO.prototype = {
/**

  • Main feature: Exports and optionally filters traced requests.
    **/
    'exportRequests': function(reqs, cookieProfile) {
    // Perform request filtering based on user input from dialog:
    var ef = new SAMLTraceIO.ExportFilter(cookieProfile);
    var filteredreqs = ef.perform(reqs);
// Package results
var result = {
  requests: filteredreqs,
  timestamp: new Date().toISOString()
};
return result;

},

'serialize': function(exportResult) {
let indentSpaces = 2;
return JSON.stringify(exportResult, null, indentSpaces);
},

'getOutputFile': function(exportResult) {
let timeStamp = exportResult && exportResult.timestamp ? exportResult.timestamp : "no-timestamp";
return SAML-tracer-export-${timeStamp}.json;
},

/**

  • Imports requests and restores them in the TraceWindow.
    **/
    'importRequests': function(selectedFile, tracer, onSuccess, onError) {
    const parseRequests = rawResult => {
    try {
    let exportedSession = JSON.parse(rawResult);
    let successfullyRestored = this.restoreFromImport(exportedSession.requests, tracer, onError);
    if (successfullyRestored) {
    onSuccess();
    }
    } catch (error) {
    console.log("An error occured while trying to parse and import requests: " + error);
    if (error instanceof SyntaxError) {
    onError("The selected file doesn't seem to contain importable traces!");
    } else if (error instanceof TypeError) {
    onError("The selected file seems to be invalid or corrupted!");
    } else {
    onError("Error while importing: " + error);
    }
    }
    };
let reader = new FileReader();
reader.onload = e => {
  parseRequests(e.target.result);
}
reader.readAsText(selectedFile);

},

'restoreFromImport' : function(importedRequests, tracer, onError) {
if (!importedRequests || importedRequests.length === 0) {
onError("There aren't any requests to import...");
return false;
}

// Since the relase of v1.0.0 every request's got a "requestId". If it ain't present, it's a legacy import.
let isLegacyImport = !importedRequests[0].hasOwnProperty("requestId");
console.log(`The imported requests are in ${isLegacyImport ? "legacy" : "current"}-style.`);

const getHeaders = importedHeaders => {
  if (isLegacyImport) {
    return importedHeaders.map(h => { return { name: h[0], value: h[1] } });
  } else {
    return importedHeaders;
  }
};

const getRequestId = importedRequest => {
  return isLegacyImport ? importedRequest.id : importedRequest.requestId;
};

const createRestoreableModel = importedRequest => {
  let pseudoRequest = {
    req: {
      method: importedRequest.method,
      url: importedRequest.url,
      requestId: getRequestId(importedRequest),
      requestBody: {
        post: importedRequest.post
      }
    },
    requestId: getRequestId(importedRequest),
    url: importedRequest.url,
    headers: getHeaders(importedRequest.requestHeaders),
    saml: importedRequest.saml,
    getResponse: () => {
      let pseudoResponse = {
        requestId: getRequestId(importedRequest),
        url: importedRequest.url,
        statusCode: importedRequest.responseStatus,
        statusLine: importedRequest.responseStatusText,
        responseHeaders: getHeaders(importedRequest.responseHeaders)
      };
      return pseudoResponse;
    }
  };
  return pseudoRequest;
};

let restoreableRequests = importedRequests.map(ir => createRestoreableModel(ir));
restoreableRequests.forEach(rr => {
  tracer.saveNewRequest(rr);
  tracer.addRequestItem(rr, rr.getResponse);
  tracer.attachResponseToRequest(rr.getResponse());
});

return true;

}
};

/**

  • ExportFilter applies filtering of SAMLTrace.Request instances
  • based on provided profile
    **/
    SAMLTraceIO.ExportFilter = function(cookieProfile) {
    this.exportFilters = [];
    this.loadPreferences(cookieProfile);
    };

SAMLTraceIO.ExportFilter.prototype = {
'loadPreferences' : function(cookieProfile) {
this.exportFilters = [];

switch (cookieProfile) {
  case '1' :	// No cookiefiltering or filtering whatsoever
    break;

  case '2' :	// Apply hash filters
    this.exportFilters.push(
      SAMLTraceIO_filters.hashValueFilter('post', '*'),                          // hash *all* the post elements
      SAMLTraceIO_filters.overwriteKeyValue('postData'),                         // overwrite the postData-variable
      SAMLTraceIO_filters.hashCookieValueFilter('requestHeaders', 'Cookie'),     // hash cookie values in request
      SAMLTraceIO_filters.hashCookieValueFilter('responseHeaders', 'Set-Cookie') // ..as well as in response
    );
    break;

  case '3' :	// Apply obfuscate/overwrite filters
    this.exportFilters.push(
      SAMLTraceIO_filters.obfuscateValueFilter('post', '*'),                          // obfuscate *all* the post elements
      SAMLTraceIO_filters.overwriteKeyValue('postData'),                              // overwrite the postData-variable
      SAMLTraceIO_filters.obfuscateCookieValueFilter('requestHeaders', 'Cookie'),     // obfuscate cookie values in request
      SAMLTraceIO_filters.obfuscateCookieValueFilter('responseHeaders', 'Set-Cookie') // ..as well as in response
    );
    break;
}

},

'perform' : function(reqs) {
let the_filters = this.exportFilters; // move from instance to local scope

const createFromJSON = function(obj) {
  let stringified = JSON.stringify(obj);
  return JSON.parse(stringified);
};

const enrichWithResponse = (req, res) => {
  let responseCopy = createFromJSON(res);
  req.responseStatus = responseCopy.statusCode;
  req.responseStatusText = responseCopy.statusLine;
  req.responseHeaders = responseCopy.responseHeaders;
};

let reqscopy = reqs.map(req => {
  let newRequest = createFromJSON(req);
  enrichWithResponse(newRequest, req.getResponse());

  the_filters.forEach(filter => filter(newRequest));
  return newRequest;
});

return reqscopy;

}
};`

@khlr
Copy link
Contributor

khlr commented Feb 11, 2020

Does this occur for each and every trace you try to export?
Or does it only happen, when there's a certain request contained in the trace?

Could you please try make a small trace. E.g. just trace the request to this issue. Is it exportable?

I could very well imagine that there's a single request in your trace which causes the error.
We probably need to narrow down the source of the problem 😉

@michaellewis259
Copy link
Author

I receive this error on ANY export attempt, both Chrome and Firefox. This is why I think it's something to do with our Cylance policy that is preventing the export from completing

@tvdijen
Copy link
Member

tvdijen commented Feb 11, 2020

I'm on a REALLY tight government workstation and even I can use SAML-tracer..
Why not try and disable your security tool for a second and see if it makes any difference, instead of asking us to debug the indebuggable/non-reproducible issue?

Ask yourself how you can rule out your environment, instead of asking the community to rule out an environment that's a complete black-box for them ;)

@khlr
Copy link
Contributor

khlr commented Feb 12, 2020

Yep, as Tim said it's really hard to guess what the problem may be. 🤔

I think it's really worth a try disabling Cylance for a moment.
Does it log something when re-enable it and try the export again? Does it prevent other downloads or similar things, too?

@michaellewis259
Copy link
Author

That's what I was somewhat obscurely asking for in my initial post. Are there any paths your extensions runs from I can try to exclude from our EPP?

@tvdijen
Copy link
Member

tvdijen commented Feb 14, 2020

What do you mean by paths? This add-on is all javascript..

@michaellewis259
Copy link
Author

I ask because EPPs can block scripts based upon policies, and I need the path the script runs from to exclude said script(s)

@khlr
Copy link
Contributor

khlr commented Feb 15, 2020

You could try the following:

  • Type about:support into Firefox's addressbar. There you'll find an extensions-section.
  • Look for SAML-tracer in the table and note its ID.
  • Go back to the top of the support-page and open the path to your profile-folder.
  • Open the extensions-folder.
  • There you'll find a file named like <SAML-tracer extension ID>.xpi
  • Exclude the path to that file from your EPP (whatever this abbreviation may mean 😁 an "endpoint protection platform"?)

Good luck 😀👍

@khlr
Copy link
Contributor

khlr commented Feb 22, 2020

Did this work out for you, @michaellewis259? Or did you give up on it? 😕

@michaellewis259
Copy link
Author

Nothing seems to be working, no exclusion I make (that's acceptable from a security standpoint) helps. I'll just use a VM or something. I appreciate the assist, and sorry for the wasted time.

@si-heger
Copy link

Even though this issue is closed I just want to add that I have the exact same issue

@tvdijen
Copy link
Member

tvdijen commented Nov 30, 2021

@si-heger Are you using the same security product as the OP?
If you can help us get to the problematic code, we can try to fix it..

@si-heger
Copy link

@tvdijen We are not using the same products but similar stuff like Crowdstrike Falcon and Tenable Nessus. Getting the code is difficult as I am not a programmer :) If you can send me an instruction on how to get more details I can do that

@tvdijen
Copy link
Member

tvdijen commented Nov 30, 2021

See if you can get things to work by following @khlr 's suggestions.
I'm not familiar with Crowdstrike or Tenable, but I'm sure it produces logs if it blocks something..

@slowerogue
Copy link

slowerogue commented Aug 1, 2022

I have the same issue, on my VM, just normal windows 10 without any antivirus installed.

on the saml-tracer, (f12), console>

Uncaught SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
    createFromJSON moz-extension://bf62048e-a85b-45ab-9121-67d45272d2fb/src/SAMLTraceIO.js:180
    enrichWithResponse moz-extension://bf62048e-a85b-45ab-9121-67d45272d2fb/src/SAMLTraceIO.js:184
    reqscopy moz-extension://bf62048e-a85b-45ab-9121-67d45272d2fb/src/SAMLTraceIO.js:192
    perform moz-extension://bf62048e-a85b-45ab-9121-67d45272d2fb/src/SAMLTraceIO.js:190
    exportRequests moz-extension://bf62048e-a85b-45ab-9121-67d45272d2fb/src/SAMLTraceIO.js:26
    createExportResult moz-extension://bf62048e-a85b-45ab-9121-67d45272d2fb/src/exportDialog.js:66
    setupContent moz-extension://bf62048e-a85b-45ab-9121-67d45272d2fb/src/exportDialog.js:60
    bindButtons moz-extension://bf62048e-a85b-45ab-9121-67d45272d2fb/src/ui.js:95

Anyway , what I tested was :
If I access the page that prompt for Warning: Potential Security Risk Ahead, SEC_ERROR_UNKNOWN_ISSUER, then the export will be null
If I have already accept the risk and conitnue previously, then the export works as expected

@kellenmurphy
Copy link
Contributor

I was able to replicate this as well, based on what info @slowerogue provided above.

2022-08-01 08_54_32

I simply triggered an AuthnRequest to an IDP that had a self-signed certificate loaded. I was unable to export the AuthnRequest in SAML-Tracer. Even trying the export again after clicking "Accept Risk and Continue" I was unable to export.

All of this testing was performed in my lab environment with no security solution in place, and given the issue seems to have cropped up for sites with self-signed certs (and hence the "Potential Security Risk" warning), I am going to venture and guess that this may be related to Firefox security impositions? I use SAML-Tracer frequently with in-progress or dev sites with self-signed HTTPS certificates, but I don't think I've ever tried exporting one of them.

Strictly speaking, I'm not sure that this is 100% related to the issue as originally brought up by @michaellewis259, but it very well could be, and certainly does seem to be repeatable. My deep suspicion here is that this is the result of restrictions placed on the WebExtension when the security warning is triggered for the self-signed cert.

@kellenmurphy
Copy link
Contributor

I also just noticed that we're dead-threading here... I'm going to post my comment above on the open issue #69.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants