diff --git a/src/apps.json b/src/apps.json index f1f55f0c9..5f49a4a67 100644 --- a/src/apps.json +++ b/src/apps.json @@ -14,8 +14,8 @@ "1" ], "headers": { - "Set-Cookie": "BITRIX_", - "X-Powered-CMS": "Bitrix Site Manager" + "Set-Cookie": "^BITRIX_", + "X-Powered-CMS": "^Bitrix Site Manager" }, "html": "(?:]+components/bitrix|(?:src|href)=\"/bitrix/(?:js|templates))", "icon": "1C-Bitrix.png", @@ -589,7 +589,7 @@ "22" ], "headers": { - "Server": "Apache-Coyote(/1\\.1)?\\;version:\\1?4.1+:", + "Server": "^Apache-Coyote(/1\\.1)?$\\;version:\\1?4.1+:", "X-Powered-By": "\bTomcat\b(?:-([\\d.]+))?\\;version:\\1" }, "icon": "Apache Tomcat.svg", @@ -1225,7 +1225,7 @@ "1" ], "headers": { - "X-Powered-By": "Dragonfly CMS" + "X-Powered-By": "^Dragonfly CMS" }, "icon": "CPG Dragonfly.png", "implies": "PHP", @@ -1776,7 +1776,7 @@ "1" ], "headers": { - "X-Powered-By": "CppCMS/([\\d.]+)\\;version:\\1" + "X-Powered-By": "^CppCMS/([\\d.]+)$\\;version:\\1" }, "icon": "CppCMS.png", "implies": "C\\+\\+", @@ -1787,8 +1787,8 @@ "1" ], "headers": { - "Set-Cookie": "CraftSessionId=", - "X-Powered-By": "Craft CMS" + "Set-Cookie": "^CraftSessionId=", + "X-Powered-By": "^Craft CMS$" }, "icon": "Craft CMS.svg", "implies": "Yii", @@ -1821,6 +1821,15 @@ "script": "tag\\.crsspxl\\.com/s1\\.js", "website": "http://datadesk.crsspxl.com" }, + "Crypto-Loot": { + "cats": [ + "19" + ], + "env": "^CryptoLoot$", + "script": "^(?:https):?//crypto-loot\\.com/lib/", + "icon": "Crypto-Loot.png", + "website": "https://crypto-loot.com/" + }, "CubeCart": { "cats": [ "6" @@ -2143,12 +2152,12 @@ "8" ], "headers": { - "Set-Cookie": "DokuWiki=" + "Set-Cookie": "^DokuWiki=" }, "icon": "DokuWiki.png", "implies": "PHP", "meta": { - "generator": "DokuWiki( Release [\\-\\d]+)?\\;version:\\1" + "generator": "^DokuWiki( Release [\\-\\d]+)?\\;version:\\1" }, "website": "http://www.dokuwiki.org" }, @@ -2648,7 +2657,7 @@ "18" ], "headers": { - "X-Powered-By": "Fat-Free Framework" + "X-Powered-By": "^Fat-Free Framework$" }, "icon": "Fat-Free Framework.png", "implies": "PHP", @@ -2722,7 +2731,7 @@ "html": "|
]*x:publishsource=\"?Excel\"?)", + "meta": { + "generator": "Microsoft Excel( [\\d.]+)?\\;version:\\1", + "ProgId": "^Excel\\." + }, + "website": "https://office.microsoft.com/excel" + }, "Microsoft SharePoint": { "cats": [ "1" @@ -5246,6 +5276,18 @@ }, "website": "http://sharepoint.microsoft.com" }, + "Microsoft Word": { + "cats": [ + "20" + ], + "icon": "Microsoft Word.svg", + "html": "(?:]*xmlns:w=\"urn:schemas-microsoft-com:office:word\"||
]*class=\"?WordSection1[\" >]|]*>[^>]*@page WordSection1)", + "meta": { + "generator": "Microsoft Word( [\\d.]+)?\\;version:\\1", + "ProgId": "^Word\\." + }, + "website": "https://office.microsoft.com/word" + }, "Mietshop": { "cats": [ "6" @@ -5373,7 +5415,8 @@ "18" ], "headers": { - "x-powered-by": "mojolicious" + "x-powered-by": "mojolicious", + "server": "^mojolicious" }, "icon": "Mojolicious.png", "implies": "Perl", @@ -5747,7 +5790,7 @@ "env": "^Nette$", "headers": { "Set-Cookie": "nette-browser=", - "X-Powered-By": "Nette Framework" + "X-Powered-By": "^Nette Framework" }, "html": [ "]+data-nette-rules", @@ -6235,8 +6278,8 @@ ], "headers": { "Server": "php/?([\\d.]+)?\\;version:\\1", - "Set-Cookie": "PHPSESSID", - "X-Powered-By": "php/?([\\d.]+)?\\;version:\\1" + "Set-Cookie": "^PHPSESSID", + "X-Powered-By": "^php/?([\\d.]+)?\\;version:\\1" }, "icon": "PHP.svg", "url": "\\.php(?:$|\\?)", @@ -6454,7 +6497,7 @@ "18" ], "headers": { - "X-Powered-By": "pimcore" + "X-Powered-By": "^pimcore$" }, "icon": "pimcore.svg", "implies": "PHP", @@ -6675,6 +6718,15 @@ "script": "^https?://(?:www\\.)?projectwonderful\\.com/(?:pwa\\.js|gen\\.php)", "website": "http://projectwonderful.com" }, + "ProjectPoi": { + "cats": [ + "19" + ], + "env": "^ProjectPoi$", + "script": "^(?:https):?//ppoi\\.org/lib/", + "icon": "ProjectPoi.png", + "website": "https://ppoi.org/" + }, "Prospector": { "cats": [ "36" diff --git a/src/drivers/bookmarklet/driver.js b/src/drivers/bookmarklet/driver.js index 5418ddbbc..1bcb3783c 100644 --- a/src/drivers/bookmarklet/driver.js +++ b/src/drivers/bookmarklet/driver.js @@ -18,8 +18,8 @@ console.log('[wappalyzer ' + type + ']', '[' + source + ']', message); }; - function getEnvironmentVars() { - wappalyzer.log('func: getEnvironmentVars'); + function getPageContent() { + wappalyzer.log('func: getPageContent'); var env = []; @@ -27,9 +27,15 @@ env.push(i); } + var scripts = Array.prototype.slice + .apply(document.scripts) + .filter(s => s.src) + .map(s => s.src); + wappalyzer.analyze(domain, url, { html: document.documentElement.innerHTML, - env: env + env: env, + scripts: scripts }); } @@ -56,7 +62,10 @@ name = line.substring(0, line.indexOf(': ')); value = line.substring(line.indexOf(': ') + 2, line.length - 1); - responseHeaders[name.toLowerCase()] = value; + if ( !responseHeaders[name.toLowerCase()] ){ + responseHeaders[name.toLowerCase()] = [] + } + responseHeaders[name.toLowerCase()].push(value); } }); @@ -139,6 +148,6 @@ return string.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/--+/g, '-').replace(/(?:^-|-$)/, ''); } - getEnvironmentVars(); + getPageContent(); getResponseHeaders(); })(); diff --git a/src/drivers/npm/driver.js b/src/drivers/npm/driver.js index c845a52a0..2c3913f75 100644 --- a/src/drivers/npm/driver.js +++ b/src/drivers/npm/driver.js @@ -72,18 +72,26 @@ const driver = options => { const headers = {}; browser.resources['0'].response.headers._headers.forEach(header => { - headers[header[0]] = header[1]; + if ( !headers[header[0]] ){ + headers[header[0]] = []; + } + headers[header[0]].push(header[1]); }); const vars = Object.getOwnPropertyNames(browser.window); const html = browser.html(); + const scripts = Array.prototype.slice + .apply(browser.document.scripts) + .filter(s => s.src) + .map(s => s.src); - const hostname = wappalyzer.parseUrl(url).hostname; + const hostname = wappalyzer.parseUrl(url).hostname; wappalyzer.analyze(hostname, url, { headers, html, - env: vars + env: vars, + scripts }); }); }); diff --git a/src/drivers/webextension/js/content.js b/src/drivers/webextension/js/content.js index c4e1940b0..7ad284495 100644 --- a/src/drivers/webextension/js/content.js +++ b/src/drivers/webextension/js/content.js @@ -7,6 +7,11 @@ if ( typeof browser !== 'undefined' && typeof document.body !== 'undefined' ) { html = html.substring(0, 25000) + html.substring(html.length - 25000, html.length); } + var scripts = Array.prototype.slice + .apply(document.scripts) + .filter(s => s.src) + .map(s => s.src); + try { browser.runtime.sendMessage({ id: 'analyze', @@ -14,6 +19,12 @@ if ( typeof browser !== 'undefined' && typeof document.body !== 'undefined' ) { source: 'content.js' }); + browser.runtime.sendMessage({ + id: 'analyze', + subject: { scripts }, + source: 'content.js' + }); + var container = document.createElement('wappalyzerData'); container.setAttribute('id', 'wappalyzerData'); diff --git a/src/drivers/webextension/js/driver.js b/src/drivers/webextension/js/driver.js index a0fac8fff..4b9a40dc6 100644 --- a/src/drivers/webextension/js/driver.js +++ b/src/drivers/webextension/js/driver.js @@ -138,20 +138,23 @@ browser.webRequest.onCompleted.addListener(request => { var url = wappalyzer.parseUrl(request.url); request.responseHeaders.forEach(function(header) { - responseHeaders[header.name.toLowerCase()] = header.value || '' + header.binaryValue; + if ( !responseHeaders[header.name.toLowerCase()] ) { + responseHeaders[header.name.toLowerCase()] = [] + } + responseHeaders[header.name.toLowerCase()].push(header.value || '' + header.binaryValue); }); if ( headersCache.length > 50 ) { headersCache = {}; } - if ( /text\/html/.test(responseHeaders['content-type']) ) { + if ( /text\/html/.test(responseHeaders['content-type'][0]) ) { if ( headersCache[url.canonical] === undefined ) { headersCache[url.canonical] = {}; } Object.keys(responseHeaders).forEach(header => { - headersCache[url.canonical][header] = responseHeaders[header]; + headersCache[url.canonical][header] = responseHeaders[header].slice(); }); } } diff --git a/src/icons/Crypto-Loot.png b/src/icons/Crypto-Loot.png new file mode 100644 index 000000000..4bcd3b9b3 Binary files /dev/null and b/src/icons/Crypto-Loot.png differ diff --git a/src/icons/JSEcoin.png b/src/icons/JSEcoin.png new file mode 100644 index 000000000..9c7d398a2 Binary files /dev/null and b/src/icons/JSEcoin.png differ diff --git a/src/icons/Microsoft Excel.svg b/src/icons/Microsoft Excel.svg new file mode 100644 index 000000000..9c912bb4e --- /dev/null +++ b/src/icons/Microsoft Excel.svg @@ -0,0 +1,22 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/icons/Microsoft Word.svg b/src/icons/Microsoft Word.svg new file mode 100644 index 000000000..626051757 --- /dev/null +++ b/src/icons/Microsoft Word.svg @@ -0,0 +1,19 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/icons/ProjectPoi.png b/src/icons/ProjectPoi.png new file mode 100644 index 000000000..65bfdff62 Binary files /dev/null and b/src/icons/ProjectPoi.png differ diff --git a/src/wappalyzer.js b/src/wappalyzer.js index 624e667a5..9936e6b9e 100644 --- a/src/wappalyzer.js +++ b/src/wappalyzer.js @@ -62,10 +62,13 @@ class Wappalyzer { if ( data.html ) { this.analyzeHtml(app, data.html); - this.analyzeScript(app, data.html); this.analyzeMeta(app, data.html); } + if ( data.scripts ) { + this.analyzeScripts(app, data.scripts); + } + if ( data.headers ) { this.analyzeHeaders(app, data.headers); } @@ -396,19 +399,18 @@ class Wappalyzer { /** * Analyze script tag */ - analyzeScript(app, html) { - var regex = new RegExp(']+src=("|\')([^"\']+)', 'ig'); + analyzeScripts(app, scripts) { var patterns = this.parsePatterns(app.props.script); if ( patterns.length ) { patterns.forEach(pattern => { var match; - while ( ( match = regex.exec(html) ) ) { - if ( pattern.regex.test(match[2]) ) { - this.addDetected(app, pattern, 'script', match[2]); + scripts.forEach(uri => { + if ( pattern.regex.test(uri) ) { + this.addDetected(app, pattern, 'script', uri); } - } + }); }); } } @@ -444,12 +446,16 @@ class Wappalyzer { var patterns = this.parsePatterns(app.props.headers); if ( headers ) { - Object.keys(patterns).forEach(header => { - patterns[header].forEach(pattern => { - header = header.toLowerCase(); - - if ( header in headers && pattern.regex.test(headers[header]) ) { - this.addDetected(app, pattern, 'headers', headers[header], header); + Object.keys(patterns).forEach(headerName => { + patterns[headerName].forEach(pattern => { + headerName = headerName.toLowerCase(); + + if ( headerName in headers ) { + headers[headerName].forEach(headerValue => { + if ( pattern.regex.test(headerValue) ) { + this.addDetected(app, pattern, 'headers', headerValue, headerName); + } + }); } }); });