Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit b67bcf2
Showing
6 changed files
with
468 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
|
||
# Created by https://www.gitignore.io/api/osx,node | ||
|
||
### Node ### | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
*.pid.lock | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Bower dependency directory (https://bower.io/) | ||
bower_components | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (http://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules/ | ||
jspm_packages/ | ||
|
||
# Typescript v1 declaration files | ||
typings/ | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional eslint cache | ||
.eslintcache | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# Output of 'npm pack' | ||
*.tgz | ||
|
||
# Yarn Integrity file | ||
.yarn-integrity | ||
|
||
# dotenv environment variables file | ||
.env | ||
|
||
|
||
### OSX ### | ||
*.DS_Store | ||
.AppleDouble | ||
.LSOverride | ||
|
||
# Icon must end with two \r | ||
Icon | ||
|
||
# Thumbnails | ||
._* | ||
|
||
# Files that might appear in the root of a volume | ||
.DocumentRevisions-V100 | ||
.fseventsd | ||
.Spotlight-V100 | ||
.TemporaryItems | ||
.Trashes | ||
.VolumeIcon.icns | ||
.com.apple.timemachine.donotpresent | ||
|
||
# Directories potentially created on remote AFP share | ||
.AppleDB | ||
.AppleDesktop | ||
Network Trash Folder | ||
Temporary Items | ||
.apdisk | ||
|
||
# End of https://www.gitignore.io/api/osx,node |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"name": "eth-phishing-detect", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "node test" | ||
}, | ||
"author": "", | ||
"license": "ISC", | ||
"dependencies": { | ||
"fast-levenshtein": "^2.0.6" | ||
}, | ||
"devDependencies": { | ||
"tape": "^4.8.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
{ | ||
"whitelist": [ | ||
"metamask.io", | ||
"myetherwallet.com", | ||
"myetheroll.com", | ||
"myetherapi.com", | ||
"ledgerwallet.com" | ||
], | ||
"blacklist": [ | ||
"wallet-ethereum.net", | ||
"myelherwallel.com", | ||
"etherswap.org", | ||
"eos.ac", | ||
"uasfwallet.com", | ||
"ziber.io", | ||
"mvetherwallet.com", | ||
"etherswap.org", | ||
"myethewallet.net", | ||
"multiply-ethereum.info", | ||
"bittrex.comze.com", | ||
"karbon.vacau.com", | ||
"xn--myetherwallt-7db.com", | ||
"xn--myetherwallt-leb.com", | ||
"etherdelta.gitlhub.io", | ||
"etherdelta.glthub.io", | ||
"myethewallet.net", | ||
"myetherwillet.com", | ||
"digitaldevelopersfund.vacau.com", | ||
"myetherwallel.com", | ||
"myeltherwallet.com", | ||
"myelherwallet.com", | ||
"wwwmyetherwallet.com", | ||
"myethermwallet.com", | ||
"district-0x.io", | ||
"coin-dash.com", | ||
"coindash.ru", | ||
"myethervallet.com", | ||
"myetherwallet.com.gl", | ||
"myetherwallet.com.ua", | ||
"myÄ—therwallet.com", | ||
"myetherwallet.com.gl", | ||
"xn--mytherwallet-fvb.com", | ||
"district0x.net", | ||
"aragonproject.io", | ||
"coin-wallet.info", | ||
"coinswallet.info", | ||
"contribute-status.im", | ||
"secure-myetherwallet.com", | ||
"update-myetherwallet.com", | ||
"ether-api.com", | ||
"ether-wall.com", | ||
"mycoinwallet.net", | ||
"etherclassicwallet.com", | ||
"ethereumchamber.com", | ||
"ethereumchamber.net", | ||
"ethereumchest.com", | ||
"myethervvallet.com", | ||
"metherwallet.com", | ||
"mtetherwallet.com", | ||
"my-etherwallet.com", | ||
"my-etherwallet.in", | ||
"myeherwallet.com", | ||
"myetcwallet.com", | ||
"myetehrwallet.com", | ||
"myeterwallet.com", | ||
"myethe.rwallet.com", | ||
"myethereallet.com", | ||
"myetherieumwallet.com", | ||
"myetherswallet.com", | ||
"myetherw.allet.com", | ||
"myetherwal.let.com", | ||
"myetherwalet.com", | ||
"myetherwaliet.com", | ||
"myetherwall.et.com", | ||
"myetherwaller.com", | ||
"myetherwallett.com", | ||
"myetherwaillet.com", | ||
"myetherwalllet.com", | ||
"myetherweb.com.de", | ||
"myethetwallet.com", | ||
"myethewallet.com", | ||
"omg-omise.co", | ||
"omise-go.com", | ||
"tenx-tech.com", | ||
"tokensale-tenx.tech", | ||
"ubiqcoin.org", | ||
"metamask.com" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
const levenshtein = require('fast-levenshtein') | ||
const DEFAULT_TOLERANCE = 4 | ||
|
||
class PhishingDetector { | ||
|
||
constructor (opts) { | ||
this.blacklist = processDomainList(opts.blacklist || []) | ||
this.whitelist = processDomainList(opts.whitelist || []) | ||
this.tolerance = ('tolerance' in opts) ? opts.tolerance : DEFAULT_TOLERANCE | ||
} | ||
|
||
check (domain) { | ||
const source = domainToParts(domain) | ||
|
||
// if source matches whitelist domain (or subdomain thereof), PASS | ||
const whitelistMatch = matchPartsAgainstList(source, this.whitelist) | ||
if (whitelistMatch) return { type: 'whitelist', result: false } | ||
|
||
// if source matches blacklist domain (or subdomain thereof), FAIL | ||
const blacklistMatch = matchPartsAgainstList(source, this.blacklist) | ||
if (blacklistMatch) return { type: 'blacklist', result: true } | ||
|
||
// check if near-match of whitelist domain, FAIL | ||
const fuzzyForm = domainPartsToFuzzyForm(source) | ||
const levenshteinMatched = this.whitelist.find((targetParts) => { | ||
const fuzzyTarget = domainPartsToFuzzyForm(targetParts) | ||
const distance = levenshtein.get(fuzzyForm, fuzzyTarget) | ||
return distance <= this.tolerance | ||
}) | ||
if (levenshteinMatched) { | ||
const match = domainPartsToDomain(levenshteinMatched) | ||
return { type: 'fuzzy', result: true, match } | ||
} | ||
|
||
// matched nothing, PASS | ||
return { type: 'all', result: false } | ||
} | ||
|
||
} | ||
|
||
module.exports = PhishingDetector | ||
|
||
// util | ||
|
||
function processDomainList (list) { | ||
return list.map(domainToParts) | ||
} | ||
|
||
function domainToParts (domain) { | ||
return domain.split('.').reverse() | ||
} | ||
|
||
function domainPartsToDomain(domainParts) { | ||
return domainParts.slice().reverse().join('.') | ||
} | ||
|
||
// for fuzzy search, drop TLD and re-stringify | ||
function domainPartsToFuzzyForm(domainParts) { | ||
return domainParts.slice(1).reverse().join('.') | ||
} | ||
|
||
// match the target parts, ignoring extra subdomains on source | ||
// source: [io, metamask, xyz] | ||
// target: [io, metamask] | ||
// result: PASS | ||
function matchPartsAgainstList(source, list) { | ||
return list.some((target) => { | ||
// target domain has more parts than source, fail | ||
if (target.length > source.length) return false | ||
// source matches target or (is deeper subdomain) | ||
return target.every((part, index) => source[index] === part) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
const PhishingDetector = require('./detector') | ||
const config = require('./config.json') | ||
|
||
const detector = new PhishingDetector(config) | ||
|
||
module.exports = checkDomain | ||
|
||
|
||
function checkDomain(domain) { | ||
return detector.check(domain).result | ||
} |
Oops, something went wrong.