/** * Cyber Triage Service * @since 1.1.0 */ init_view(); validate_libs(); // GLOBALS var lookup_results = undefined; var session_file_name = undefined; function validate_libs() { if (typeof saveAs === "undefined" || typeof Blob === "undefined") { $("#browser_error_div").toggle(); $("#main_div").toggle(); } } function init_view() { $("#browser_error_div").toggle(); $("#success_div").toggle(); $("#error_div").toggle(); } function process() { $("#status_msg").text(''); var jsonInpObj = validate_input(); if(!jsonInpObj){ return; } $("#overlay").toggle(); // Toggle the overlay $("#json_data").prop("disabled", true); $("#upload_button").prop("disabled", true); var tokenSvc = invoke_reputation_service_getToken(jsonInpObj); tokenSvc.done(function(data) { invoke_reputation_service_queryHashes(data, jsonInpObj) }); tokenSvc.fail(function(err) { var errorMessage = err.responseJSON.error.message; display_service_errors(errorMessage); if ($("#overlay").is(":visible")) { $("#overlay").toggle(); // if overlay is visible .. close it. } }); tokenSvc.always(function() { $("#status_msg").text(''); }); } function invoke_reputation_service_getToken(obj) { var tokenData = JSON.stringify( { "license_id" : obj.license_id, "host_id" : obj.license_host_id , "ct_version": obj.ct_version } ); var tokenSvc = $.ajax({ method : "POST", url: "/_ah/api/auth/v1/generate_token", data: tokenData, dataType : "json", beforeSend: function( xhr ) { xhr.setRequestHeader('Content-Type', 'application/json'); $("#status_msg").text('Authenticating...'); } }); return tokenSvc; } function invoke_reputation_service_queryHashes(tokenData, obj){ // process the hashes in chunks of 200. var hashesList = _.chunk(obj.hashes, 200) var promises = []; _.forEach(hashesList, function(hashes) { var hashData = JSON.stringify({"hashes" : hashes}); var params = { query_types:'MALWARE,CORRELATION', host_id:obj.target_host_id, token:tokenData.token , api_key: tokenData.api_key }; var paramsStr = jQuery.param( params ); var querySvcPromise = $.ajax({ method : "POST", url: "_ah/api/reputation/v1/query/file/hash/Md5?"+paramsStr, data: hashData, dataType : "json", beforeSend: function( xhr ) { xhr.setRequestHeader('Content-Type', 'application/json'); $("#status_msg").text('Processing hashes...'); } }); promises.push(querySvcPromise); }); // https://medium.com/swlh/dealing-with-multiple-promises-in-javascript-41d6c21f20ff // https://eligrey.com/blog/saving-generated-files-on-the-client-side/ Promise.all(promises) .then(function(values) { var _items = [].concat.apply([], values.map( function(v) { return v.items})); lookup_results = JSON.stringify({ items : _items, session_id: obj.session_id, hashes_count: obj.hashes_count}); try{ session_file_name = "results_" + obj.session_id.replace('|','_')+".json"; }catch(ex){ session_file_name = "results_" + obj.session_id+".json"; } //console.log(str); $("#status_msg").text(''); $("#success_div").toggle(); if ($("#overlay").is(":visible")) { $("#overlay").toggle(); // if overlay is visible .. close it. } }) .catch(function(err) { console.log(err.responseJSON.error.message) display_service_errors(err.responseJSON.error.message); if ($("#overlay").is(":visible")) { $("#overlay").toggle(); // if overlay is visible .. close it. } }); // TODO: Session ID in saved file // TODO: File name ? // TODO: Deal with errors during lookup. } function save_to_disk() { if(lookup_results != undefined) { saveAs(new Blob([lookup_results], {type: "application/json;charset=utf-8" }), session_file_name); } } function reset_page() { $("#json_data").removeClass("is-invalid"); $("#json_data").val("") $("#json_data").focus(); $("#json_data").prop("disabled", false); $("#upload_button").prop("disabled", false); location.reload(); } function display_validation_errors(message) { $("#json_data").addClass("is-invalid"); $("#json_data_validation_msg").text(message); return false; } function display_service_errors(message) { $("#response_error_msg").text(message); $("#error_div").toggle(); } function validate_input() { $("#json_data").removeClass("is-invalid"); var inputJSON = $.trim($("#json_data").val()); if (inputJSON.length == 0) { return display_validation_errors("Please provide the hashes list JSON"); } try { var obj = jQuery.parseJSON(inputJSON); // Validate fields. This is the long way, but easier to write and debug. also, we dont have to do this too often anyways. if (obj.license_id === undefined) { return display_validation_errors("license_id field is missing in the JSON"); } if (obj.license_host_id === undefined) { return display_validation_errors("license_host_id field is missing in the JSON"); } if (obj.ct_version === undefined) { return display_validation_errors("ct_version field is missing in the JSON"); } if (obj.target_host_id === undefined) { return display_validation_errors("target_host_id field is missing in the JSON"); } if (obj.session_id === undefined) { return display_validation_errors("session_id field is missing in the JSON"); } if (obj.hashes_count === undefined) { return display_validation_errors("hashes_count field is missing in the JSON"); } if (obj.hashes === undefined || obj.hashes.length == 0) { return display_validation_errors("hashes field is missing or invaild in the JSON"); } return obj; } catch (err) { console.log(err); return display_validation_errors("JSON parsing error : (" + err + ")"); } }