diff --git a/_data/legit_urls.yaml b/_data/legit_urls.yaml index dfba4fef..d5aad537 100644 --- a/_data/legit_urls.yaml +++ b/_data/legit_urls.yaml @@ -3,6 +3,7 @@ name: MyCrypto url: 'https://mycrypto.com' featured: true + description: Ethereum blockchain interface. addresses: - '0x4bbeEB066eD09B7AEd07bF39EEe0460DFa261520' - @@ -10,10 +11,11 @@ name: MetaMask url: 'https://metamask.io' featured: true + description: Ethereum Web3 wallet - browser extension - id: 3 name: MyCryptoAPI - url: 'https://www.mycryptoapi.com' + url: 'https://mycryptoapi.com' - id: 4 name: Ethereum @@ -28,6 +30,7 @@ name: Ledger Wallet featured: true url: 'https://ledgerwallet.com' + description: Hardware wallet provider - id: 7 name: Etherscan @@ -35,6 +38,7 @@ featured: true addresses: - '0x71c7656ec7ab88b098defb751b7401b5f6d8976f' + description: Block explorer - id: 8 name: EtherID @@ -50,7 +54,7 @@ - id: 11 name: ETHNews - url: 'https://www.ethnews.com' + url: 'https://ethnews.com' - id: 12 name: ETHEX @@ -134,19 +138,19 @@ - id: 32 name: EthereumNZ - url: 'http://www.ethereum.nz' + url: 'http://ethereum.nz' - id: 33 name: nethereum - url: 'http://www.nethereum.com' + url: 'http://nethereum.com' - id: 34 name: metamas - url: 'http://www.metamas.com' + url: 'http://metamas.com' - id: 35 name: Metabase - url: 'http://www.metabase.com' + url: 'http://metabase.com' - id: 36 name: FundRequest @@ -154,7 +158,7 @@ - id: 37 name: Dentacoin - url: 'https://www.dentacoin.com' + url: 'https://dentacoin.com' - id: 38 name: Etherplan @@ -167,6 +171,7 @@ id: 40 name: Bity url: 'https://bity.com' + description: Provider of crypto swap services - id: 41 name: Changelly @@ -176,15 +181,15 @@ - id: 42 name: Coinbase - url: 'https://www.coinbase.com' + url: 'https://coinbase.com' - id: 43 name: CryptoCompare - url: 'https://www.cryptocompare.com' + url: 'https://cryptocompare.com' - id: 44 name: Easy Ethereum - url: 'https://www.easyeth.com' + url: 'https://easyeth.com' - id: 45 name: Etherchain @@ -215,7 +220,7 @@ id: 51 name: Kraken featured: true - url: 'https://www.kraken.com' + url: 'https://kraken.com' - id: 52 name: MyEtherWallet Knowledge Base @@ -224,6 +229,7 @@ id: 53 name: ShapeShift featured: true + description: Simple cryptocurrency exchange url: 'https://shapeshift.io' - id: 54 @@ -242,11 +248,13 @@ id: 57 name: Bittrex featured: true + description: Cryptocurrency exchange url: 'https://bittrex.com' - id: 58 name: Coindash featured: true + description: Cryptocurrency exchange url: 'https://coindash.io' - id: 59 @@ -277,12 +285,12 @@ id: 64 name: KICKICO featured: true - url: 'https://www.kickico.com' + url: 'https://kickico.com' - id: 65 name: Monetha featured: true - url: 'https://www.monetha.io' + url: 'https://monetha.io' - id: 66 name: Numerai @@ -312,7 +320,7 @@ id: 71 name: TenX featured: true - url: 'https://www.tenx.tech' + url: 'https://tenx.tech' - id: 72 name: Ubiq @@ -322,7 +330,7 @@ id: 73 name: Unocoin featured: true - url: 'https://www.unocoin.com' + url: 'https://unocoin.com' - id: 74 name: Golem @@ -335,7 +343,7 @@ - id: 76 name: Swapy Network - url: 'https://www.swapy.network/' + url: 'https://swapy.network/' - id: 77 name: COPYTRACK @@ -343,7 +351,8 @@ - id: 78 name: Parity - url: 'https://www.parity.io/' + description: Ethereum client + url: 'https://parity.io/' - id: 79 name: Parity Technologies @@ -359,20 +368,23 @@ - id: 82 name: MyEtherWallet - url: 'https://www.myetherwallet.com' + description: Ethereum blockchain interface + url: 'https://myetherwallet.com' - id: 83 name: AirSwap - url: 'https://www.airswap.io' + url: 'https://airswap.io' - id: 84 name: IDEX + description: Decentralized exchange with centralized order book url: 'https://idex.market' - id: 85 name: BTCManager + description: Crypto news site url: 'http://btcmanager.com' - id: 86 - name: Neodium Network + name: Neodium Network url: 'https://neodium.network' diff --git a/_layouts/neutraldomain.html b/_layouts/neutraldomain.html new file mode 100644 index 00000000..fd8bca88 --- /dev/null +++ b/_layouts/neutraldomain.html @@ -0,0 +1,28 @@ + +
+

{{ neutral.name }}

+
+{{ neutral.notification }} +{{ neutral.url }}
+{{ neutral.googlethreat }} +{{ neutral.virustotal }} +{{ neutral.phishtank }} +{{ neutral.urlscan }}
+{{ neutral.urlscreenshot }} + +
+ +{{ page.built }} + + + diff --git a/_layouts/scamdomain.html b/_layouts/scamdomain.html new file mode 100644 index 00000000..1cce1bfa --- /dev/null +++ b/_layouts/scamdomain.html @@ -0,0 +1,80 @@ + + + +
+

