diff --git a/components/virustotal.js b/components/virustotal.js index 7ce29f2..189d575 100644 --- a/components/virustotal.js +++ b/components/virustotal.js @@ -111,7 +111,7 @@ polarity.export = PolarityComponent.extend({ 'numResolutionsShown', Math.min(this.get('maxResolutionsToShow'), this.get('details.resolutions.length')) ); - console.log(this.get('details')) + console.log(this.get('details')); this._super(...arguments); }, diff --git a/integration.js b/integration.js index 9e784b6..6c23f53 100644 --- a/integration.js +++ b/integration.js @@ -38,9 +38,6 @@ const debugLookupStats = { const throttleCache = new Map(); const BUG_ICON = ``; - -const GLOBE_ICON = ``; - const IGNORED_IPS = new Set(['127.0.0.1', '255.255.255.255', '0.0.0.0']); const LOOKUP_URI_BY_TYPE = { @@ -89,7 +86,7 @@ function doLookup(entities, options, cb) { if (pendingLookupCache.isRunning(entity.value)) return pendingLookupCache.addPendingLookup(entity.value, cb); - if(_isEntityBlocked(entity, options)){ + if (_isEntityBlocked(entity, options)) { return; } @@ -249,41 +246,44 @@ function _isEntityBlocked(entity, options) { const currentDomainUrlBlocklistRegex = options.domainUrlBlocklistRegex; // initialize regex if needed - if(ipBlocklistRegex === null && currentIpBlocklistRegex.length > 0){ + if (ipBlocklistRegex === null && currentIpBlocklistRegex.length > 0) { Logger.debug('Initializing ip blocklist regex'); ipBlocklistRegex = new RegExp(currentIpBlocklistRegex); } - if(domainUrlBlocklistRegex === null && currentDomainUrlBlocklistRegex.length > 0){ + if (domainUrlBlocklistRegex === null && currentDomainUrlBlocklistRegex.length > 0) { Logger.debug('Initializing domain/url blocklist regex'); domainUrlBlocklistRegex = new RegExp(currentDomainUrlBlocklistRegex); } - if(currentIpBlocklistRegex.length === 0){ + if (currentIpBlocklistRegex.length === 0) { ipBlocklistRegex = null; } - if(currentDomainUrlBlocklistRegex.length === 0){ + if (currentDomainUrlBlocklistRegex.length === 0) { domainUrlBlocklistRegex = null; } - if(ipBlocklistRegex !== null && ipBlocklistRegex.toString() !== `/${currentIpBlocklistRegex}/`){ + if ( + ipBlocklistRegex !== null && + ipBlocklistRegex.toString() !== `/${currentIpBlocklistRegex}/` + ) { Logger.debug('Updating ipBlocklistRegex'); ipBlocklistRegex = new RegExp(currentIpBlocklistRegex); } - if(domainUrlBlocklistRegex !== null && domainUrlBlocklistRegex.toString() !== `/${currentDomainUrlBlocklistRegex}/`){ + if ( + domainUrlBlocklistRegex !== null && + domainUrlBlocklistRegex.toString() !== `/${currentDomainUrlBlocklistRegex}/` + ) { Logger.debug('Updating domainUrlBlocklistRegex'); domainUrlBlocklistRegex = new RegExp(currentDomainUrlBlocklistRegex); } - Logger.trace( - { blocklist }, - 'Blocklist value' - ); + Logger.trace({ blocklist }, 'Blocklist value'); if (_.includes(blocklist, entity.value.toLowerCase())) { - Logger.debug({entity: entity.value}, 'Blocked Entity'); + Logger.debug({ entity: entity.value }, 'Blocked Entity'); return true; } @@ -308,16 +308,13 @@ function _isEntityBlocked(entity, options) { } } - if(entity.isURL){ + if (entity.isURL) { if (domainUrlBlocklistRegex !== null) { const urlObj = new URL(entity.value); const hostname = urlObj.hostname; Logger.debug(hostname, 'Hostname of url to block'); if (domainUrlBlocklistRegex.test(hostname)) { - Logger.debug( - { url: entity.value}, - 'URL lookup blocked due to blocklist regex' - ); + Logger.debug({ url: entity.value }, 'URL lookup blocked due to blocklist regex'); return true; } } @@ -448,7 +445,9 @@ function _lookupHash(hashesArray, entityLookup, options, done) { function _lookupUrl(entity, options, done) { if (doLookupLogging) debugLookupStats.urlLookups++; - const urlAsBase64WithoutPadding = Buffer.from(entity.value).toString('base64').replace(/=+$/, ''); + const urlAsBase64WithoutPadding = Buffer.from(entity.value) + .toString('base64') + .replace(/=+$/, ''); let requestOptions = { uri: `${LOOKUP_URI_BY_TYPE.url}/${urlAsBase64WithoutPadding}`, method: 'GET', @@ -845,8 +844,27 @@ function onDetails(lookupObject, options, cb) { }); }); }); + } else if (entity.isMD5 || entity.isSHA1 || entity.isSHA256) { + let fileNameOptions = { + uri: `https://www.virustotal.com/api/v3/files/${entity.value}`, + method: 'GET', + headers: { 'x-apikey': options.apiKey } + }; + + requestWithDefaults(fileNameOptions, (err, response, body) => { + _handleRequestError(err, response, body, options, (err, result) => { + if (err) { + Logger.error(err, `Error Looking up ${_.startCase(type)}`); + return done(err); + } + + lookupObject.data.details.fileNames = result.data.attributes.names; + + cb(null, lookupObject.data); + }); + }); } else { - return cb(null, lookupObject.data); + cb(null, lookupObject.data); } } diff --git a/package.json b/package.json index 04afd3c..9d9c837 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "main": "./integration.js", "name": "VirusTotal", - "version": "3.4.1-beta", + "version": "3.5.1-beta", "private": true, "dependencies": { - "request": "^2.88.2", + "async": "^3.2.0", "lodash": "^4.17.21", - "async": "^3.2.0" + "request": "^2.88.2" }, "devDependencies": { "chai": "^4.2", diff --git a/styles/virustotal.less b/styles/virustotal.less index 0d8777b..34793fc 100644 --- a/styles/virustotal.less +++ b/styles/virustotal.less @@ -9,7 +9,7 @@ b.muted { font-size: 8px; } -.table-icon{ +.table-icon { font-size: 10px; } @@ -86,4 +86,8 @@ td.positives { } } } -} \ No newline at end of file +} + +.name-list { + margin-top: 15px; +} diff --git a/templates/virustotal.hbs b/templates/virustotal.hbs index a719c17..593a7f6 100644 --- a/templates/virustotal.hbs +++ b/templates/virustotal.hbs @@ -1,383 +1,481 @@ {{#if details.noInfoMessage}} -
- No Information in VirusTotal -
+
+ No Information in VirusTotal +
{{else}} -
-
-
- - - - - - - {{details.positives}} - - - / {{details.total}} - - - - -
-
- {{#if details.tags.length}} -
-

- {{fa-icon "tags" fixedWidth=true}} - Tags -

-
- {{#each details.tags as |tag|}} -
- {{tag}} -
- {{/each}} -
-
- {{/if}} +
+
+
+ + + + + + + {{details.positives}} + + + / + {{details.total}} + + + + +
- - - - {{#if (eq activeTab "detection")}} - -
- Scan Date: - {{moment-format details.scan_date "YYYY-MM-DD HH:mm:ss UTC"}} + {{#if details.tags.length}} +
+

+ {{fa-icon "tags" fixedWidth=true}} + Tags +

+
+ {{#each details.tags as |tag|}} +
+ {{tag}} +
+ {{/each}}
+
+ {{/if}} +
-
- - {{fa-icon "laptop" fixedWidth=true}} - Scan Results ({{details.positives}} of {{details.total}}) - {{fa-icon (if showScanResults "caret-up" "caret-down") fixedWidth=true}} - -
- {{#if showScanResults}} -
- - - {{#each details.positiveScans as |positiveScan|}} - - - - - {{/each}} - {{#each details.negativeScans as |negativeScan|}} - - - - - {{/each}} - -
- {{positiveScan.name}} - - - {{fa-icon "exclamation" class="p-red table-icon" fixedWidth=true}} - {{positiveScan.result}} - -
- {{negativeScan.name}} - - - {{#if (eq negativeScan.result "Unrated")}} - {{fa-icon "question" class="p-grey table-icon" fixedWidth=true}} - {{else}} - {{#if (eq negativeScan.result "type-unsupported")}} - {{fa-icon "eye-slash" class="p-grey table-icon" fixedWidth=true}} - {{else}} - {{#if (eq negativeScan.result "Suspicious")}} - {{fa-icon "info" class="p-orange table-icon" fixedWidth=true}} - {{else}} - {{fa-icon "check" class="p-green table-icon" fixedWidth=true}} - {{/if}} - {{/if}} - {{/if}} - {{#if (eq negativeScan.result "type-unsupported")}} - Unable to process file type - {{else}} - {{#if (eq negativeScan.result "Suspicious")}} - Suspicious - {{else}} - {{#if (not negativeScan.result)}} - Undetected - {{else}} - {{negativeScan.result}} - {{/if}} - {{/if}} - {{/if}} - -
-
- {{/if}} + - {{#if (eq activeTab "details")}} - - {{#if details.detailsTab.length}} - {{#each details.detailsTab as |detailsField|}} - {{#if detailsField.isObject}} -

{{fa-icon icon="th-list" fixedWidth=true}} {{detailsField.key}}

- {{#each-in detailsField.value as |key value|}} - {{#if value}} -
- {{key}}: - {{value}} -
+ {{#if (eq activeTab "detection")}} + +
+ Scan Date: + {{moment-format + details.scan_date + "YYYY-MM-DD HH:mm:ss UTC" + }} +
+ {{! detections }} +
+ + {{fa-icon "laptop" fixedWidth=true}} + Scan Results ({{details.positives}} + of + {{details.total}}) + {{fa-icon (if showScanResults "caret-up" "caret-down") fixedWidth=true}} + +
+ {{#if showScanResults}} +
+ + + {{#each details.positiveScans as |positiveScan|}} + + + + + {{/each}} + {{#each details.negativeScans as |negativeScan|}} + + + + {{/each}} + +
+ {{positiveScan.name}} + + + {{fa-icon "exclamation" class="p-red table-icon" fixedWidth=true}} + {{positiveScan.result}} + +
+ {{negativeScan.name}} + + + {{#if (eq negativeScan.result "Unrated")}} + {{fa-icon "question" class="p-grey table-icon" fixedWidth=true}} + {{else}} + {{#if (eq negativeScan.result "type-unsupported")}} + {{fa-icon "eye-slash" class="p-grey table-icon" fixedWidth=true}} + {{else}} + {{#if (eq negativeScan.result "Suspicious")}} + {{fa-icon "info" class="p-orange table-icon" fixedWidth=true}} + {{else}} + {{fa-icon "check" class="p-green table-icon" fixedWidth=true}} + {{/if}} {{/if}} - {{/each-in}} - {{else}} - {{#if detailsField.isList}} - {{#each detailsField.value as |value|}} - {{#if value}} -
- {{detailsField.key}}: - {{value}} -
- {{/if}} - {{/each}} + {{/if}} + {{#if (eq negativeScan.result "type-unsupported")}} + Unable to process file type {{else}} - {{#if detailsField.isTitle}} -

{{fa-icon icon="th-list" fixedWidth=true}} {{detailsField.key}}

+ {{#if (eq negativeScan.result "Suspicious")}} + Suspicious + {{else}} + {{#if (not negativeScan.result)}} + Undetected {{else}} - {{#if detailsField.value}} -
- {{detailsField.key}}: - {{detailsField.value}} -
- {{/if}} + {{negativeScan.result}} {{/if}} + {{/if}} {{/if}} - {{/if}} +
+
+
+ {{/if}} + {{/if}} + {{! end of detections}} + {{! start of file names}} + {{#if (eq activeTab "fileNames")}} + {{#if block.isLoadingDetails}} + Loading Highlights ... + {{else}} + + {{#if block.data.details.fileNames}} +
+ {{fa-icon "laptop" fixedWidth=true}} + Filenames +
+ {{#each block.data.details.fileNames as |name index|}} + + {{/each}} + {{else}} + No Filenames found + {{/if}} + {{/if}} + {{/if}} + {{! end of file names}} + {{#if (eq activeTab "details")}} + + {{#if details.detailsTab.length}} + {{#each details.detailsTab as |detailsField|}} + {{#if detailsField.isObject}} +

{{fa-icon icon="th-list" fixedWidth=true}} + {{detailsField.key}}

+ {{#each-in detailsField.value as |key value|}} + {{#if value}} +
+ {{key}}: + {{value}} +
+ {{/if}} + {{/each-in}} + {{else}} + {{#if detailsField.isList}} + {{#each detailsField.value as |value|}} + {{#if value}} +
+ {{detailsField.key}}: + {{value}} +
+ {{/if}} + {{/each}} + {{else}} + {{#if detailsField.isTitle}} +

{{fa-icon icon="th-list" fixedWidth=true}} + {{detailsField.key}}

+ {{else}} + {{#if detailsField.value}} +
+ {{detailsField.key}}: + {{detailsField.value}} +
+ {{/if}} + {{/if}} + {{/if}} {{/if}} + {{/each}} {{/if}} + {{/if}} - {{#if (eq activeTab "relations")}} - - {{#if details.referenceFiles.length}} -
- - {{fa-icon "project-diagram" fixedWidth=true}} - Files Referring ({{details.referenceFiles.length}}) - {{fa-icon (if showFilesReferring "caret-up" "caret-down") fixedWidth=true}} + {{#if (eq activeTab "relations")}} + + {{#if details.referenceFiles.length}} +
+ + {{fa-icon "project-diagram" fixedWidth=true}} + Files Referring ({{details.referenceFiles.length}}) + {{fa-icon (if showFilesReferring "caret-up" "caret-down") fixedWidth=true}} + +
+ + {{#if showFilesReferring}} + {{#each details.referenceFiles as |referrenceFile|}} +
+ {{#if referrenceFile.name}} +
+ Name: + + {{#if referrenceFile.link}} + {{referrenceFile.name}} + {{else}} + {{referrenceFile.name}} + {{/if}} -
+
+ {{/if}} + {{#if referrenceFile.type}} +
+ Type: + {{referrenceFile.type}} +
+ {{/if}} + {{#if referrenceFile.detections}} +
+ Detections: + {{referrenceFile.detections}} +
+ {{/if}} + {{#if referrenceFile.scannedDate}} +
+ Scanned: + + {{#if (eq referrenceFile.scannedDate "-")}} + - + {{else}} + {{moment-format referrenceFile.scannedDate "YYYY-MM-DD HH:mm:ss UTC"}} + {{/if}} + +
+ {{/if}} +
+ {{/each}} + {{/if}} + {{/if}} + + {{#if details.historicalWhoIs.length}} +
+ + {{fa-icon "project-diagram" fixedWidth=true}} + Historical Whois Lookups ({{details.historicalWhoIs.length}}) + {{fa-icon (if showHistoricalWhois "caret-up" "caret-down") fixedWidth=true}} + +
- {{#if showFilesReferring}} - {{#each details.referenceFiles as |referrenceFile|}} -
- {{#if referrenceFile.name}} -
- Name: - - {{#if referrenceFile.link}} - {{referrenceFile.name}} - {{else}} - {{referrenceFile.name}} - {{/if}} - -
+ {{#if showHistoricalWhois}} + {{#if block.entity.isIP}} +
+ + + + + + + + + +
Last UpdatedOrganizationEmail
+ {{#each details.historicalWhoIs as |whoisRow index|}} + + + + + + + + + +
+ {{fa-icon + (if (get expandedWhoisMap index) "caret-up" "caret-down") + fixedWidth=true + }} + + {{moment-format + whoisRow.last_updated + "YYYY-MM-DD" + }} + + + {{#if whoisRow.OrgName}} + {{whoisRow.OrgName}} + {{else}} + - {{/if}} - {{#if referrenceFile.type}} -
- Type: - {{referrenceFile.type}} -
+
+
+ + {{#if whoisRow.OrgTechEmail}} + {{whoisRow.OrgTechEmail}} + {{else}} + - {{/if}} - {{#if referrenceFile.detections}} -
- Detections: - {{referrenceFile.detections}} -
+
+
+ {{#if (get expandedWhoisMap index)}} +
+ {{#each whoIsIpKeys as |ipKey|}} + {{#if (get whoisRow ipKey.key)}} +
+ {{ipKey.key}}: + + {{#if ipKey.isDate}} + {{moment-format + (get whoisRow ipKey.key) + "YYYY-MM-DD HH:mm:ss UTC" + }} + {{else}} + {{get whoisRow ipKey.key}} + {{/if}} + +
+ {{/if}} + {{/each}} +
+ {{/if}} + {{/each}} +
+ {{else}} +
+ + + + + + + + + +
Last UpdatedRegistrarRegistrant
+ {{#each details.historicalWhoIs as |whoisRow index|}} + + + + + + + + + +
+ {{fa-icon + (if (get expandedWhoisMap index) "caret-up" "caret-down") + fixedWidth=true + }} + + {{moment-format + whoisRow.last_updated + "YYYY-MM-DD" + }} + + + {{#if whoisRow.Registrar}} + {{whoisRow.Registrar}} + {{else}} + - {{/if}} - {{#if referrenceFile.scannedDate}} -
- Scanned: - - {{#if (eq referrenceFile.scannedDate "-")}} - - - {{else}} - {{moment-format referrenceFile.scannedDate "YYYY-MM-DD HH:mm:ss UTC"}} - {{/if}} - -
+
+
+ + {{#if whoisRow.Registrant}} + {{whoisRow.Registrant}} + {{else}} + - {{/if}} - - {{/each}} - {{/if}} - {{/if}} - - {{#if details.historicalWhoIs.length}} -
- - {{fa-icon "project-diagram" fixedWidth=true}} - Historical Whois Lookups ({{details.historicalWhoIs.length}}) - {{fa-icon (if showHistoricalWhois "caret-up" "caret-down") fixedWidth=true}} - -
- - {{#if showHistoricalWhois}} - {{#if block.entity.isIP}} -
- - - - - - - - - -
Last UpdatedOrganizationEmail
- {{#each details.historicalWhoIs as |whoisRow index|}} - - - - - - - - - -
- {{fa-icon (if (get expandedWhoisMap index) "caret-up" "caret-down") fixedWidth=true}} - - {{moment-format whoisRow.last_updated "YYYY-MM-DD"}} - - - {{#if whoisRow.OrgName}} - {{whoisRow.OrgName}} - {{else}} - - - {{/if}} - - - - {{#if whoisRow.OrgTechEmail}} - {{whoisRow.OrgTechEmail}} - {{else}} - - - {{/if}} - -
- {{#if (get expandedWhoisMap index)}} -
- {{#each whoIsIpKeys as |ipKey|}} - {{#if (get whoisRow ipKey.key)}} -
- {{ipKey.key}}: - - {{#if ipKey.isDate}} - {{moment-format (get whoisRow ipKey.key) "YYYY-MM-DD HH:mm:ss UTC"}} - {{else}} - {{get whoisRow ipKey.key}} - {{/if}} - -
- {{/if}} - {{/each}} -
- {{/if}} - {{/each}} -
- {{else}} -
- - - - - - - - - -
Last UpdatedRegistrarRegistrant
- {{#each details.historicalWhoIs as |whoisRow index|}} - - - - - - - - - -
- {{fa-icon (if (get expandedWhoisMap index) "caret-up" "caret-down") fixedWidth=true}} - - {{moment-format whoisRow.last_updated "YYYY-MM-DD"}} - - - {{#if whoisRow.Registrar}} - {{whoisRow.Registrar}} - {{else}} - - - {{/if}} - - - - {{#if whoisRow.Registrant}} - {{whoisRow.Registrant}} - {{else}} - - - {{/if}} - -
- {{#if (get expandedWhoisMap index)}} -
- {{#each whoIsDomainKeys as |domainKey|}} - {{#if (get whoisRow domainKey.key)}} -
- {{domainKey.key}}: - - {{#if domainKey.isDate}} - {{moment-format (get whoisRow domainKey.key) "YYYY-MM-DD HH:mm:ss UTC"}} - {{else}} - {{get whoisRow domainKey.key}} - {{/if}} - -
- {{/if}} - {{/each}} -
- {{/if}} - {{/each}} -
- {{/if}} - {{/if}} +
+
+ {{#if (get expandedWhoisMap index)}} +
+ {{#each whoIsDomainKeys as |domainKey|}} + {{#if (get whoisRow domainKey.key)}} +
+ {{domainKey.key}}: + + {{#if domainKey.isDate}} + {{moment-format + (get whoisRow domainKey.key) + "YYYY-MM-DD HH:mm:ss UTC" + }} + {{else}} + {{get whoisRow domainKey.key}} + {{/if}} + +
+ {{/if}} + {{/each}} +
+ {{/if}} + {{/each}} +
{{/if}} + {{/if}} {{/if}} -{{/if}} + {{/if}} +{{/if}} \ No newline at end of file