diff options
Diffstat (limited to 'app/scripts')
-rw-r--r-- | app/scripts/background.js | 26 | ||||
-rw-r--r-- | app/scripts/blacklister.js | 45 | ||||
-rw-r--r-- | app/scripts/controllers/infura.js | 14 | ||||
-rw-r--r-- | app/scripts/inpage.js | 1 | ||||
-rw-r--r-- | app/scripts/lib/is-phish.js | 38 |
5 files changed, 88 insertions, 36 deletions
diff --git a/app/scripts/background.js b/app/scripts/background.js index e8987394f..bc0fbdc37 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -11,6 +11,7 @@ const NotificationManager = require('./lib/notification-manager.js') const MetamaskController = require('./metamask-controller') const extension = require('extensionizer') const firstTimeState = require('./first-time-state') +const isPhish = require('./lib/is-phish') const STORAGE_KEY = 'metamask-config' const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' @@ -90,6 +91,10 @@ function setupController (initState) { extension.runtime.onConnect.addListener(connectRemote) function connectRemote (remotePort) { + if (remotePort.name === 'blacklister') { + return checkBlacklist(remotePort) + } + var isMetaMaskInternalProcess = remotePort.name === 'popup' || remotePort.name === 'notification' var portStream = new PortStream(remotePort) if (isMetaMaskInternalProcess) { @@ -135,6 +140,27 @@ function setupController (initState) { return Promise.resolve() } +// Listen for new pages and return if blacklisted: +function checkBlacklist (port) { + const handler = handleNewPageLoad.bind(null, port) + port.onMessage.addListener(handler) + setTimeout(() => { + port.onMessage.removeListener(handler) + }, 30000) +} + +function handleNewPageLoad (port, message) { + const { pageLoaded } = message + if (!pageLoaded || !global.metamaskController) return + + const state = global.metamaskController.getState() + const updatedBlacklist = state.blacklist + + if (isPhish({ updatedBlacklist, hostname: pageLoaded })) { + port.postMessage({ 'blacklist': pageLoaded }) + } +} + // // Etc... // diff --git a/app/scripts/blacklister.js b/app/scripts/blacklister.js index 9337599cc..37751b595 100644 --- a/app/scripts/blacklister.js +++ b/app/scripts/blacklister.js @@ -1,41 +1,14 @@ -const levenshtein = require('fast-levenshtein')
-const blacklistedMetaMaskDomains = ['metamask.com']
-const blacklistedDomains = require('etheraddresslookup/blacklists/domains.json').concat(blacklistedMetaMaskDomains)
-const whitelistedMetaMaskDomains = ['metamask.io', 'www.metamask.io']
-const whitelistedDomains = require('etheraddresslookup/whitelists/domains.json').concat(whitelistedMetaMaskDomains)
-const LEVENSHTEIN_TOLERANCE = 4
-const LEVENSHTEIN_CHECKS = ['myetherwallet', 'myetheroll', 'ledgerwallet', 'metamask']
+const extension = require('extensionizer')
+var port = extension.runtime.connect({name: 'blacklister'})
+port.postMessage({ 'pageLoaded': window.location.hostname })
+port.onMessage.addListener(redirectIfBlacklisted)
-// credit to @sogoiii and @409H for their help!
-// Return a boolean on whether or not a phish is detected.
-function isPhish(hostname) {
- var strCurrentTab = hostname
-
- // check if the domain is part of the whitelist.
- if (whitelistedDomains && whitelistedDomains.includes(strCurrentTab)) { return false }
-
- // check if the domain is part of the blacklist.
- var isBlacklisted = blacklistedDomains && blacklistedDomains.includes(strCurrentTab)
-
- // check for similar values.
- var levenshteinMatched = false
- var levenshteinForm = strCurrentTab.replace(/\./g, '')
- LEVENSHTEIN_CHECKS.forEach((element) => {
- if (levenshtein.get(element, levenshteinForm) < LEVENSHTEIN_TOLERANCE) {
- levenshteinMatched = true
- }
- })
-
- return isBlacklisted || levenshteinMatched
-}
-
-window.addEventListener('load', function () {
- var hostnameToCheck = window.location.hostname
- if (isPhish(hostnameToCheck)) {
- // redirect to our phishing warning page.
+function redirectIfBlacklisted (response) {
+ const { blacklist } = response
+ const host = window.location.hostname
+ if (blacklist && blacklist === host) {
window.location.href = 'https://metamask.io/phishing.html'
}
-})
+}
-module.exports = isPhish
diff --git a/app/scripts/controllers/infura.js b/app/scripts/controllers/infura.js index b34b0bc03..97b2ab7e3 100644 --- a/app/scripts/controllers/infura.js +++ b/app/scripts/controllers/infura.js @@ -1,5 +1,6 @@ const ObservableStore = require('obs-store') const extend = require('xtend') +const recentBlacklist = require('etheraddresslookup/blacklists/domains.json') // every ten minutes const POLLING_INTERVAL = 300000 @@ -9,6 +10,7 @@ class InfuraController { constructor (opts = {}) { const initState = extend({ infuraNetworkStatus: {}, + blacklist: recentBlacklist, }, opts.initState) this.store = new ObservableStore(initState) } @@ -30,12 +32,24 @@ class InfuraController { }) } + updateLocalBlacklist () { + return fetch('https://api.infura.io/v1/blacklist') + .then(response => response.json()) + .then((parsedResponse) => { + this.store.updateState({ + blacklist: parsedResponse, + }) + return parsedResponse + }) + } + scheduleInfuraNetworkCheck () { if (this.conversionInterval) { clearInterval(this.conversionInterval) } this.conversionInterval = setInterval(() => { this.checkInfuraNetworkStatus() + this.updateLocalBlacklist() }, POLLING_INTERVAL) } } diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index ec764535e..9e98c044b 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -65,3 +65,4 @@ function restoreContextAfterImports () { console.warn('MetaMask - global.define could not be overwritten.') } } + diff --git a/app/scripts/lib/is-phish.js b/app/scripts/lib/is-phish.js new file mode 100644 index 000000000..68c09e4ac --- /dev/null +++ b/app/scripts/lib/is-phish.js @@ -0,0 +1,38 @@ +const levenshtein = require('fast-levenshtein') +const blacklistedMetaMaskDomains = ['metamask.com'] +let blacklistedDomains = require('etheraddresslookup/blacklists/domains.json').concat(blacklistedMetaMaskDomains) +const whitelistedMetaMaskDomains = ['metamask.io', 'www.metamask.io'] +const whitelistedDomains = require('etheraddresslookup/whitelists/domains.json').concat(whitelistedMetaMaskDomains) +const LEVENSHTEIN_TOLERANCE = 4 +const LEVENSHTEIN_CHECKS = ['myetherwallet', 'myetheroll', 'ledgerwallet', 'metamask'] + + +// credit to @sogoiii and @409H for their help! +// Return a boolean on whether or not a phish is detected. +function isPhish({ hostname, updatedBlacklist = null }) { + var strCurrentTab = hostname + + // check if the domain is part of the whitelist. + if (whitelistedDomains && whitelistedDomains.includes(strCurrentTab)) { return false } + + // Allow updating of blacklist: + if (updatedBlacklist) { + blacklistedDomains = blacklistedDomains.concat(updatedBlacklist) + } + + // check if the domain is part of the blacklist. + const isBlacklisted = blacklistedDomains && blacklistedDomains.includes(strCurrentTab) + + // check for similar values. + let levenshteinMatched = false + var levenshteinForm = strCurrentTab.replace(/\./g, '') + LEVENSHTEIN_CHECKS.forEach((element) => { + if (levenshtein.get(element, levenshteinForm) <= LEVENSHTEIN_TOLERANCE) { + levenshteinMatched = true + } + }) + + return isBlacklisted || levenshteinMatched +} + +module.exports = isPhish |