{{ scam.name }}

+
+ {{ scam.actions }} +
+
+{{ scam.notification }} +{{ scam.url }} +{{ scam.category }} +{{ scam.description }} +{{ scam.status }} +{{ scam.ip }}
+{{ scam.metamask }} +{{ scam.googlethreat }} +{{ scam.virustotal }} +{{ scam.phishtank }} +{{ scam.urlscan }}
+{{ scam.nameservers }}
+{{ scam.addresses }}
+{{ scam.urlscreenshot }} +

+ + + +
+ +{{ page.built }} + + + diff --git a/_layouts/search.html b/_layouts/search.html index 561b4faf..9a262474 100644 --- a/_layouts/search.html +++ b/_layouts/search.html @@ -29,7 +29,7 @@

Check URL / IP / ETH Address

Enter a URL, IP address, or ETH address to check whether you can trust it or not.

- +

Trusted domains

diff --git a/_layouts/verifieddomain.html b/_layouts/verifieddomain.html new file mode 100644 index 00000000..c047f6c3 --- /dev/null +++ b/_layouts/verifieddomain.html @@ -0,0 +1,30 @@ + +
+

{{ verified.name }}

+
+{{ verified.notification }} +{{ verified.url }} +{{ verified.description }}
+{{ verified.googlethreat }} +{{ verified.virustotal }} +{{ verified.phishtank }} +{{ verified.urlscan }}
+{{ verified.addresses }}
+{{ verified.urlscreenshot }} + +
+ +{{ page.built }} + + + diff --git a/_static/css/neutraldomain.css b/_static/css/neutraldomain.css new file mode 100644 index 00000000..78271275 --- /dev/null +++ b/_static/css/neutraldomain.css @@ -0,0 +1,54 @@ +.ui.bulleted.list { + margin-top: 4px; + margin-bottom: 0; +} + +.ui.grid { + margin-bottom: 0px; +} + +.ui.input { + width: 100%; +} + +#actions { + text-align: right; +} + +.class_offline { + color: green; +} + +.class_active { + color: red; +} + +.class_suspended { + color: orange; +} + +.class_inactive { + color: orange; +} + +#scam-screenshot { + filter: gray; + -webkit-filter: grayscale(1); + filter: grayscale(1); + width: 100%; + height: 100%; + border: 2px solid #000; +} +#scam-screenshot:hover { + cursor: -moz-zoom-in; + cursor: -webkit-zoom-in; + cursor: zoom-in; + -webkit-filter: grayscale(0); + filter: none; +} + +.built { + font-size: 8pt; + font-style: italic; + margin-top: 7%; +} diff --git a/_static/css/scam.css b/_static/css/scam.css index cef70f78..78271275 100644 --- a/_static/css/scam.css +++ b/_static/css/scam.css @@ -35,9 +35,8 @@ filter: gray; -webkit-filter: grayscale(1); filter: grayscale(1); - width: 450px; - height: 300px; - border-radius: 1em; + width: 100%; + height: 100%; border: 2px solid #000; } #scam-screenshot:hover { @@ -52,4 +51,4 @@ font-size: 8pt; font-style: italic; margin-top: 7%; -} \ No newline at end of file +} diff --git a/_static/css/verified.css b/_static/css/verified.css new file mode 100644 index 00000000..78271275 --- /dev/null +++ b/_static/css/verified.css @@ -0,0 +1,54 @@ +.ui.bulleted.list { + margin-top: 4px; + margin-bottom: 0; +} + +.ui.grid { + margin-bottom: 0px; +} + +.ui.input { + width: 100%; +} + +#actions { + text-align: right; +} + +.class_offline { + color: green; +} + +.class_active { + color: red; +} + +.class_suspended { + color: orange; +} + +.class_inactive { + color: orange; +} + +#scam-screenshot { + filter: gray; + -webkit-filter: grayscale(1); + filter: grayscale(1); + width: 100%; + height: 100%; + border: 2px solid #000; +} +#scam-screenshot:hover { + cursor: -moz-zoom-in; + cursor: -webkit-zoom-in; + cursor: zoom-in; + -webkit-filter: grayscale(0); + filter: none; +} + +.built { + font-size: 8pt; + font-style: italic; + margin-top: 7%; +} diff --git a/_static/img/ankr.png b/_static/img/ankr.png new file mode 100644 index 00000000..a38e6138 Binary files /dev/null and b/_static/img/ankr.png differ diff --git a/_static/img/binance.png b/_static/img/binance.png new file mode 100644 index 00000000..ef8ad688 Binary files /dev/null and b/_static/img/binance.png differ diff --git a/_static/img/bitfinex.png b/_static/img/bitfinex.png new file mode 100644 index 00000000..c005b5b5 Binary files /dev/null and b/_static/img/bitfinex.png differ diff --git a/_static/img/coinbase.png b/_static/img/coinbase.png new file mode 100644 index 00000000..98ad72a8 Binary files /dev/null and b/_static/img/coinbase.png differ diff --git a/_static/img/electrum.png b/_static/img/electrum.png new file mode 100644 index 00000000..6937eeb1 Binary files /dev/null and b/_static/img/electrum.png differ diff --git a/_static/img/exchange.png b/_static/img/exchange.png new file mode 100644 index 00000000..700b9881 Binary files /dev/null and b/_static/img/exchange.png differ diff --git a/_static/img/fantom.png b/_static/img/fantom.png new file mode 100644 index 00000000..4311af3c Binary files /dev/null and b/_static/img/fantom.png differ diff --git a/_static/img/forkdelta.png b/_static/img/forkdelta.png new file mode 100644 index 00000000..b90fa603 Binary files /dev/null and b/_static/img/forkdelta.png differ diff --git a/_static/img/hitbtc.png b/_static/img/hitbtc.png new file mode 100644 index 00000000..391d7135 Binary files /dev/null and b/_static/img/hitbtc.png differ diff --git a/_static/img/luno.png b/_static/img/luno.png new file mode 100644 index 00000000..7ee4f239 Binary files /dev/null and b/_static/img/luno.png differ diff --git a/_static/img/neo.png b/_static/img/neo.png new file mode 100644 index 00000000..af3a7ca8 Binary files /dev/null and b/_static/img/neo.png differ diff --git a/_static/img/odyssey.png b/_static/img/odyssey.png new file mode 100644 index 00000000..00ef33e7 Binary files /dev/null and b/_static/img/odyssey.png differ diff --git a/_static/img/orchid.png b/_static/img/orchid.png new file mode 100644 index 00000000..6f98e145 Binary files /dev/null and b/_static/img/orchid.png differ diff --git a/_static/img/telegram.png b/_static/img/telegram.png new file mode 100644 index 00000000..1b0cbf7c Binary files /dev/null and b/_static/img/telegram.png differ diff --git a/_static/img/texacon.png b/_static/img/texacon.png new file mode 100644 index 00000000..dbdcfca4 Binary files /dev/null and b/_static/img/texacon.png differ diff --git a/_static/img/tron.png b/_static/img/tron.png index e6a6c2fb..36751fc4 100644 Binary files a/_static/img/tron.png and b/_static/img/tron.png differ diff --git a/_static/img/trust-trading.png b/_static/img/trust-trading.png new file mode 100644 index 00000000..a84b1741 Binary files /dev/null and b/_static/img/trust-trading.png differ diff --git a/_static/img/vechain.png b/_static/img/vechain.png new file mode 100644 index 00000000..2c348e26 Binary files /dev/null and b/_static/img/vechain.png differ diff --git a/_static/img/yobit.png b/_static/img/yobit.png new file mode 100644 index 00000000..9099da07 Binary files /dev/null and b/_static/img/yobit.png differ diff --git a/_static/img/zeex.png b/_static/img/zeex.png new file mode 100644 index 00000000..204b50f9 Binary files /dev/null and b/_static/img/zeex.png differ diff --git a/_static/js/neutraldomain.js b/_static/js/neutraldomain.js new file mode 100644 index 00000000..63b8bc44 --- /dev/null +++ b/_static/js/neutraldomain.js @@ -0,0 +1,22 @@ +window.addEventListener("load", function() { + $("#shr").val(location.href); + $("#gen").click(function() { + $('#abusemodal').modal('show'); + }); + $("#history").click(function() { + $('#historymodal').modal('show'); + }); + $("#share").click(function() { + $('#sharemodal').modal('show'); + }); +}); + +function copyshr() { + document.getElementById("shr").select(); + document.execCommand("copy"); +} + +function copyabuse() { + document.getElementById("abuse").select(); + document.execCommand("copy"); +} \ No newline at end of file diff --git a/_static/js/search.js b/_static/js/search.js index 5eece5b4..78f2c12e 100644 --- a/_static/js/search.js +++ b/_static/js/search.js @@ -11,13 +11,16 @@ window.addEventListener("load", function() { $.getJSON("/api/check/" + encodeURIComponent($("input").val().toLowerCase().replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0]), function(result) { if (result.result == 'verified') { hideEverything(); + var strLink = ''; $("#verifiedmessage").html(encodeURI($("input").val().toLowerCase().replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0]) + ' is a verified domain. You can trust the contents.'); - $("#verifiedmessage").html($("#verifiedmessage").html()); + strLink = 'Details on this domain '; + $("#verifiedmessage").html($("#verifiedmessage").html() + ' ' + strLink); $("#verified").css('display', 'flex'); } else if (result.result == 'neutral') { hideEverything(); $("#neutralmessage").html(encodeURI($("input").val().toLowerCase().replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0]) + ' wasn\'t recognized as a malicious domain, nor as verified domain. Be careful!'); - $("#neutralmessage").html($("#neutralmessage").html()); + strLink = 'Details on this domain '; + $("#neutralmessage").html($("#neutralmessage").html() + ' ' + strLink); $("#neutral").css('display', 'flex'); } else if (result.result == 'whitelisted') { hideEverything(); @@ -32,13 +35,13 @@ window.addEventListener("load", function() { var strLink = ''; if (result.type == 'domain' && 'category' in result.entries[0]) { $("#blacklistmessage").html(encodeURI($("input").val().toLowerCase().replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0]) + ' was put on the blacklist for ' + result.entries[0].category.toLowerCase() + '.'); - strLink = 'Details '; + strLink = 'Details on this domain '; } else if(result.type == 'address') { $("#blacklistmessage").html(encodeURI($("input").val().toLowerCase()) + ' was put on the blacklist and is associated with '+ result.entries.length +' blocked domain(s).'); strLink = 'Details on this address '; } else if(result.type == 'ip') { $("#blacklistmessage").html(encodeURI($("input").val().toLowerCase().replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0]) + ' was put on the blacklist and is associated with '+ result.entries.length +' blocked domain(s)'); - strLink = 'Details '; + strLink = 'Details on this domain '; } $("#blacklistmessage").html($("#blacklistmessage").html() + ' ' + strLink); $("#blocked").css('display', 'flex'); diff --git a/_static/js/verified.js b/_static/js/verified.js new file mode 100644 index 00000000..63b8bc44 --- /dev/null +++ b/_static/js/verified.js @@ -0,0 +1,22 @@ +window.addEventListener("load", function() { + $("#shr").val(location.href); + $("#gen").click(function() { + $('#abusemodal').modal('show'); + }); + $("#history").click(function() { + $('#historymodal').modal('show'); + }); + $("#share").click(function() { + $('#sharemodal').modal('show'); + }); +}); + +function copyshr() { + document.getElementById("shr").select(); + document.execCommand("copy"); +} + +function copyabuse() { + document.getElementById("abuse").select(); + document.execCommand("copy"); +} \ No newline at end of file diff --git a/_utils/lookup.js b/_utils/lookup.js new file mode 100644 index 00000000..d2c5b487 --- /dev/null +++ b/_utils/lookup.js @@ -0,0 +1,18 @@ +const request = require('request') + +class weblookup { + lookup (input) { + return new Promise(function(resolve, reject) { + var result = request(input, + {timeout: 30*1000}, function(e, response, body) { + if(e || !([200, 301, 302].includes(response.statusCode))) { + resolve(e) + } + else if(!e && response.statusCode == 200){ + resolve(JSON.parse(body)) + } + }); + }); + } +} +module.exports = weblookup diff --git a/_utils/webcheck.js b/_utils/webcheck.js new file mode 100644 index 00000000..7de9fc72 --- /dev/null +++ b/_utils/webcheck.js @@ -0,0 +1,18 @@ +const request = require('request') + +class web { + lookup (input) { + return new Promise(function(resolve, reject) { + var result = request('https://urlscan.io/api/v1/search/?q=domain%3A' + input, + {timeout: 30*1000}, function(e, response, body) { + if(e || !([200, 301, 302].includes(response.statusCode))) { + resolve(e) + } + else if(!e && response.statusCode == 200){ + resolve(JSON.parse(body)) + } + }); + }); + } +} +module.exports = web diff --git a/config.example.js b/config.example.js index ad0fd01c..8b16ccd9 100644 --- a/config.example.js +++ b/config.example.js @@ -3,6 +3,7 @@ module.exports = { "cache_refreshing_interval": 1000 * 60 * 30, "Google_SafeBrowsing_API_Key": null, "Github_Hook_Secret": null, + "VirusTotal_API_Key": null, "Urlscan_API_Key": null, "AbuseIPDB_API_Key": null, "repository": { diff --git a/run.js b/run.js index 30b18e39..30cd692f 100644 --- a/run.js +++ b/run.js @@ -1,6 +1,7 @@ 'use strict'; const fs = require('fs-extra'); + const express = require('express'); const bodyParser = require('body-parser'); const url = require('url'); @@ -13,6 +14,9 @@ const crypto = require("crypto"); const request = require('request'); const app = express(); const config = require('./config'); +const check = require('./_utils/webcheck.js'); +const lookup = require('./_utils/lookup.js'); + const default_template = fs.readFileSync('./_layouts/default.html', 'utf8'); let cache; @@ -300,7 +304,7 @@ function startWebServer() { if (scams[i].name.length > 40) { scams[i].name = scams[i].name.substring(0, 40) + '...'; } - table += "" + category + "" + subcategory + "" + status + "" + scams[i].name + ""; + table += "" + category + "" + subcategory + "" + status + "" + scams[i].name + ""; } template = template.replace("{{ scams.table }}", table); @@ -480,6 +484,473 @@ function startWebServer() { } }); + app.get('/domain/:domain/', function(req, res) { // Serve /domain// + var whitelistImports; + var blacklistImports; + var fuzzylistImports; + var toleranceImports; + let domainpage = encodeURIComponent(req.params.domain.replace("www.","").split(/[/?#]/)[0].toLowerCase()); + + if(/^([0-9a-z\.\-]+)$/.exec(domainpage) === null) { + let template = fs.readFileSync('./_layouts/404.html', 'utf8'); + res.send(default_template.replace('{{ content }}', template)); + return; + } + + var webcheck = new check(); + var urllookup = new lookup(); + let startTime = (new Date()).getTime(); + + let scam = getCache().scams.find(function(scam) { + return scam.name == domainpage; + }); + + let verified = getCache().legiturls.find(function(verified) { + return verified.url.replace("https://", '') == domainpage; + }); + + // NEUTRAL DOMAIN PAGES + if(typeof scam === "undefined" && typeof verified === "undefined") { + let template = fs.readFileSync('./_layouts/neutraldomain.html', 'utf8'); + template = template.replace("{{ neutral.name }}", domainpage); + template = template.replace("{{ neutral.url }}", 'URL: ' + "http://" + domainpage + '
'); + template = template.replace("{{ neutral.notification }}", '
This domain has not yet been classified on EtherScamDB
') + template = template.replace("{{ neutral.googlethreat }}", "Google Safe Browsing Status: {{ neutral.googlethreat }}
"); + template = template.replace("{{ neutral.virustotal }}", "VirusTotal Detections: {{ neutral.virustotal }}
"); + template = template.replace("{{ neutral.phishtank }}", "Phishtank Detected: {{ neutral.phishtank }}
"); + template = template.replace("{{ neutral.urlscan }}", "Urlscan Scan Results: {{ neutral.urlscan }}
"); + template = template.replace("{{ neutral.urlscreenshot }}", "Urlscan Screenshot:
{{ neutral.urlscreenshot }}
"); + webcheck.lookup( domainpage ).then(function(output) { + if(output.total == 0){ + template = template.replace("{{ neutral.urlscan }}", " Not Yet"); + template = template.replace("{{ neutral.urlscreenshot }}", " Screenshot could not be displayed"); + res.send(default_template.replace('{{ content }}', template)); + } else if(output.total != 0){ + var interval = 0; + var index = 0; + for(interval; interval < output.total; interval++){ + if(url.parse(output.results[interval].task.url).hostname.replace('www.','') == domainpage){ + index = interval; + break; + } else if(interval == 99){ + template = template.replace("{{ neutral.urlscan }}", " Link could not be found") + template = template.replace("{{ neutral.urlscanlink }}", ""); + template = template.replace("{{ neutral.urlscreenshot }}", " Screenshot could not be displayed"); + res.send(default_template.replace('{{ content }}', template)); + return; + } + } + template = template.replace("{{ neutral.urlscan }}", "Link"); + template = template.replace("{{ neutral.urlscanlink }}", 'https://urlscan.io/result/' + output.results[index]._id); + urllookup.lookup( output.results[index].result ).then(function(lookupout) { + if(lookupout.data != null){ + template = template.replace("{{ neutral.urlscreenshot }}", "
Screenshot of website
"); + res.send(default_template.replace('{{ content }}', template)); + } else{ + template = template.replace("{{ neutral.urlscreenshot }}", " Screenshot could not be displayed"); + } + }) + } + }); + + if ('Google_SafeBrowsing_API_Key' in config && config.Google_SafeBrowsing_API_Key && domainpage != 'undefined') { + var options = { + uri: 'https://safebrowsing.googleapis.com/v4/threatMatches:find?key=' + config.Google_SafeBrowsing_API_Key, + method: 'POST', + json: { + client: { + clientId: "Ethereum Scam Database", + clientVersion: "1.0.0" + }, + threatInfo: { + threatTypes: ["THREAT_TYPE_UNSPECIFIED", "MALWARE", "SOCIAL_ENGINEERING", "UNWANTED_SOFTWARE", "POTENTIALLY_HARMFUL_APPLICATION"], + platformTypes: ["ANY_PLATFORM"], + threatEntryTypes: ["THREAT_ENTRY_TYPE_UNSPECIFIED", "URL", "EXECUTABLE"], + threatEntries: [{ + "url": domainpage + }] + } + } + }; + request(options, function(error, response, body) { + if (!error && response.statusCode == 200) { + if ('matches' in body && 0 in body.matches) { + template = template.replace("{{ neutral.googlethreat }}", "Blocked for " + body.matches[0]['threatType'] + ''); + } else { + template = template.replace("{{ neutral.googlethreat }}", "Not Blocked "); + } + } else { + template = template.replace("{{ neutral.googlethreat }}", " Could not pull data from Google SafeBrowsing"); + } + }); + } else { + template = template.replace("{{ neutral.googlethreat }}", " Could not pull data from Google SafeBrowsing"); + console.log("Warning: No Google Safe Browsing API key found"); + } + if ('VirusTotal_API_Key' in config && config.VirusTotal_API_Key && domainpage != 'undefined') { + var options = { + uri: 'https://www.virustotal.com/vtapi/v2/url/report?apikey=' + config.VirusTotal_API_Key + '&resource=http://' + domainpage, + method: 'GET', + }; + request(options, function(error, response, body) { + if (!error && response.statusCode == 200) { + body = JSON.parse(body); + if(body.response_code != 0){ + if (body.positives == 0) { + template = template.replace("{{ neutral.virustotal }}", " " + body.positives + ' / ' + body.total + ''); + } else { + template = template.replace("{{ neutral.virustotal }}", " " + body.positives + ' / ' + body.total + " "); + } + if (body.scans.Phishtank.result == "clean site"){ + template = template.replace("{{ neutral.phishtank }}", " " + "Clean Site" + ''); + } else if(body.scans.Phishtank.result == "phishing site"){ + template = template.replace("{{ neutral.phishtank }}", " " + "Phishing Site"+ ''); + } else{ + template = template.replace("{{ neutral.phishtank }}", " " + body.scans.Phishtank.result + ''); + } + } else{ + template = template.replace("{{ neutral.virustotal }}", " Could not pull data from VirusTotal"); + template = template.replace("{{ neutral.phishtank }}", " Could not pull data from Phishtank"); + } + } else { + template = template.replace("{{ neutral.virustotal }}", " Could not pull data from VirusTotal"); + template = template.replace("{{ neutral.phishtank }}", " Could not pull data from Phishtank"); + } + template = template.replace("{{ page.built }}", '

