diff --git a/frontend/src/components/Blocks.js b/frontend/src/components/Blocks.js index 36af9d2..fb6d63d 100644 --- a/frontend/src/components/Blocks.js +++ b/frontend/src/components/Blocks.js @@ -1,4 +1,3 @@ -/* eslint-disable no-unused-vars */ import { useState, useEffect } from 'react'; import UserAgentBlock from './UserAgentBlock'; import IntlBlock from './IntlBlock'; @@ -7,10 +6,7 @@ import NavigatorBlock from './NavigatorBlock'; import ScreenBlock from './ScreenBlock'; import FingerprintBlock from './FingerprintBlock'; import LocationBlock from './LocationBlock'; -import HardwareBlock from './HardwareBlock'; -import SoftwareBlock from './SoftwareBlock'; import ConnectionBlock from './ConnectionBlock'; -import FiltersBlock from './FiltersBlock'; // import FontsBlock from './FontsBlock'; import { fetchAPI, getWebWorker } from '../utils/common'; diff --git a/frontend/src/components/ContentList.js b/frontend/src/components/ContentList.js deleted file mode 100644 index 5af1a5b..0000000 --- a/frontend/src/components/ContentList.js +++ /dev/null @@ -1,25 +0,0 @@ -import { ReactComponent as WifiIcon } from '../images/wifi.svg'; -import { ReactComponent as BrowserIcon } from '../images/browser.svg'; -import { ReactComponent as FingerprintIcon } from '../images/fingerprint.svg'; - -const Icons = { - wifi: , - browser: , - fingerprint: , -}; - -const ContentList = ({ items }) => ( -
- {items.map((item) => ( -
-
{Icons[item.icon]}
-
-

{item.title}

-
{item.body}
-
-
- ))} -
-); - -export default ContentList; diff --git a/frontend/src/components/FiltersBlock.js b/frontend/src/components/FiltersBlock.js deleted file mode 100644 index 44ecf52..0000000 --- a/frontend/src/components/FiltersBlock.js +++ /dev/null @@ -1,39 +0,0 @@ -import { useState, useEffect } from 'react'; -import Block from './Block'; -import Table from './Table'; - -const FiltersBlock = () => { - const [adBlockDetected, setAdBlockDetected] = useState(false); - - useEffect(() => { - fetch('https://www3.doubleclick.net', { - method: 'HEAD', - mode: 'no-cors', - cache: 'no-store', - }).catch(() => { - setAdBlockDetected(true); - }); - }, []); - - const data = [ - { - key: 'adBlock', - title: 'Adblock detected', - value: adBlockDetected ? 'True' : 'False', - }, - ]; - - return ( - -

Content Filters

- -

- Explanation: Although content filters like adblock can protect - you against certain methods of tracking, it can also be used as another - identification metric. -

- - ); -}; - -export default FiltersBlock; diff --git a/frontend/src/components/FingerprintBlock2.js b/frontend/src/components/FingerprintBlock2.js deleted file mode 100644 index a67830f..0000000 --- a/frontend/src/components/FingerprintBlock2.js +++ /dev/null @@ -1,61 +0,0 @@ -import { useState } from 'react'; -import Block from './Block'; -import Table from './Table'; -import { - getHardware, - getWebGL, - getSoftware, - getFingerprint, - getHash, - getName, - handleSave, -} from './mainOld'; - -const FingerprintBlock = () => { - const [name, setName] = useState(''); - const [load, setLoad] = useState(false); - const [saved, setSaved] = useState(''); - const hash = getHash([...getHardware(), ...getWebGL(), ...getSoftware()]); - getName(hash, setName, setLoad); - return ( - -

Fingerprint

- {load && ( - <> - {name ? ( -
- ) : ( -
-
{hash}
-
- )} - - )} -

- Explanation: This is a unique identifier that can be used to - follow you around the web. Even if you clear cookies, change your IP or - use private mode the hash will stay the same. Enter your name below and - reload the page in private mode to test it out. -

- {saved ? ( -

Success! Re-scan browser.

- ) : ( - { - handleSave(e, hash, setSaved); - }} - > - - - - )} - - ); -}; - -export default FingerprintBlock; diff --git a/frontend/src/components/HardwareBlock.js b/frontend/src/components/HardwareBlock.js deleted file mode 100644 index bba5bf8..0000000 --- a/frontend/src/components/HardwareBlock.js +++ /dev/null @@ -1,27 +0,0 @@ -import { useState, useEffect } from 'react'; -import Block from './Block'; -import Table from './Table'; -import { getHardware, getWebGL, getBattery } from './mainOld'; - -const HardwareBlock = () => { - const [data, setData] = useState([]); - - useEffect(() => { - getBattery().then((batteryInfo) => { - setData([...getHardware(), ...getWebGL(), ...batteryInfo]); - }); - }, []); - - return ( - -

Hardware

-
-

- Explanation: JavaScript can be used to find information about - your hardware. This information can be used to create a fingerprint. -

- - ); -}; - -export default HardwareBlock; diff --git a/frontend/src/components/OldTable.js b/frontend/src/components/OldTable.js deleted file mode 100644 index cb8c3b4..0000000 --- a/frontend/src/components/OldTable.js +++ /dev/null @@ -1,16 +0,0 @@ -const Table = ({ data }) => ( -
-
- {data.map((item) => ( - - - - - - - ))} -
{item.title}{item.value}
- -); - -export default Table; diff --git a/frontend/src/components/SoftwareBlock.js b/frontend/src/components/SoftwareBlock.js deleted file mode 100644 index 89af4c7..0000000 --- a/frontend/src/components/SoftwareBlock.js +++ /dev/null @@ -1,16 +0,0 @@ -import Block from './Block'; -import Table from './Table'; -import { getSoftware } from './mainOld'; - -const SoftwareBlock = () => ( - -

Software

- -

- Explanation: JavaScript can be used to find information about your - software. This information can be used to create a fingerprint. -

- -); - -export default SoftwareBlock; diff --git a/frontend/src/components/StartBlock.js b/frontend/src/components/StartBlock.js deleted file mode 100644 index 1e720d3..0000000 --- a/frontend/src/components/StartBlock.js +++ /dev/null @@ -1,40 +0,0 @@ -import ContentList from './ContentList'; -import Block from './Block'; - -const contentItems = [ - { - title: 'Fingerprint', - icon: 'fingerprint', - body: 'Browsers reveal bits of identifiable information. This data can be combined into a digital fingerprint which can be used to follow you around the web.', - }, - { - title: 'Connection', - icon: 'wifi', - body: 'Websites are able to access your IP address when you connect to their server. Your IP address exposes information about your connection and location.', - }, - { - title: 'System Info', - icon: 'browser', - body: "JavaScript can be used to find data about your computer's software and hardware. This information can be used to create a fingerprint.", - }, -]; - -const StartBlock = ({ setScan }) => ( - -

About

-
- Vytal shows you what traces your browser leaves behind while surfing the - web. This scan allows you to understand how easy it is to identify and - track your browser even while using private mode. -
- - setScan(true)} - id="scanButton" - value="Scan Browser" - /> -
-); - -export default StartBlock; diff --git a/frontend/src/components/main.js b/frontend/src/components/main.js deleted file mode 100644 index d727c65..0000000 --- a/frontend/src/components/main.js +++ /dev/null @@ -1,277 +0,0 @@ -/* eslint-disable no-unused-vars */ -/* eslint-disable dot-notation */ -// import Bowser from 'bowser'; - -export { - getNavigator, - checkNavigatorProperties, - checkWebWorker, - detectTor, - getIntl, -}; - -const getDeviceMemory = () => ({ - key: 'deviceMemory', - value: navigator.deviceMemory, - issues: [ - checkNavigatorProperties('deviceMemory'), - checkNavigatorValue('deviceMemory'), - checkNavigatorPrototype('deviceMemory'), - ], -}); - -const getHardwareConcurrency = () => ({ - key: 'hardwareConcurrency', - value: navigator.hardwareConcurrency, - issues: [ - checkNavigatorProperties('hardwareConcurrency'), - checkNavigatorValue('hardwareConcurrency'), - checkNavigatorPrototype('hardwareConcurrency'), - ], -}); - -const getMaxTouchPoints = () => ({ - key: 'maxTouchPoints', - value: navigator.maxTouchPoints, - issues: [ - checkNavigatorProperties('maxTouchPoints'), - checkNavigatorValue('maxTouchPoints'), - checkNavigatorPrototype('maxTouchPoints'), - ], -}); - -const getPlatform = () => ({ - key: 'platform', - value: navigator.platform, - issues: [ - checkNavigatorProperties('platform'), - checkNavigatorValue('platform'), - checkNavigatorPrototype('platform'), - ], -}); - -const getUserAgent = () => ({ - key: 'userAgent', - value: navigator.userAgent, - issues: [ - checkNavigatorProperties('userAgent'), - checkNavigatorValue('userAgent'), - checkNavigatorPrototype('userAgent'), - ], -}); - -const getLanguage = () => ({ - key: 'language', - value: navigator.language, - issues: [ - checkNavigatorProperties('language'), - checkNavigatorValue('language'), - checkNavigatorPrototype('language'), - ], -}); - -const getLanguages = () => ({ - key: 'languages', - value: navigator.languages, - issues: [ - checkNavigatorProperties('languages'), - checkNavigatorValue('languages'), - checkNavigatorPrototype('languages'), - ], -}); - -const getCookieEnabled = () => ({ - key: 'cookieEnabled', - value: navigator.cookieEnabled ? 'True' : 'False', - issues: [ - checkNavigatorProperties('cookieEnabled'), - checkNavigatorValue('cookieEnabled'), - checkNavigatorPrototype('cookieEnabled'), - ], -}); - -const getDoNotTrack = () => ({ - key: 'doNotTrack', - value: navigator.doNotTrack ? 'True' : 'False', - issues: [ - checkNavigatorProperties('doNotTrack'), - checkNavigatorValue('doNotTrack'), - checkNavigatorPrototype('doNotTrack'), - ], -}); - -const getWebDriver = () => ({ - key: 'webdriver', - value: navigator.webdriver ? 'True' : 'False', - issues: [ - checkNavigatorProperties('webdriver'), - checkNavigatorValue('webdriver'), - checkNavigatorPrototype('webdriver'), - ], -}); - -const getPlugins = () => ({ - key: 'plugins', - value: sortPlugins(navigator.plugins), - issues: [ - checkNavigatorProperties('plugins'), - checkNavigatorValue('plugins'), - checkNavigatorPrototype('plugins'), - ], -}); - -const getVendor = () => ({ - key: 'vendor', - value: navigator.vendor, - issues: [ - checkNavigatorProperties('vendor'), - checkNavigatorValue('vendor'), - checkNavigatorPrototype('vendor'), - ], -}); - -const getAppVersion = () => ({ - key: 'appVersion', - value: navigator.appVersion, - issues: [ - checkNavigatorProperties('appVersion'), - checkNavigatorValue('appVersion'), - checkNavigatorPrototype('appVersion'), - ], -}); - -const getNavigator = () => [ - getDeviceMemory(), - getHardwareConcurrency(), - getMaxTouchPoints(), - getPlatform(), - getUserAgent(), - getLanguage(), - getLanguages(), - getCookieEnabled(), - getDoNotTrack(), - getWebDriver(), - getPlugins(), - getVendor(), - getAppVersion(), -]; - -// const getDateNow = () => ({ -// key: 'date', -// title: 'Date', -// value: Date.now(), -// issues: [], -// }); - -const getLocale = () => ({ - key: 'locale', - value: Intl.DateTimeFormat().resolvedOptions().locale, - issues: [], -}); - -const getTimezone = () => ({ - key: 'timezone', - value: Intl.DateTimeFormat().resolvedOptions().timeZone, - issues: [], -}); - -const getIntl = () => [getLocale(), getTimezone()]; - -const detectTor = () => { - const date = new Date(); - if ( - navigator.plugins.length === 0 && - date.getTimezoneOffset() === 0 && - window.outerWidth === window.screen.availWidth && - window.outerHeight === window.screen.availHeight - ) { - return true; - } - return false; -}; - -// const getTimezoneOffset = () => ({ -// key: 'timezoneOffset', -// value: new Date().getTimezoneOffset(), -// issues: [], -// }); - -// const getTor = () => ({ -// key: 'tor', -// title: 'Tor browser', -// value: detectTor() ? 'True' : 'False', -// issues: [], -// }); - -// const getAdblock = () => ({ -// key: 'adblock', -// title: 'Adblock', -// value: Promise.resolve(detectAdblock()), -// issues: [], -// }); - -// const detectAdblock = () => -// fetch('https://www3.doubleclick.net', { -// method: 'HEAD', -// mode: 'no-cors', -// cache: 'no-store', -// }); - -// const getOther = () => [getBrave(), getTor(), getAdblock()]; - -// sorts plugins object into comma separated list -const sortPlugins = (data) => { - const { length } = data; - - let list = ''; - for (let i = 0; i < length; i++) { - if (i !== 0) list += ', '; - list += data[i].name; - } - return list; -}; - -const checkNavigatorProperties = (key) => { - if (Object.getOwnPropertyDescriptor(navigator, key) !== undefined) { - return 'Failed undefined properties'; - } - return null; -}; - -const checkNavigatorValue = (key) => { - if ( - Object.getOwnPropertyDescriptor(Navigator.prototype, key).value !== - undefined - ) { - return 'Failed descriptor.value undefined'; - } - return null; -}; - -const checkNavigatorPrototype = (key) => { - try { - // eslint-disable-next-line no-unused-vars - const check = Navigator.prototype[key]; - return 'Failed Navigator.prototype'; - } catch (err) { - // eslint-disable-next-line no-unused-vars - const check = ''; - } - return null; -}; - -const checkWebWorker = (key, setWorkerData) => { - let w; - if (typeof w === 'undefined') { - w = new Worker('/worker.js'); - } - w.postMessage(key); - w.onmessage = (event) => { - if ( - event.data !== undefined && - event.data.toString() !== navigator[key].toString() - ) { - setWorkerData(event.data.toString()); - } - }; -}; diff --git a/frontend/src/components/mainOld.js b/frontend/src/components/mainOld.js deleted file mode 100644 index 33e9d3b..0000000 --- a/frontend/src/components/mainOld.js +++ /dev/null @@ -1,330 +0,0 @@ -import md5 from 'crypto-js/md5'; -import Bowser from 'bowser'; -import axios from 'axios'; - -export { - fetchAPI, - getLocation, - getMap, - getConnection, - getSoftware, - getHardware, - getWebGL, - getBattery, - getFingerprint, - getHash, - getName, - handleSave, -}; - -const fetchAPI = (setData, setDisplay) => { - fetch('https://api.vytal.io/ip/') - .then((response) => response.json()) - .then((json) => { - setData(json); - setDisplay(1); - }) - .catch(() => { - setDisplay(0); - }); -}; - -const getLocation = (json) => { - const data = [ - { - key: 'country', - title: 'Country', - value: json.country, - }, - { - key: 'regionName', - title: 'Region', - value: json.regionName, - }, - { - key: 'lat', - title: 'City', - value: json.city, - }, - { - key: 'zip', - title: 'Zip code', - value: json.zip, - }, - { - key: 'lat', - title: 'Latitude', - value: json.lat, - }, - { - key: 'lon', - title: 'Longitude', - value: json.lon, - }, - ]; - return data; -}; - -const getMap = (data) => - `https://maps.googleapis.com/maps/api/staticmap?center=${data.lat},${data.lon}&markers=color:red%7Clabel:%7C${data.lat},${data.lon}&size=500x200&zoom=10&key=AIzaSyB-YN-X8PGBSPd7NOaQu4csVhgJUnF3ZGk`; - -const getConnection = (json) => { - const data = [ - { - key: 'ipAddress', - title: 'IP address', - value: json.query, - }, - { - key: 'isp', - title: 'ISP', - value: json.isp, - }, - { - key: 'org', - title: 'Organization', - value: json.org, - }, - { - key: 'asn', - title: 'ASN', - value: json.as, - }, - ]; - return data; -}; - -const getHardware = () => { - const data = [ - { - key: 'screenResolution', - title: 'Screen resolution', - value: `${window.screen.width}x${window.screen.height}`, - }, - { - key: 'colorResolution', - title: 'Color Resolution', - value: window.screen.colorDepth, - }, - { - key: 'deviceMemory', - title: 'Device memory', - value: navigator.deviceMemory ? `${navigator.deviceMemory}GB` : 'N/A', - }, - { - key: 'cpuCores', - title: '# of CPU cores', - value: navigator.hardwareConcurrency || 'N/A', - }, - { - key: 'maxTouchpoints', - title: 'Max touchpoints', - value: navigator.maxTouchPoints || 0, - }, - ]; - return data; -}; - -const getBattery = async () => { - let level, status; - if ('getBattery' in navigator) { - await navigator.getBattery().then((res) => { - level = `${Math.round(res.level * 100)}%`; - status = res.charging ? 'Charging' : 'Not charging'; - }); - } else { - level = 'N/A'; - status = 'N/A'; - } - const data = [ - { - key: 'batteryLevel', - title: 'Battery level', - value: level, - }, - { - key: 'batteryStatus', - title: 'Battery status', - value: status, - }, - ]; - return data; -}; - -const getWebGL = () => { - const gl = document.createElement('canvas').getContext('webgl'); - let ext; - if (gl) { - ext = gl.getExtension('WEBGL_debug_renderer_info'); - } else { - ext = null; - } - - const data = [ - { - key: 'webGLVendor', - title: 'WebGL vendor', - value: ext ? gl.getParameter(ext.UNMASKED_VENDOR_WEBGL) : 'N/A', - }, - { - key: 'webglRenderer', - title: 'WebGL renderer', - value: ext ? gl.getParameter(ext.UNMASKED_RENDERER_WEBGL) : 'N/A', - }, - ]; - return data; -}; - -const getSoftware = () => { - const uaResult = Bowser.parse(navigator.userAgent); - const date = new Date(); - const data = [ - { - key: 'browser', - title: 'Browser', - value: uaResult.browser.name, - }, - { - key: 'browserVersion', - title: 'Browser version', - value: uaResult.browser.version, - }, - { - key: 'browserEngine', - title: 'Browser engine', - value: uaResult.browser.engine || 'N/A', - }, - { - key: 'os', - title: 'OS', - value: `${uaResult.os.name} ${uaResult.os.versionName}`, - }, - { - key: 'osVersion', - title: 'OS version', - value: uaResult.os.version, - }, - { - key: 'platform', - title: 'Platform', - value: navigator.platform, - }, - { - key: 'systemType', - title: 'System type', - value: uaResult.platform.type, - }, - { - key: 'userAgent', - title: 'User agent', - value: navigator.userAgent || 'N/A', - }, - { - key: 'preferredLanguage', - title: 'Preferred language', - value: navigator.language || 'N/A', - }, - // { - // key: 'languages', - // title: 'Languages', - // value: sortArr(navigator.languages) || 'N/A', - // }, - { - key: 'timezone', - title: 'Timezone', - value: Intl.DateTimeFormat().resolvedOptions().timeZone || 'N/A', - }, - { - key: 'timezoneOffset', - title: 'Timezone offset', - value: date.getTimezoneOffset() || 'N/A', - }, - { - key: 'cookiesEnabled', - title: 'Cookies enabled', - value: navigator.cookieEnabled ? 'True' : 'False', - }, - { - key: 'javaEnabled', - title: 'Java enabled', - value: navigator.javaEnabled() ? 'True' : 'False', - }, - { - key: 'dntHeader', - title: 'DNT header enabled', - value: navigator.doNotTrack ? 'True' : 'False', - }, - { - key: 'automatedBrowser', - title: 'Automated browser', - value: navigator.webdriver ? 'True' : 'False', - }, - { - key: 'plugins', - title: 'Plugins', - value: sortPlugins(navigator.plugins) || 'N/A', - }, - ]; - return data; -}; - -// sorts array into comma separated list -// const sortArr = (arr) => { -// const arrLength = arr.length; -// let list = ''; -// for (let i = 0; i < arrLength; i++) { -// if (i !== 0) list += ', '; -// list += arr[i]; -// } -// return list; -// }; - -// sorts plugins object into comma separated list -const sortPlugins = (data) => { - const { length } = data; - - let list = ''; - for (let i = 0; i < length; i++) { - if (i !== 0) list += ', '; - list += data[i].name; - } - return list; -}; - -const getFingerprint = (name, hash) => { - const data = [ - { - key: 'name', - title: 'Name', - value: name, - }, - { - key: 'hash', - title: 'Hash', - value: hash, - }, - ]; - return data; -}; - -const getHash = (data) => md5(JSON.stringify(data)).toString(); - -const getName = (hash, setName, setLoad) => { - axios - .get(`https://api.vytal.io/fingerprint/?hash=${hash}`) - .then((response) => { - if (response.data.length !== 0) { - setName(response.data[response.data.length - 1].name); - } - setLoad(true); - }); -}; - -const handleSave = (e, hash, setSaved) => { - e.preventDefault(); - axios.post('https://api.vytal.io/fingerprint/', { - name: e.target[0].value, - hash, - }); - setSaved(true); -};