├── logo.png ├── README.md ├── test1.html ├── test2.html ├── fuzzer.js ├── PMHook.js ├── replay.html └── logger.html /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehgdotnet/postmessagehook/HEAD/logo.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # postmessagehook 2 | by Gary O'Leary-Steele | cloned from https://sentinel.appcheck-ng.com/static/pm/logger.html 3 | -------------------------------------------------------------------------------- /test1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /test2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /fuzzer.js: -------------------------------------------------------------------------------- 1 | function fuzz_json(data, fuzz_func){ 2 | /* 3 | Unpacks a JSON object and applies the callback to 4 | each property. 5 | 6 | The callback is passed the current value and should return the new 7 | value. 8 | 9 | Args: 10 | data: Object to fuzz 11 | fuzz_func: fuzzed function to apply to data 12 | 13 | */ 14 | //console.log("Fuzzing json"); 15 | var fuzzed_objects = []; 16 | for(var key in data) { 17 | 18 | // Ensure we only deal with fuzzable props not builtins 19 | if(data.hasOwnProperty(key)) { 20 | // If its not an object send to simple fuzzer to apply callback 21 | if(typeof data[key] != "object"){ 22 | 23 | // Obtain an array of fuzzed objects 24 | fuzzed = simple_fuzz(data[key],fuzz_func); 25 | 26 | // copy the object and insert fuzzed values. 27 | for(c=0;c < fuzzed.length; c++){ 28 | // Make copy 29 | var copy = JSON.parse(JSON.stringify(data)); 30 | // apply fuzzed value 31 | copy[key] = fuzzed[c]; 32 | fuzzed_objects.push(copy); 33 | } 34 | 35 | }else{ 36 | // Make a copy of the original so that the 37 | // nested elements we pass in dont get changed in the original 38 | //var copy = JSON.parse(JSON.stringify(data)); 39 | //var unpacked_nested_object = fuzz_json(copy[key],fuzz_func); 40 | 41 | // Here we use recursion to unpack to the point we can apply the fuzzer. 42 | // then we unpack these and add them to the return value 43 | var unpacked_nested_object = fuzz_json(data[key],fuzz_func) 44 | //console.log(unpacked_nested_object); 45 | for(var u=0,l=unpacked_nested_object.length; u 1 && data.split("{").length == data.split("{").length){ 139 | 140 | // assuming that the part after the first { is JSON 141 | 142 | // Only deals with 1 JSON struct!! should improve this to get them all 143 | var start_json = data.indexOf("{") 144 | var end_json = data.lastIndexOf("}") 145 | 146 | var prefix = data.slice(0, start_json) 147 | var json_part = data.slice(start_json, end_json + 1) 148 | var suffix = data.slice(end_json + 1) 149 | //console.log(prefix) 150 | //console.log(json_part) 151 | //console.log(suffix) 152 | 153 | json_part_fuzzed= do_simple_fuzz(JSON.parse(json_part), fuzz_func) 154 | for(var i=0,l=json_part_fuzzed.length; i= 0) ? (indexOf + (startpos || 0)) : indexOf; 189 | } 190 | 191 | String.prototype.regexLastIndexOf = function(regex, startpos) { 192 | regex = (regex.global) ? regex : new RegExp(regex.source, "g" + (regex.ignoreCase ? "i" : "") + (regex.multiLine ? "m" : "")); 193 | if(typeof (startpos) == "undefined") { 194 | startpos = this.length; 195 | } else if(startpos < 0) { 196 | startpos = 0; 197 | } 198 | var stringToWorkWith = this.substring(0, startpos + 1); 199 | var lastIndexOf = -1; 200 | var nextStop = 0; 201 | while((result = regex.exec(stringToWorkWith)) != null) { 202 | lastIndexOf = result.index; 203 | regex.lastIndex = ++nextStop; 204 | } 205 | return lastIndexOf; 206 | } 207 | 208 | function dedupe_array(a) { 209 | var seen = {}; 210 | var out = []; 211 | var len = a.length; 212 | var j = 0; 213 | for(var i = 0; i < len; i++) { 214 | var item = a[i]; 215 | if(seen[item] !== 1) { 216 | seen[item] = 1; 217 | out[j++] = item; 218 | } 219 | } 220 | return out; 221 | } 222 | 223 | 224 | var fuzz_count = 0 225 | function default_fuzz_callback(data){ 226 | 227 | // test to see if the value looks like a URL. 228 | 229 | //var tag_payload = "" 230 | 231 | /* 232 | Perhaps we can just prepend the javascript: proto handler to all payloads. Shouldn't harm 233 | innerHTML injections etc. 234 | 235 | Note: when triggering navigation events we are likely to navigate the page away from the vulnerable code 236 | therefore we should reload the page on each iteration. 237 | 238 | */ 239 | //var tag_payload = "" 240 | var tag_payload = " '\" onerror='top.alert(" +fuzz_count + ")//' onload='top.alert(" +fuzz_count + ")//' " 241 | 242 | 243 | url_regex = /https*:\/\//i 244 | var payload; 245 | 246 | if(typeof data == "string" && data.regexIndexOf(url_regex,0) > -1){ 247 | 248 | url_index = data.regexIndexOf(url_regex,0) 249 | 250 | payload = "javascript:top.alert(" + fuzz_count + ")//" + tag_payload; 251 | //insert the js uri handler just before the legit url 252 | payload = [data.slice(0, url_index), payload , data.slice(url_index)].join(''); 253 | }else{ 254 | payload = data + tag_payload 255 | } 256 | 257 | fuzzed = payload; 258 | fuzz_count = fuzz_count + 1; 259 | return fuzzed 260 | } 261 | 262 | 263 | function delimfuzz(data, delim, cb){ 264 | var parts = data.split(delim); 265 | var fuzzed = []; 266 | 267 | if (parts.length ===1){ 268 | return; 269 | } 270 | 271 | for(var i=0,l=parts.length; i"; 302 | } 303 | //out = fuzz_json(data,mod_callback) 304 | 305 | out = simple_fuzz(data,mod_callback) 306 | 307 | for(i=0; i< out.length;i++){ 308 | console.warn(JSON.stringify(out[i])); 309 | } 310 | 311 | } -------------------------------------------------------------------------------- /PMHook.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name postmessagehook 3 | // @namespace http://tampermonkey.net/ 4 | // @version 1.0 5 | // @run-at document-start 6 | // @description PostMessage logger for security testing 7 | // @author Gary O'Leary-Steele 8 | // @match http*://*/* 9 | // @grant none 10 | // ==/UserScript== 11 | 12 | (function() { 13 | 14 | /* 15 | Fiddler rule to inject hook 16 | 17 | static function OnBeforeResponse(oSession: Session) { 18 | if (m_Hide304s && oSession.responseCode == 304) { 19 | oSession["ui-hide"] = "true"; 20 | } 21 | 22 | //is it a html-response and is it from stackoverflow.com 23 | if (oSession.oResponse.headers.ExistsAndContains("Content-Type", "html")) { 24 | 25 | // Remove any compression or chunking 26 | oSession.utilDecodeResponse(); 27 | 28 | var oBody = System.Text.Encoding.UTF8.GetString(oSession.responseBodyBytes); 29 | 30 | oSession.oResponse.headers.Remove("Content-Security-Policy"); 31 | oSession.oResponse.headers.Remove("X-Content-Security-Policy"); 32 | oSession.oResponse.headers.Remove("X-WebKit-CSP"); 33 | 34 | var hook = '' 35 | oBody = hook + oBody 36 | // Set the response body to the changed body string 37 | oSession.utilSetResponseBody(oBody); 38 | } 39 | 40 | 41 | } 42 | 43 | 44 | */ 45 | var url = "https://sentinel.appcheck-ng.com/static/pm/logger.html"; 46 | var id = "appcheck_postmessage_logging_frame"; 47 | var do_not_hook = "sentinel.appcheck-ng.com"; 48 | 49 | (function(funcName, baseObj) { 50 | funcName = funcName || "docReady"; 51 | baseObj = baseObj || window; 52 | var readyList = []; 53 | var readyFired = false; 54 | var readyEventHandlersInstalled = false; 55 | 56 | function ready() { 57 | if (!readyFired) { 58 | readyFired = true; 59 | for (var i = 0; i < readyList.length; i++) { 60 | readyList[i].fn.call(window, readyList[i].ctx); 61 | } 62 | readyList = []; 63 | } 64 | } 65 | 66 | function readyStateChange() { 67 | if ( document.readyState === "complete" ) { 68 | ready(); 69 | } 70 | } 71 | 72 | baseObj[funcName] = function(callback, context) { 73 | if (readyFired) { 74 | setTimeout(function() {callback(context);}, 1); 75 | return; 76 | } else { 77 | readyList.push({fn: callback, ctx: context}); 78 | } 79 | if (document.readyState === "complete") { 80 | setTimeout(ready, 1); 81 | } else if (!readyEventHandlersInstalled) { 82 | if (document.addEventListener) { 83 | document.addEventListener("DOMContentLoaded", ready, false); 84 | window.addEventListener("load", ready, false); 85 | } else { 86 | document.attachEvent("onreadystatechange", readyStateChange); 87 | window.attachEvent("onload", ready); 88 | } 89 | readyEventHandlersInstalled = true; 90 | } 91 | }; 92 | })("docReady", window); 93 | 94 | // http://blakeembrey.com/articles/2014/01/wrapping-javascript-functions/ 95 | var before = function (before, fn) { 96 | return function () { 97 | try{ 98 | before.apply(this, arguments); 99 | }catch(e){ 100 | console.error(e); 101 | } 102 | return fn.apply(this, arguments); 103 | }; 104 | }; 105 | 106 | // message listener to determine when the logger frame is ready 107 | var logger_iframe_ready = false; 108 | function iframe_is_ready(event){ 109 | 110 | try{ 111 | if (event.data == "logger_iframe_ready"){ 112 | console.log("logger iframe ready"); 113 | logger_iframe_ready = true; 114 | 115 | // if we have any in the queue then send the messages. 116 | if(logger_queue.length > 0) { 117 | for(var i=0,l=logger_queue.length; i 2 | 3 | 4 | 5 | PostMessage Tester 6 | 7 | 235 | 236 | 237 |

postMessage Fuzzer

238 |
Uh oh! Your browser does not support the following required technologies:
239 |
240 |
241 |
242 | URL: 243 |

244 | 245 | 246 | 247 |
248 | 249 |

250 | 251 |
252 | Message: 253 |

254 | 255 | 256 | 257 | 258 |
259 | 260 |
261 | 274 |
275 | 276 |
277 | 283 |
284 |
285 | 286 |
287 |

288 |                 
289 | 290 |
291 |

292 |                 
293 |
294 |
<html>
295 | <body>
296 | 
297 | </body>
298 | <script>
299 | 
300 |
301 | </script> 302 | </html>
303 | As data URI: 304 |

305 |                 
306 |
307 |
308 |
309 | 310 | 311 | 312 | 313 | 492 | 493 | 494 | -------------------------------------------------------------------------------- /logger.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 184 | 591 | Download PMHook.js  Open Replay Tool 592 |

Message Event Handler Log

593 | 594 | 595 | Filter URLs (regex): 596 | 597 | 598 | 608 | 609 |
610 | 611 | 612 |
613 | 614 | 615 | 616 | 617 | 618 | --------------------------------------------------------------------------------