This page was built in ' + ((new Date()).getTime() - startTime) + 'ms, and last updated at ' + dateFormat(getCache().updated, "UTC:mmm dd yyyy, HH:MM") + ' UTC

'); + }); + } else { + template = template.replace("{{ neutral.virustotal }}", " Could not pull data from VirusTotal"); + template = template.replace("{{ neutral.phishtank }}", " Could not pull data from Phishtank"); + template = template.replace("{{ page.built }}", '

This page was built in ' + ((new Date()).getTime() - startTime) + 'ms, and last updated at ' + dateFormat(getCache().updated, "UTC:mmm dd yyyy, HH:MM") + ' UTC

'); + console.log("Warning: No VirusTotal API key found"); + } + } + + // VERIFIED DOMAIN PAGES + if(typeof verified != "undefined"){ + let template = fs.readFileSync('./_layouts/verifieddomain.html', 'utf8'); + template = template.replace("{{ verified.name }}", verified.name); + template = template.replace("{{ verified.notification }}", '
This is a verified domain.
') + template = template.replace("{{ verified.googlethreat }}", "Google Safe Browsing Status: {{ verified.googlethreat }}
"); + template = template.replace("{{ verified.virustotal }}", "VirusTotal Detections: {{ verified.virustotal }}
"); + template = template.replace("{{ verified.phishtank }}", "Phishtank Detected: {{ verified.phishtank }}
"); + template = template.replace("{{ verified.urlscan }}", "Urlscan Scan Results: {{ verified.urlscan }}
"); + template = template.replace("{{ verified.urlscreenshot }}", "Urlscan Screenshot:
{{ verified.urlscreenshot }}
"); + webcheck.lookup( url.parse(verified.url).hostname ).then(function(output) { + if(output.total == 0){ + template = template.replace("{{ verified.urlscan }}", "Not Yet"); + res.send(default_template.replace('{{ content }}', template)); + } else if(output.total != 0){ + var interval = 0; + var index = 0; + for(interval; interval < output.total; interval++){ + if(url.parse(output.results[interval].task.url).hostname.replace('www.','') == url.parse(verified.url).hostname){ + index = interval; + break; + } else if(interval == 99){ + index = 0; + template = template.replace("{{ verified.urlscan }}", " Link could not be found") + template = template.replace("{{ verified.urlscanlink }}", ""); + template = template.replace("{{ verified.urlscreenshot }}", " Screenshot could not be displayed"); + res.send(default_template.replace('{{ content }}', template)); + return; + } + } + template = template.replace("{{ verified.urlscan }}", "Link"); + template = template.replace("{{ verified.urlscanlink }}", 'https://urlscan.io/result/' + output.results[index]._id); + urllookup.lookup( output.results[index].result ).then(function(lookupout) { + if(lookupout.data != null){ + template = template.replace("{{ verified.urlscreenshot }}", "
Screenshot of website
"); + res.send(default_template.replace('{{ content }}', template)); + } else{ + template = template.replace("{{ verified.urlscreenshot }}", " Screenshot could not be displayed"); + } + }) + } + }); + + if ('description' in verified) { + template = template.replace("{{ verified.description }}", 'Description: ' + verified.description + '
'); + } else { + template = template.replace("{{ verified.description }}", ''); + } + if ('addresses' in verified) { + var addresses_text = ''; + verified.addresses.forEach(function(address) { + addresses_text += '
' + address + '
'; + }); + template = template.replace("{{ verified.addresses }}", 'Related addresses:
' + addresses_text + '
'); + } else { + template = template.replace("{{ verified.addresses }}", ''); + } + if ('url' in verified) { + template = template.replace("{{ verified.url }}", 'URL: ' + verified.url + '
'); + } else { + template = template.replace("{{ verified.url }}", ''); + } + if ('Google_SafeBrowsing_API_Key' in config && config.Google_SafeBrowsing_API_Key && domainpage != 'undefined') { + var options = { + uri: 'https://safebrowsing.googleapis.com/v4/threatMatches:find?key=' + config.Google_SafeBrowsing_API_Key, + method: 'POST', + json: { + client: { + clientId: "Ethereum Scam Database", + clientVersion: "1.0.0" + }, + threatInfo: { + threatTypes: ["THREAT_TYPE_UNSPECIFIED", "MALWARE", "SOCIAL_ENGINEERING", "UNWANTED_SOFTWARE", "POTENTIALLY_HARMFUL_APPLICATION"], + platformTypes: ["ANY_PLATFORM"], + threatEntryTypes: ["THREAT_ENTRY_TYPE_UNSPECIFIED", "URL", "EXECUTABLE"], + threatEntries: [{ + "url": domainpage + }] + } + } + }; + request(options, function(error, response, body) { + if (!error && response.statusCode == 200) { + if ('matches' in body && 0 in body.matches) { + template = template.replace("{{ verified.googlethreat }}", " Blocked for " + body.matches[0]['threatType'] + ''); + } else { + template = template.replace("{{ verified.googlethreat }}", " Not Blocked "); + } + } else { + template = template.replace("{{ verified.googlethreat }}", " Could not pull data from Google SafeBrowsing"); + } + }); + } else { + template = template.replace("{{ verified.googlethreat }}", " Could not pull data from Google SafeBrowsing"); + console.log("Warning: No Google Safe Browsing API key found"); + } + + if ('VirusTotal_API_Key' in config && config.VirusTotal_API_Key && domainpage != 'undefined') { + var options = { + uri: 'https://www.virustotal.com/vtapi/v2/url/report?apikey=' + config.VirusTotal_API_Key + '&resource=http://' + domainpage, + method: 'GET', + }; + request(options, function(error, response, body) { + if (!error && response.statusCode == 200) { + body = JSON.parse(body); + if(body.response_code != 0){ + if (body.positives == 0) { + template = template.replace("{{ verified.virustotal }}", " " + body.positives + ' / ' + body.total + ''); + } else { + template = template.replace("{{ verified.virustotal }}", " " + body.positives + ' / ' + body.total + " "); + } + if (body.scans.Phishtank.result == "clean site"){ + template = template.replace("{{ verified.phishtank }}", " " + "Clean Site" + ''); + } else if(body.scans.Phishtank.result == "phishing site"){ + template = template.replace("{{ verified.phishtank }}", " " + "Phishing Site"+ ''); + } else{ + template = template.replace("{{ verified.phishtank }}", " " + body.scans.Phishtank.result + ''); + } + } else{ + template = template.replace("{{ verified.virustotal }}", " Could not pull data from VirusTotal"); + template = template.replace("{{ verified.phishtank }}", " Could not pull data from Phishtank"); + } + } else { + template = template.replace("{{ verified.virustotal }}", " Could not pull data from VirusTotal"); + template = template.replace("{{ verified.phishtank }}", " Could not pull data from Phishtank"); + } + template = template.replace("{{ page.built }}", '

This page was built in ' + ((new Date()).getTime() - startTime) + 'ms, and last updated at ' + dateFormat(getCache().updated, "UTC:mmm dd yyyy, HH:MM") + ' UTC

'); + }); + } else { + template = template.replace("{{ verified.virustotal }}", " Could not pull data from VirusTotal"); + template = template.replace("{{ verified.phishtank }}", " Could not pull data from Phishtank"); + template = template.replace("{{ page.built }}", '

This page was built in ' + ((new Date()).getTime() - startTime) + 'ms, and last updated at ' + dateFormat(getCache().updated, "UTC:mmm dd yyyy, HH:MM") + ' UTC

'); + } + } + + // SCAM DOMAIN PAGES + if(typeof scam != "undefined"){ + let template = fs.readFileSync('./_layouts/scamdomain.html', 'utf8'); + var actions_text = ""; + template = template.replace("{{ scam.id }}", scam.id); + template = template.replace("{{ scam.name }}", scam.name); + template = template.replace("{{ scam.notification }}", '
Warning: This is a scam domain.
') + template = template.replace("{{ scam.googlethreat }}", "Google Safe Browsing Status: {{ scam.googlethreat }}
"); + template = template.replace("{{ scam.virustotal }}", "VirusTotal Detections: {{ scam.virustotal }}
"); + template = template.replace("{{ scam.phishtank }}", "Phishtank Detected: {{ scam.phishtank }}
"); + template = template.replace("{{ scam.urlscan }}", "Urlscan Scan Results: {{ scam.urlscan }}
"); + template = template.replace("{{ scam.urlscreenshot }}", "Urlscan Screenshot:
{{ scam.urlscreenshot }}
"); + webcheck.lookup( url.parse(scam.url).hostname ).then(function(output) { + if(output.total == 0){ + template = template.replace("{{ scam.urlscan }}", "Not Yet"); + res.send(default_template.replace('{{ content }}', template)); + } else if(output.total != 0){ + var interval = 0; + var index = 0; + for(interval; interval < output.total; interval++){ + if(url.parse(output.results[interval].task.url).hostname.replace('www.','') == url.parse(scam.url).hostname){ + index = interval; + break; + } else if(interval == 99){ + index = 0; + template = template.replace("{{ scam.urlscan }}", " Link could not be found") + template = template.replace("{{ scam.urlscanlink }}", ""); + template = template.replace("{{ scam.urlscreenshot }}", " Screenshot could not be displayed"); + res.send(default_template.replace('{{ content }}', template)); + return; + } + } + template = template.replace("{{ scam.urlscan }}", "Link"); + template = template.replace("{{ scam.urlscanlink }}", 'https://urlscan.io/result/' + output.results[index]._id); + urllookup.lookup( output.results[index].result ).then(function(lookupout) { + if(lookupout.data != null){ + template = template.replace("{{ scam.urlscreenshot }}", "
Screenshot of website
"); + res.send(default_template.replace('{{ content }}', template)); + } else{ + template = template.replace("{{ scam.urlscreenshot }}", " Screenshot could not be displayed"); + } + }) + } + }) + + if ('category' in scam) { + if ('subcategory' in scam) { + template = template.replace("{{ scam.category }}", 'Category: ' + scam.category + ' - ' + scam.subcategory + '
'); + } else { + template = template.replace("{{ scam.category }}", 'Category: ' + scam.category + '
'); + } + } else { + template = template.replace("{{ scam." + name + " }}", ''); + } + if ('status' in scam) { + template = template.replace("{{ scam.status }}", 'Status: ' + scam.status + '
'); + } else { + template = template.replace("{{ scam.status }}", ''); + } + if ('description' in scam) { + template = template.replace("{{ scam.description }}", 'Description: ' + scam.description + '
'); + } else { + template = template.replace("{{ scam.description }}", ''); + } + if ('nameservers' in scam) { + var nameservers_text = ''; + scam.nameservers.forEach(function(nameserver) { + nameservers_text += '
' + nameserver + '
'; + }); + template = template.replace("{{ scam.nameservers }}", 'Nameservers:
' + nameservers_text + '
'); + } else { + template = template.replace("{{ scam.nameservers }}", ''); + } + if ('addresses' in scam) { + var addresses_text = ''; + scam.addresses.forEach(function(address) { + addresses_text += '
' + address + '
'; + }); + template = template.replace("{{ scam.addresses }}", 'Related addresses:
' + addresses_text + '
'); + } else { + template = template.replace("{{ scam.addresses }}", ''); + } + if ('ip' in scam) { + template = template.replace("{{ scam.ip }}", 'IP: ' + scam.ip + '
'); + } else { + template = template.replace("{{ scam.ip }}", ''); + } + if ('url' in scam) { + template = template.replace("{{ scam.abusereport }}", generateAbuseReport(scam)); + actions_text += ''; + actions_text += ' Archive'; + template = template.replace("{{ scam.url }}", 'URL: ' + scam.url + '
'); + /* Parses data for Metamask*/ + if (fs.existsSync('./_data/metamaskImports.json')) { + try { + var importsData = require('./_data/metamaskImports.json') + const detector = new phishingDetector(importsData); + template = template.replace("{{ scam.metamask }}", "MetaMask Status: " + (detector.check(url.parse(scam.url).hostname).result ? "Blocked" : "Not Yet Blocked") + "
"); + } catch (e) { + console.log(e); + } + } else{ + console.log('MetaMask JSON not found'); + }; + if ('status' in scam && scam.status != 'Offline' && fs.existsSync('_cache/screenshots/' + scam.id + '.png')) { + template = template.replace("{{ scam.screenshot }}", '

Screenshot

'); + } else { + template = template.replace("{{ scam.screenshot }}", ''); + } + } else { + template = template.replace("{{ scam.googlethreat }}", ''); + template = template.replace("{{ scam.screenshot }}", ''); + } + actions_text += ' Improve'; + template = template.replace("{{ scam.actions }}", '
' + actions_text + '
'); + if ('Google_SafeBrowsing_API_Key' in config && config.Google_SafeBrowsing_API_Key && 'url' in scam) { + var options = { + uri: 'https://safebrowsing.googleapis.com/v4/threatMatches:find?key=' + config.Google_SafeBrowsing_API_Key, + method: 'POST', + json: { + client: { + clientId: "Ethereum Scam Database", + clientVersion: "1.0.0" + }, + threatInfo: { + threatTypes: ["THREAT_TYPE_UNSPECIFIED", "MALWARE", "SOCIAL_ENGINEERING", "UNWANTED_SOFTWARE", "POTENTIALLY_HARMFUL_APPLICATION"], + platformTypes: ["ANY_PLATFORM"], + threatEntryTypes: ["THREAT_ENTRY_TYPE_UNSPECIFIED", "URL", "EXECUTABLE"], + threatEntries: [{ + "url": url.parse(scam.url).hostname + }] + } + } + }; + request(options, function(error, response, body) { + if (!error && response.statusCode == 200) { + if ('matches' in body && 0 in body.matches) { + template = template.replace("{{ scam.googlethreat }}", " Blocked for " + body.matches[0]['threatType'] + ''); + } else { + template = template.replace("{{ scam.googlethreat }}", " Not Blocked Yet "); + } + } else { + template = template.replace("{{ scam.googlethreat }}", " Could not pull data from Google SafeBrowsing"); + } + }); + } else { + template = template.replace("{{ scam.googlethreat }}", " Could not pull data from Google SafeBrowsing"); + console.log("Warning: No Google Safe Browsing API key found"); + } + if ('VirusTotal_API_Key' in config && config.VirusTotal_API_Key && domainpage != 'undefined') { + var options = { + uri: 'https://www.virustotal.com/vtapi/v2/url/report?apikey=' + config.VirusTotal_API_Key + '&resource=http://' + domainpage, + method: 'GET', + }; + request(options, function(error, response, body) { + if (!error && response.statusCode == 200) { + body = JSON.parse(body); + if(body.response_code != 0){ + if (body.positives == 0) { + template = template.replace("{{ scam.virustotal }}", " " + body.positives + ' / ' + body.total + ''); + } else { + template = template.replace("{{ scam.virustotal }}", " " + body.positives + ' / ' + body.total + " "); + } + if (body.scans.Phishtank.result == "clean site"){ + template = template.replace("{{ scam.phishtank }}", " " + "Clean Site" + ''); + } else if(body.scans.Phishtank.result == "phishing site"){ + template = template.replace("{{ scam.phishtank }}", " " + "Phishing Site"+ ''); + } else{ + template = template.replace("{{ scam.phishtank }}", " " + body.scans.Phishtank.result + ''); + } + } else{ + template = template.replace("{{ scam.virustotal }}", " Could not pull data from VirusTotal"); + template = template.replace("{{ scam.phishtank }}", " Could not pull data from Phishtank"); + } + } else { + template = template.replace("{{ scam.virustotal }}", " Could not pull data from VirusTotal"); + template = template.replace("{{ scam.phishtank }}", " Could not pull data from Phishtank"); + } + template = template.replace("{{ page.built }}", '

This page was built in ' + ((new Date()).getTime() - startTime) + 'ms, and last updated at ' + dateFormat(getCache().updated, "UTC:mmm dd yyyy, HH:MM") + ' UTC

'); + }); + } else { + template = template.replace("{{ scam.virustotal }}", " Could not pull data from VirusTotal"); + template = template.replace("{{ scam.phishtank }}", " Could not pull data from Phishtank"); + template = template.replace("{{ page.built }}", '

This page was built in ' + ((new Date()).getTime() - startTime) + 'ms, and last updated at ' + dateFormat(getCache().updated, "UTC:mmm dd yyyy, HH:MM") + ' UTC

'); + console.log("Warning: No VirusTotal API key found"); + } + } + + }); + app.get('/ip/:ip/', function(req, res) { // Serve /ip// let template = fs.readFileSync('./_layouts/ip.html', 'utf8'); template = template.replace("{{ ip.ip }}", req.params.ip);